Provider-specific integration fields, examples and setup guides, with separate incoming monitoring and outgoing notification flows.
Interactive n8n and Uptime Kuma instructions with component-specific URLs, valid incident examples and copy controls.
Account password recovery using one-time, expiring email links, rate limits, generic request responses and unchanged two-factor requirements. Resetting a password invalidates old remembered logins and authenticated sessions.
Shared, clearly highlighted section navigation for Settings and Mail templates.
Accessible, colour-coded status choices for reporting incidents and posting updates.
Locally bundled WYSIWYG editor with Markdown mode and a plain-text fallback. Messages remain Markdown in storage and notifications.
Incident cards with the latest update, affected components, visibility, source and repeat counts.
Service availability bars with day tooltips and measured uptime, plus visible component bars on mobile.
Public status refresh every 30 seconds while the tab is visible. Real changes trigger a dismissible notification and a brief highlight, respecting reduced-motion preferences.
Connection-loss feedback and automatic retry without discarding the last loaded status.
Changed
Service bars, percentages and status labels align in a fixed area on the right. Expanded component bars use the same height, spacing and 30-day display as their service; percentages still cover 90 days.
The visual editor and formatting toolbar use more compact dimensions.
The displayed incident status Watching is now Monitoring. The stored value 3 and the existing Watching API name remain compatible; Monitoring is accepted as an alias.
Saved-action notifications appear at the bottom right. Delivery success is never inferred from an update being posted.
Incident timelines and status headers use the existing status colours in light and dark themes.
Fonts are self-hosted, and editor usage statistics are disabled.
Fixed
Editor initialization no longer runs before its textarea exists; failed validation preserves the selected status and message.
Missing or empty uptime samples show No data and are excluded from averages.
Reopening an incident clears its previous resolution timestamp.
Upgrade
No new database migration or environment setting is required. Built editor assets are included; Node.js is only needed to rebuild them.
The Update link on an incident is now a proper button with a pencil icon, placed before the status label. On a mouse it appears when you hover the incident, so a signed-out visitor's view stays uncluttered; on touch it is always visible, and keyboard focus brings it back. A long incident title now wraps instead of pushing the button off the card.
A note's dismiss button no longer brings its own <form>. When a note sits inside another form — the Status page screen, or a component's heartbeat note — the nested form was invalid HTML, and the browser silently closed the outer form at that point. That detached everything after the note (theme, incident days, Save/Undo) from the real form, so the Status page settings screen showed no live preview and neither Save nor any toggle did anything whenever no service group existed yet.
Reporting an incident no longer fails with "The components.N field must be an integer" when a component is left on "— leave unchanged —". Every component's status selector posted a value, even the placeholder one, so picking a real status for one component while leaving any other unchanged rejected the whole report.
Settings → Mail's "Send test e-mail" now shows the failure when the test can't actually be sent (bad host, refused connection, ...) instead of silently redirecting back with nothing to see — the same information the button already collects, just never rendered.
Mail templates no longer tells an install without the brand pack to "press Save" on a screen that has no Save button.
Reporting an incident that fails validation for an unrelated reason (a missing title, say) no longer resets every component's status back to "— leave unchanged —"; the choices you made are kept so you don't have to redo them.
Built-in logos and icons use content-versioned URLs after PHP updates. Logo theme selection is scoped consistently, and the fixed dark setup panel always uses the white variant.
Docker updates no longer offer a non-functional pull-and-restart button or report success after writing an unconsumed trigger. The Updates screen explains host-side Compose updates and version pins; direct update requests fail explicitly and cannot replace container files.
Updated the built-in Pharos logos, light/dark variants, browser icon and default email logo from the new brand kit. Custom installation names and uploaded branding remain supported.
Services: the empty state uses the same layout as Components. Creating a service from the component dialog reports session, validation and server errors separately.
Browser requests and live previews retain the public origin behind HTTPS proxies, including installations in a subdirectory. The status-page preview follows the form's theme without overwriting the visitor's preference; mail preview failures are visible.
Proxy trust now loads after the environment and works with cached configuration. Docker Compose forwards TRUSTED_PROXIES, so configured HTTPS proxies produce correct form actions and redirects.
Self-updates and rollbacks reset the web OPcache after replacing files, including recovery from failed updates. Hosts that restrict the reset API receive a restart warning; command-line updates explicitly require checking/restarting the separate web PHP cache.
Upgrade notes
The updater running in 0.5.4 does not include this fix. The first upgrade from 0.5.4 may still require a one-time PHP service or container restart. Docker image updates already recreate the container.
Discord notifications, with mentions disabled and rate-limit-aware retries.
Signal notifications through your own authenticated HTTPS bridge. An optional Docker Compose and gateway configuration is included; linking a Signal account is still required.
A persistent notification outbox with bounded retries and delivery history, so a temporary delivery failure does not silently lose an incident notification.
Optional automatic cron setup through DirectAdmin or cPanel, plus php artisan pharos:cron --install for hosts with shell access. Existing tasks are read first, preserved and checked after installation.
A dedicated authenticated Uptime Kuma status webhook for manually managed components.
Fixed
Installer: detects versioned CLI PHP installations for DirectAdmin, cPanel, CloudLinux and Plesk and distinguishes web PHP from cron PHP. Restricted filesystem access produces an explicit warning instead of a false success.
Installer: a private installation key protects the initial setup; CSRF checks and installation locks prevent unintended configuration changes. Existing installations and APP_KEY are preserved, and database passwords retain special characters.
MySQL: setting changes no longer fail because the audit log expected a numeric ID for a text setting key.
Updates and rollback: copied public files follow the exact release or backup; tracked obsolete release files are removed without deleting uploads or custom files. Symlink destinations are refused, and failed backups or migrations stop the update.
Monitoring: DNS resolution fails closed and TCP checks use the same validated address throughout. Failed scheduler runs no longer appear as successful checks.
Notifications: connection credentials are stored encrypted and excluded from delivery errors. Signal credentials are not rendered back into the page.
Integrations: clearer heartbeat and Kuma instructions and long API addresses that fit mobile screens.
Shell installer: unverified releases, non-empty installation directories and unsafe pinned-version overwrites are refused. Older releases receive manual cron instructions when automatic setup is unavailable.
Upgrade notes
Back up your installation and database, then run php artisan migrate --force after updating. Keep the scheduler running every minute for checks and notification retries.
Discord requires a channel webhook. Signal requires a linked bridge, HTTPS endpoint and bearer token; it is not hosted by Pharos.
Cron availability depends on hosting permissions. Plesk can use Scheduled Tasks or the CLI command. A saved cron task is only confirmed operational after a successful scheduler run.
MySQL database backups and restores remain operator-managed. Public files from before the new ownership manifest are not deleted automatically.
Status page: the incident history is paged. *Days of incident history* now sets how many days one page shows; *Older incidents* and *Newer incidents* at the bottom of the list walk through the earlier days, and the Older link only appears when there is something earlier to see. Open incidents that outlive the first page stay pinned there and are not repeated on later pages.
Updates: when a migration or the file copy fails halfway, the version that was just backed up is put back automatically — files the new release added are removed first — instead of leaving new code on an old database. The message names the backup either way.
Backups and the Updates screen no longer need the intl PHP extension to show a size; hosts and the Docker image without it saw a backup "fail" right after it had been written.
HTTP and TCP checks go through the same guard as webhooks and single sign-on: a check can watch your own network, but never this machine, 169.254.169.254 or another link-local address, and it follows no redirects — the response code is the result. Names are resolved once and the connection pinned to that address.
CSV exports (subscribers, audit log) neutralise cells that a spreadsheet would run as a formula, such as an address starting with =.
The public status page fetched uptime twice per component; it is one query for the whole page now.
Session cookies are marked Secure automatically when APP_URL is https; set SESSION_SECURE_COOKIE to override.
A test that compared "1 August" with "31 August" failed on the first day of a month.
Added
TRUSTED_PROXIES in .env (addresses, or *) for installs behind Cloudflare or a Docker reverse proxy, so rate limits and the audit log see the visitor's address rather than the proxy's.
Docker: the image carries a HEALTHCHECK on /up, and the scheduler container waits for the app to be healthy.
Release page: canonical URL and social-sharing tags.
Changed
The README's cron line redirects output, as the installers already did; without it a control panel mails the scheduler's output every minute.
"Cachet 2.x compatible" is now described as what it is: components and incidents in Cachet's shape, without ping, version, groups, metrics, subscribers or schedules.
Release archives no longer include .phpunit.result.cache and the release-page generator.
A fresh install showed the "Get notified" form before any mail settings existed, and a visitor who used it got a server error. The form now stays off the public page until Settings → Mail has an SMTP host, the Subscribers screen says so, and a mail transport that fails answers with a message instead of a 500.
Opening an incident with a component id that does not exist no longer fails with a database error; unknown ids are dropped.
Added
Updates: installing a release, making a backup and rolling back now open a dialog that shows each step as it happens (download, checksum, unpack, backup, install, migrate) with a live file count, instead of a bare button that returns when everything is over.
Fixed
Release archives left out resources/views/vendor/ (the Pharos pagination view): the Audit log returned a 500 as soon as it had more than one page. Fresh installs of 0.5.0 are affected; installs updated from an older checkout were not.
Installers: DirectAdmin support — the cron line is pinned to /usr/local/php<MM>/bin/php, and DirectoryIndex index.php keeps the panel's placeholder index.html from shadowing the status page.
/get verifies the release manifest with PHP's sodium first; hosts whose OpenSSL cannot do Ed25519 one-shot verification (CloudLinux 1.1.1k without -rawin) refused every manifest.
Take a backup first. Pharos snapshots include SQLite; MySQL needs a separate database backup. A version-pinned installer is for a fresh installation, not a downgrade. Restore matching code and database when rolling back.