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)
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.
- Download pharos-install.php and upload it into the document root of the domain you want the status page on: File Manager, then
public_htmlor the subdomain's folder. - Unlock. Open
https://status.example.com/pharos-install.phpand 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. - 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.
- 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 copiespublic/into the document root with anindex.phpthat points at the app. No document root change is needed, and.envis never reachable from the web. - 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
.envwith a fresh key and runs the migrations. - 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.
- 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.
pharos-app-<domain-id> folder, public/ into the web folder.
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 toindex.php; the.htaccessinpublic/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.
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.
- 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.
- Unpack the release zip from the releases page into
pharos-app/under the site's own system user, then set Hosting Settings → Document root topharos-app/public. - Copy
.env.exampleto.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
- Give that user write access to
storage/andbootstrap/cache/. Do not use world writable permissions. Nothing outsidepublic/may be reachable from a browser: not.env, notvendor/, not the database. - 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
- 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:
| When | What runs |
|---|---|
| Every minute | Due 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 UTC | Remote backups, when a destination is set. |
| Daily | Pruning: 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.