Backups and restore
Scheduled backups, restore drill into an ephemeral container, end-to-end verification.
Backup
Section titled “Backup”scripts/backup.sh pipes pg_dump --clean --if-exists --no-owner through gzip and writes a timestamped .sql.gz to /var/backups/pulse/.
Schedule with cron or systemd:
15 3 * * * /opt/pulse/scripts/backup.shAlso snapshot Traefik’s acme.json (see Self-hosting → TLS) and Redis if you care about queue depth at restore time (usually you don’t — workers refill on demand).
Restore
Section titled “Restore”scripts/restore.sh <backup.sql.gz> boots a fresh ephemeral Postgres container on port 15432, replays the dump, and prints a count report.
scripts/restore.sh /var/backups/pulse/pulse-2026-05-19.sql.gz# [restore] starting ephemeral postgres on :15432# [restore] applying dump...# [restore] table rows# [restore] monitors 342# [restore] users 18# [restore] organizations 3# [restore] incidents 1102# [restore] alert_rules 27# [restore] OKOverride the port with RESTORE_PORT=15440.
End-to-end drill
Section titled “End-to-end drill”scripts/backup-test.sh ties it together: take a backup of the running dev DB → restore into the ephemeral instance → run sanity SQL → cleanup. Run it monthly. If it ever fails, you’ve found a backup format change before you needed it.