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 |
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:
After a restore¶
Two things are worth checking, because they live outside Postgres:
- Figures. Run
python -m app.cli check-links— it will list pointers into articles and media that no longer resolve. - Embeddings. The
retry_missing_embeddingssweep 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 |