Self-hosted status page and probe system built with Bun, PostgreSQL, and Docker Compose.
app: Bun HTTP server for/,/admin,/api/public/status,/api/admin/*,/api/probe/reportpostgres: source of truth for catalog, probe results, overrides, announcements, and public snapshotsprobe: optional Bun runtime declared in a separate Compose override file
Ingress is intentionally out of scope for the repo. Point nginx, caddy, or a tunnel at the exposed app port.
- Copy the environment template:
cp .env.example .envCore settings live at the top of .env. Probe-specific settings are grouped separately and matter only when you start with docker-compose.probe.yml.
- Start the stack:
docker compose up -d --build- Open:
- public page:
http://127.0.0.1:3000/ - admin page:
http://127.0.0.1:3000/admin - public API:
http://127.0.0.1:3000/api/public/status
The app container runs PostgreSQL migrations on startup. The compose default also seeds a minimal flarestatus service and flarestatus-public-api component.
To enable the bundled probe too:
docker compose -f docker-compose.yml -f docker-compose.probe.yml up -d --buildCommon shortcuts:
make up: startpostgres + appmake up-probe: startpostgres + app + probemake down: stop the core stackmake down-probe: stop the stack including probemake logs: follow core stack logsmake logs-probe: follow logs including probemake ps: show core stack containersmake config: render the core Compose configmake config-probe: render the merged Compose config with probe
- Start PostgreSQL:
docker compose up -d postgres- Export runtime variables:
export DATABASE_URL=postgresql://flarestatus:flarestatus@127.0.0.1:5432/flarestatus
export ADMIN_API_TOKEN=test-admin-token
export PROBE_API_TOKEN=test-probe-token- Apply migrations:
bun run migrate- Start the app:
bun run dev- In another shell, start a probe:
export PROBE_COMPONENT_SLUG=flarestatus-public-api
export PROBE_REPORT_ENDPOINT=http://127.0.0.1:3000/api/probe/report
export PROBE_REPORT_TOKEN=test-probe-token
export PROBE_CHECK_TYPE=http
export PROBE_HTTP_URL=http://127.0.0.1:3000/api/public/status
bun --filter probe startOr use the bundled Compose probe:
docker compose -f docker-compose.yml -f docker-compose.probe.yml up -d probeEvery probe needs:
PROBE_COMPONENT_SLUGPROBE_REPORT_ENDPOINTPROBE_REPORT_TOKENPROBE_CHECK_TYPE
Supported check types:
http:PROBE_HTTP_URL, optionalPROBE_HTTP_TIMEOUT_MS, optionalPROBE_HTTP_EXPECTED_STATUStcp:PROBE_TCP_HOST,PROBE_TCP_PORT, optionalPROBE_TCP_TIMEOUT_MSredis:PROBE_REDIS_URL, optionalPROBE_REDIS_TIMEOUT_MSpostgres:PROBE_POSTGRES_CONNECTION_STRING, optionalPROBE_POSTGRES_TIMEOUT_MS
Runtime mode:
- loop mode: omit
PROBE_RUN_ONCEor setfalse - one-shot mode: set
PROBE_RUN_ONCE=true - interval:
PROBE_INTERVAL_MS, default30000
Catalog:
curl http://127.0.0.1:3000/api/admin/catalog \
-H 'Authorization: Bearer test-admin-token'Create a service:
curl -X POST http://127.0.0.1:3000/api/admin/services \
-H 'Authorization: Bearer test-admin-token' \
-H 'Content-Type: application/json' \
--data '{"slug":"sub2api","name":"Sub2API","description":"Primary API","sortOrder":20,"enabled":true}'Create a component:
curl -X POST http://127.0.0.1:3000/api/admin/components \
-H 'Authorization: Bearer test-admin-token' \
-H 'Content-Type: application/json' \
--data '{"serviceSlug":"sub2api","slug":"sub2api-public-api","name":"Public API","probeType":"http","isCritical":true,"sortOrder":10,"enabled":true}'Create an override:
curl -X POST http://127.0.0.1:3000/api/admin/overrides \
-H 'Authorization: Bearer test-admin-token' \
-H 'Content-Type: application/json' \
--data '{"targetType":"component","targetSlug":"flarestatus-public-api","overrideStatus":"degraded","message":"Investigating elevated latency"}'Create an announcement:
curl -X POST http://127.0.0.1:3000/api/admin/announcements \
-H 'Authorization: Bearer test-admin-token' \
-H 'Content-Type: application/json' \
--data '{"title":"Scheduled maintenance","body":"Database failover in progress.","statusLevel":"partial_outage"}'bun run testbun --filter probe testbun run typecheckdocker compose -f docker-compose.yml configdocker compose -f docker-compose.yml -f docker-compose.probe.yml config
Runbooks: