Backups and monitoring
Backups, restores, retention, health checks and metrics for a running hub.
Backups
The optional backup service runs pg_dump every night at BACKUP_HOUR (UTC, default 3). It keeps 14
daily and 8 weekly dumps in BACKUP_DIR (default ./backups).
docker compose --profile backup up -d
docker compose run --rm backup --once # take one nowCopy BACKUP_DIR off the machine with rsync, restic or object storage. A backup on the same disk as the
database is not a backup.
Restoring
Restore into an empty database, and test the procedure at least once before you need it:
docker compose stop web worker
docker compose exec db psql -U hub -d postgres -c 'DROP DATABASE hub WITH (FORCE)' -c 'CREATE DATABASE hub'
docker compose exec db psql -U hub -d hub -c 'CREATE EXTENSION timescaledb' -c 'SELECT timescaledb_pre_restore()'
docker compose exec -T db pg_restore -U hub -d hub --no-owner < backups/daily/hub-<stamp>.dump
docker compose exec db psql -U hub -d hub -c 'SELECT timescaledb_post_restore()'
docker compose start web workerRetention
| Data | Kept | Variable |
|---|---|---|
| Raw XP samples (5-minute) | 365 days | XP_RAW_RETENTION_DAYS (at least 14) |
| Hourly and daily XP | forever | |
| Location trail | 30 days | LOCATION_RETENTION_DAYS |
| Raw plugin payloads | 72 hours | RAW_PAYLOAD_RETENTION_HOURS |
| Audit log | 2 years | AUDIT_LOG_RETENTION_DAYS |
| Events, sessions, equipment, wealth | forever |
Health and metrics
GET /api/healthanswers 200 when the web app can reach the database, 503 otherwise. It needs no auth.- Metrics are off until you set
METRICS_TOKEN. Then both endpoints wantAuthorization: Bearer <METRICS_TOKEN>:- the web app's
GET /metrics: ingest, live connections, pairing, the public API and data exports; - the worker's
GET /metricson portWORKER_METRICS_PORT(9464): job runs and durations, Discord re-verification, open play sessions and grace expiries.
- the web app's
Metric labels never contain user, account or device ids, names, IP addresses or coordinates.
The hub repository ships a Prometheus scrape example (ops/prometheus/scrape-example.yml), alert rules
(ops/prometheus/alerts.yml) and a Grafana dashboard (ops/grafana/dashboards/hub-overview.json). Keep
the scrape job names hub-web and hub-worker; the dashboard expects them.
curl -H "Authorization: Bearer $METRICS_TOKEN" http://127.0.0.1:9464/metricsDecommissioning
The admin decommission switch makes the hub answer 410 to the plugin, which disables the connection in every player's plugin for good. Players have to pair again to use another hub. Only use it when you shut the hub down permanently.