Skip to content

Backups and restore

What is backed up

What How Where Kept
PostgreSQL The db-backup service, @daily ./backups 14 daily, 4 weekly, 6 monthly
PostgreSQL, again A dump taken before each Borgmatic run /home/danvics/docker/db-dumps Borgmatic's retention
docker compose logs db-backup --tail=10
ls -la backups/

What is not backed up

The object store. MinIO holds every figure, and the bucket is not versioned. Once purge_trashed_media removes an object there is no copy of it here. A database restore afterwards brings back a row pointing at nothing.

This is the reason the bin holds for 30 days, the reason the purge runs daily rather than hourly, the reason there is exactly one beat, and the reason a grant holder can only ever unlink a figure rather than bin it. See What can be undone.

Also not backed up: Redis (site settings, job state, in-flight session progress) and the ChromaDB page chunks. Redis settings are a handful of keys that can be reset from the admin page; page chunks can be rebuilt by reprocessing the documents.

By hand

# dump
docker compose exec postgres pg_dump -U pedquiz pedquiz > manual-backup.sql

# restore
cat backups/daily/pedquiz-YYYYMMDD-HHMMSS.sql.gz | gunzip | \
  docker compose exec -T postgres psql -U pedquiz -d pedquiz

Direct access:

docker compose exec postgres psql -U pedquiz -d pedquiz

After a restore

Two things are worth checking, because they live outside Postgres:

  1. Figures. Run python -m app.cli check-links — it will list pointers into articles and media that no longer resolve.
  2. Embeddings. The retry_missing_embeddings sweep runs every 15 minutes and will pick up anything missing, but a bulk restore is a reason to watch it rather than assume it.

Volumes

Volume Holds
postgres_data The database
minio_data Media objects
uploads_data Uploaded PDFs, and media not yet migrated to S3
chroma_data Document page chunks
redis_data Settings, queue, job state
loki_data, grafana_data, promtail_positions Logs