Browse documentation

Pharos / Docs / v1.0.1

Install on cPanel, DirectAdmin, Plesk or compatible PHP hosting

Updated 2026-10-22 · Pharos 1.0.1

Three ways in, one result: the application lives outside the web root, only its public files are served by the web server, and one cron line runs every minute. Pick the way that fits your host: no SSH, SSH, or by hand. Prefer containers? Skip to Docker. Every path downloads the same signed release: the installer verifies the Ed25519 manifest and the SHA-256 before it unpacks a single file.

Plesk is documented, not verified. cPanel and DirectAdmin are verified on live hosts. The Plesk steps on this page are written down, but they have not been run on a live Plesk server yet. Try them on a test domain first, and see the Plesk procedure below.

A. Without SSH: the web installer (cPanel, DirectAdmin, Plesk)

Download the installer

One PHP file you upload next to your site. It checks the server, downloads the signed release, verifies it, sets up the database and shows the one cron line, then removes itself. It walks through seven steps: Unlock, Check the server, Download, Configure, Scheduler, and then Your account and Done inside Pharos. Each step also works without JavaScript; with it, long steps show live progress.

  1. Download pharos-install.php and upload it into the document root of the domain you want the status page on: File Manager, then public_html or the subdomain's folder.
  2. Unlock. Open https://status.example.com/pharos-install.php and unlock it with the private installation key from the file shown on screen, using your hosting File Manager. Keep this key for the account step.
  3. Check the server. PHP 8.3+, extensions, writable folders and access to the release server, grouped with a fix for cPanel, DirectAdmin and Plesk where something is missing. Nothing is written yet.
  4. Download fetches the release, checks the signed manifest and the checksum, unpacks the application into a private pharos-app-<domain-id> folder next to the web root, never inside it, and copies public/ into the document root with an index.php that points at the app. No document root change is needed, and .env is never reachable from the web.
  5. Configure asks for the site address, detected from the page, and the database: SQLite is recommended and needs nothing from your host; MySQL or MariaDB has a Test connection button. Save settings and set up the database writes .env with a fresh key and runs the migrations.
  6. Scheduler shows the one line with the right PHP binary for your host. Add it under Cron Jobs (cPanel, DirectAdmin) or Scheduled Tasks (Plesk); the screen turns green by itself on the first run. It also shows your installation key once more, with a Copy button. Continue to your account deletes the installer file and opens step 6 in Pharos.
  7. Your account and Done happen in Pharos. Step 6: paste the installation key, name the status page, pick the time zone and create your administrator with Create my account and finish. Step 7 shows the version, address, database and scheduler state, and opens Pharos.

The installer keeps whatever your panel already put in .htaccess (PHP handler, ini blocks) and adds Pharos's rules underneath, including DirectoryIndex index.php so a placeholder index.html from the panel does not shadow the page. A half-finished install resumes where it stopped; a finished one refuses to run twice.

Step 1 of 7 of the web installer: where to find the private installation key, with a Copy path button, and the field to paste it.
Step 1, Unlock. Open the file shown on screen in your hosting File Manager and paste its key. You paste the same key once more when you create your account.
Step 2 of 7, the server check: all 17 checks passed for PHP, the folders, the extensions, the release server and PHP for cron.
Step 2, Check the server. PHP, extensions, folders, the release server and PHP for cron in one view. Nothing is written yet; fix what is red, then press Download the release.
Step 3 of 7, the download: the signed release fetched, signature and checksum verified, every file unpacked and the public folder copied.
Step 3, Download. Signature, checksum and unpack each confirmed. The app went to a private pharos-app-<domain-id> folder, public/ into the web folder.
Step 4 of 7, configure: the site address detected from the page, SQLite recommended or MySQL or MariaDB, and the button Save settings and set up the database.
Step 4, Configure. The site address and the database. SQLite is one file next to the app; MySQL or MariaDB suits hosts where you already manage databases. Save settings and set up the database takes a few seconds.
Step 5 of 7, the scheduler: one cron line with a Copy button, a confirmation that the scheduler ran, where to add it in cPanel, DirectAdmin and Plesk, and the installation key to copy.
Step 5, Scheduler. The one cron line, with the PHP binary that matches the version the installer found, and where to add it in your panel. The first run is confirmed by itself. Continue to your account deletes the installer and opens step 6 in Pharos.

B. With SSH: one command

curl -fsSL https://pharos.solutionmax.net/get | sh -s -- --php --url https://status.example.com

