feat(ops): scheduled Postgres backups via db-backup sidecar
All durable state (library, monitor/wanted lists, discovery, config, and the
encrypted credentials) lived only in the single postgres-data volume with no
backup — one volume loss = total loss. Adds a db-backup compose sidecar that
pg_dumps immediately on start then every BACKUP_INTERVAL_SECONDS (default daily),
keeping the last BACKUP_KEEP (default 7) custom-format dumps in ${BACKUP_DIR}.
Travels with the stack (no host cron), starts with `up -d`. .env.example
documents the knobs; README adds a "Backup & restore" section with pg_restore
steps and an off-box note. Verified live: sidecar wrote a valid 128K dump of the
real lyra DB (pg_restore -l lists all tables + _prisma_migrations).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -57,5 +57,43 @@ services:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
# Scheduled Postgres backups. ALL durable state (library, monitored/wanted lists,
|
||||
# discovery data, config, AND the encrypted credentials) lives in the single
|
||||
# postgres-data volume — one volume loss = total loss. This sidecar pg_dumps on an
|
||||
# interval (immediately on start, then every BACKUP_INTERVAL_SECONDS), keeping the
|
||||
# last BACKUP_KEEP dumps in ${BACKUP_DIR:-./backups}. Restore steps: see README.
|
||||
# For off-box safety, point BACKUP_DIR at a synced/NAS path or rsync ./backups away.
|
||||
db-backup:
|
||||
image: postgres:17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
PGHOST: db
|
||||
PGUSER: ${POSTGRES_USER}
|
||||
PGPASSWORD: ${POSTGRES_PASSWORD}
|
||||
PGDATABASE: ${POSTGRES_DB}
|
||||
BACKUP_INTERVAL_SECONDS: ${BACKUP_INTERVAL_SECONDS:-86400}
|
||||
BACKUP_KEEP: ${BACKUP_KEEP:-7}
|
||||
volumes:
|
||||
- ${BACKUP_DIR:-./backups}:/backups
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- |
|
||||
echo "db-backup: starting (interval=$${BACKUP_INTERVAL_SECONDS}s keep=$${BACKUP_KEEP})"
|
||||
while true; do
|
||||
ts=$$(date +%Y%m%d-%H%M%S)
|
||||
out="/backups/lyra-$${ts}.dump"
|
||||
if pg_dump -Fc -f "$${out}.tmp" 2>/tmp/err; then
|
||||
mv "$${out}.tmp" "$${out}"
|
||||
echo "db-backup: wrote $${out} ($$(du -h "$${out}" | cut -f1))"
|
||||
else
|
||||
echo "db-backup: pg_dump FAILED: $$(cat /tmp/err)"; rm -f "$${out}.tmp"
|
||||
fi
|
||||
ls -1t /backups/lyra-*.dump 2>/dev/null | tail -n +$$(( $${BACKUP_KEEP} + 1 )) | xargs -r rm -f
|
||||
sleep "$${BACKUP_INTERVAL_SECONDS}"
|
||||
done
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
|
||||
Reference in New Issue
Block a user