Self-hosting Status
Deploy the web application and workers, persist data, and upgrade.
Status runs as two processes: the web application (which stores configuration and history and serves the console) and one or more workers (which run the actual checks). Both ship from one Docker build.
Quickstart with Docker Compose
git clone <repository> status
cd status
docker compose up -d
docker compose logs webThe log prints a setup token:
[status] This instance is not configured yet.
[status] Open /setup and enter this token: 9JjPVL7_Bm5FCmg6wTHueC9KBMOsmPFEOpen <http://localhost:3000/setup>, enter that token, and work through the
wizard. It configures the database connection when none is set, then the
public URL, private profile-picture storage, sign-in methods (email/password,
SSO, or both), the first organization, and the shared worker token. Password
deployments create their first owner in the wizard.
The token proves you can read the container's logs or filesystem, so an
uninitialized instance cannot be claimed by whoever finds it first. It is
deleted when setup completes, and both /setup and /api/setup/* return 404
from then on.
Finishing the worker
The wizard's workers step reveals the shared worker token once. Put it in a
.env next to docker-compose.yml and restart the worker:
echo "MONITOR_WORKER_TOKEN=wrk_..." >> .env
docker compose up -d workerConfirm it connected on the Agents page, or in the worker log:
[worker] activated revision 4f53cda18c2b (3 monitors)
[worker] worker-1 v0.0.0 started in default; data=/var/lib/status-workerPersistent data
Three volumes matter, for different reasons:
| Volume | Holds | If lost |
|---|---|---|
postgres-data | All configuration and history | Everything is gone. Back it up—see backup-restore.md. |
web-state | Session secret, encryption key ring, wizard-saved database connection, and locally stored profile pictures | Stored credentials cannot be decrypted; local profile pictures are lost; a wizard-saved database URL must be re-entered. |
worker-data | Cached configuration and the outbound result queue | Queued results not yet delivered are lost; the worker re-syncs and continues. |
Store web-state on persistent storage and include it in backups. It is separate from PostgreSQL. Losing it makes encrypted credentials inaccessible.
The bundled deployment stores profile pictures in web-state. Multiple web
replicas must use a shared filesystem or select S3-compatible storage in the
wizard. Stored pictures remain private; browsers fetch them through Status
after membership is checked.
Building the images directly
docker build --target web -t status/web .
docker build --target worker -t status/worker .Behind a reverse proxy
Set the public URL in the wizard (or Settings → Instance) to the origin users actually reach, and forward it to the container's port 3000. When SSO is enabled, it must match the redirect URI registered with your identity provider:
https://status.example.com/api/auth/callback/authentikEnable Trust proxy headers only when the proxy overwrites
X-Forwarded-For. With it enabled behind a proxy that merely appends, clients
can spoof their address and evade the IP-keyed rate limits.
Upgrading
docker compose pull
docker compose up -dThe image applies pending migrations on startup. If a migration fails the server refuses to serve rather than run against a half-migrated schema. Take a backup first—see backup-restore.md.
An existing deployment's .env keeps working unchanged: every environment
variable that used to configure Status still overrides the corresponding
database setting. See configuration.md for the precedence
rules.
Related documentation
- Configuration: the five configuration layers
- Run monitor workers
- Monitoring agents: per-organization workers
- Backup and restore