The script reads the machine (PHP version and extensions), verifies the manifest and the archive, unpacks into a private pharos-app-<domain-id> folder (change it with --dir), writes .env, migrates, links storage and adds the cron line to your crontab with the PHP binary pinned to the version it found. Where it cannot write the crontab (DirectAdmin's jailed shell, for one), it prints the line for you to add in the panel. Read it first if you like: curl -fsSL https://pharos.solutionmax.net/get | less.

Then point the document root at ~/pharos-app/public. Unlike the web installer, the script does not touch your web folder. This is the one step it leaves to you:

  • cPanel: Domains → Manage → Document Root. Over SSH, for a subdomain: uapi SubDomain changedocroot domain=status.example.com docroot=pharos-app/public.
  • DirectAdmin: Domain Setup if your host lets you set a document root. Most do not for user accounts; then replace the web folder with a link, which DirectAdmin's Apache follows: cd ~/domains/status.example.com && mv public_html public_html.orig && ln -s ~/pharos-app/public public_html
  • Plesk: Hosting Settings → Document root → pharos-app/public.
  • Your own server: an nginx or Apache vhost with its root at /home/you/pharos-app/public, PHP-FPM 8.3, and every unknown path rewritten to index.php; the .htaccess in public/ does that on Apache.

Apache and LiteSpeed pick the new root up within a minute. Open the site: the setup form appears. Never set the document root to a private pharos-app-<domain-id> folder itself: that exposes your .env.

Updating is the same command again: the script hands over to Pharos's own updater, which backs the current version up first. The Updates screen in the admin does the same with a button.

A terminal running the get script: system detected, manifest signature valid, PHP checked, archive downloaded and verified, unpacked, installation key shown, database migrated, cron task configured, then the document root instructions per panel.
The SSH route, start to finish. Same release, same checks; the last lines are the document root step for your panel.
Step 6 of 7, inside Pharos: installation key, status page name, time zone, your name, email and password, and the button Create my account and finish.
Step 6, Your account. Either way it ends here. Paste the installation key, name the status page, pick the time zone and create the first administrator. This screen disappears the moment the account exists; step 7, Done, opens Pharos.

Installing a specific version

Both installers take the newest release from /releases/latest.json unless you pin one, to reproduce something, or to walk through an update yourself:

curl -fsSL https://pharos.solutionmax.net/get | sh -s -- --php --url https://status.example.com --version 1.0.1
https://status.example.com/pharos-install.php?version=1.0.1

A pinned install reads pharos-<version>.json, the manifest signed for that exact release; a version that was never published fails cleanly. Each release on the releases page also carries its own pre-pinned copy of the web installer, pharos-install-<version>.php, for when a query string is awkward. Afterwards the Updates screen offers the newest release as usual. Pharos never downgrades on its own: to go back, use Roll back under Updates, restore a verified backup. The get --version option is for new installations and refuses to overwrite an existing PHP install.

C. By hand

If you would rather not run either installer, it is a standard PHP 8.3 application:

git clone https://github.com/solutionmax/pharos.git ~/pharos && cd ~/pharos
composer install --no-dev --optimize-autoloader
cp .env.example .env && php artisan key:generate
touch database/database.sqlite && chmod -R 775 storage bootstrap/cache database
php artisan migrate --force && php artisan storage:link
php artisan config:cache && php artisan route:cache && php artisan view:cache

Set at least APP_ENV=production, APP_DEBUG=false, APP_URL and DB_CONNECTION=sqlite in .env, point the document root at ~/pharos/public as in B, and add the cron line below. Run php artisan optimize:clear after any .env change.

SQLite needs a writable directory, not just a writable file. It writes its journal next to the database, so permissions on the folder matter as much as on the file itself.

The first browser visit shows the setup form. From the command line instead: php artisan pharos:user [email protected] --name="Your Name" prints a generated password once, updates an existing account rather than failing, and is also how you get back in if you lock yourself out.

Plesk: the documented procedure

This is the procedure for Plesk as it is written down for 1.0. It has not been verified on a live Plesk server, so read it as steps to test, not as a tested route.

  1. Select PHP 8.3 or later for the domain. Enable cURL, mbstring, OpenSSL, sodium, PDO SQLite (or PDO MySQL), XML and DOM, fileinfo, GD and ZIP.
  2. Unpack the release zip from the releases page into pharos-app/ under the site's own system user, then set Hosting Settings → Document root to pharos-app/public.
  3. Copy .env.example to .env. Set the HTTPS address of the site, APP_DEBUG=false and the database. Then run, as that site's user:
    php artisan key:generate --force
    php artisan migrate --force
    php artisan storage:link
  4. Give that user write access to storage/ and bootstrap/cache/. Do not use world writable permissions. Nothing outside public/ may be reachable from a browser: not .env, not vendor/, not the database.
  5. Add a Scheduled Task that runs every minute as the site user:
    /opt/plesk/php/8.3/bin/php /var/www/vhosts/example.com/pharos-app/artisan schedule:run
  6. Finish the account setup in the browser. Then prove the basics on that host: an HTTP check, a confirmation mail that arrives, a maintenance window, a backup, an update and a rollback. Check that the scheduler's last run is current.

The documented rollback is the same as on other PHP hosts: restore the files and the database that belong together. See Updates. It has not been verified on a live Plesk server either.

The one cron line

Everything time-based hangs off one scheduled command. Both installers give you the exact line; by hand, add a job that runs every minute (cPanel Cron Jobs, DirectAdmin Cron Jobs, Plesk Scheduled Tasks). In the panel's form the five stars go in the time fields and the rest in the command field:

* * * * * cd /home/you/pharos-app && php artisan schedule:run >/dev/null 2>&1

If your host's default php is not 8.3, use the full path to the 8.3 binary. cPanel exposes it as /opt/cpanel/ea-php83/root/usr/bin/php or /opt/alt/php83/usr/bin/php, and DirectAdmin as /usr/local/php83/bin/php. The documented path for Plesk is /opt/plesk/php/8.3/bin/php; like the rest of the Plesk steps it has not been verified on a live Plesk server. Pharos shows a warning in the admin until it sees the first run; verify by hand with php artisan pharos:check --force.

With SSH you do not have to type the line yourself. Run these from the application folder:

php artisan pharos:cron            # print the line for this install
php artisan pharos:cron --install  # add it to this user's crontab, other tasks stay

That one line drives everything Pharos does on a clock:

WhenWhat runs
Every minuteDue checks, uptime for services that are reported from outside, maintenance windows, subscriber mail, outgoing notifications, and the worker for a probe location when this install is one.
Daily, 02:45 UTCRemote backups, when a destination is set.
DailyPruning: the audit log, raw check results, and probe results.

No cron on your host at all? An outside service can call Pharos over HTTPS every minute. See Web cron. Real cron stays the better choice wherever you have it.