Skip to main content

Database Backup β€” Logical pg_dump

Gap 11 gap closure β€” 2026-07-01. Three PostgreSQL instances backed up daily via logical pg_dump to MinIO db-backups/ bucket.

Velero captures PVC data at filesystem level (kopia blocks), which is crash-consistent but not application-consistent for a running PostgreSQL instance. This logical backup layer provides clean, importable SQL dumps.


Architecture​

Controller (daily 02:00 UTC)
db-backup script
β”œβ”€ kubectl exec β†’ backstage-postgresql-0 β†’ pg_dumpall β†’ gzip
β”œβ”€ kubectl exec β†’ nextcloud-postgresql-0 β†’ pg_dump nextcloud β†’ gzip
β”œβ”€ kubectl exec β†’ authentik-postgresql-0 β†’ pg_dump authentik β†’ gzip
└─ docker exec minio mc cp β†’ myminio/db-backups/
β”œβ”€β”€ backstage/YYYYMMDDTHHMMSSZ.sql.gz
β”œβ”€β”€ nextcloud/YYYYMMDDTHHMMSSZ.sql.gz
└── authentik/YYYYMMDDTHHMMSSZ.sql.gz

MinIO lifecycle policy: 30-day expiry on db-backups/ bucket

Database Coverage​

InstanceNamespacePodUserDatabasesBackup type
Backstagebackstagebackstage-postgresql-0postgres (superuser)9 plugin DBspg_dumpall
Nextcloudnextcloudnextcloud-postgresql-0nextcloud (app user)nextcloudpg_dump
Authentikauthentikauthentik-postgresql-0authentik (app user)authentikpg_dump

:::note Authentik postgres superuser The Authentik chart disables TCP password auth for the postgres superuser (peer-only local socket). The authentik app user has sufficient grants to dump the authentik database. :::


Script​

Located at /home/ktayl/.local/bin/db-backup on the controller.

Credentials are read at runtime from the pods' mounted secret files and Kubernetes secrets β€” no passwords hardcoded in the script. Password rotation is picked up automatically on the next run.

Schedule (ktayl user crontab):

0 2 * * * /home/ktayl/.local/bin/db-backup >> /home/ktayl/db-backup.log 2>&1

Verify Backups​

# Check recent dumps in MinIO
docker exec minio mc ls myminio/db-backups/backstage/ | tail -3
docker exec minio mc ls myminio/db-backups/nextcloud/ | tail -3
docker exec minio mc ls myminio/db-backups/authentik/ | tail -3

# View last run log
tail -20 ~/db-backup.log

# Run immediately
~/.local/bin/db-backup

First verified run (2026-07-01):

  • Backstage: 4.5M dump (all 9 plugin databases) βœ…
  • Nextcloud: 4.0K dump (empty database, app just deployed) βœ…
  • Authentik: 7.8M dump (full identity provider state) βœ…

Restore a Database​

See Disaster Recovery Runbook β€” Scenario D.


Prometheus Alerts​

backup-dr PrometheusRule in monitoring namespace includes:

  • VeleroNoRecentBackup β€” last successful Velero backup > 25h ago
  • VeleroBackupFailed β€” failed backup in last 26h
  • VeleroBackupStorageLocationUnavailable β€” MinIO unreachable
  • MinioDiskFull β€” controller disk < 10% free

These alert on Velero-level failures. Database backup failures log to ~/db-backup.log and syslog (logger -t db-backup); check with journalctl -t db-backup -n 20.