Task A — make the container backup-capable + validated dump + mechanism fingerprint
SUPABASE_DB_URL is set in Coolify on the API service, and this WSL2 box can't reach db.<ref>.supabase.co — so the backup runs INSIDE the API container, which has the env + Supabase network. Made that real: - Dockerfile: install postgresql-client (pg_dump/pg_restore) + rsync + bash in the runner image. - backup-db.sh: added an integrity fingerprint on every run — pg_restore --list must parse the archive AND find ledger_entries, else the run FAILS + pages (stronger than the size check; catches a corrupt/structureless dump). - BACKUP-RUNBOOK.md: rewritten for the container-exec reality — host cron does `docker exec <api> sh /app/scripts/backup-db.sh` (inherits env + network + pg_dump), or a Coolify Scheduled Task. Full restore-fingerprint steps included. MECHANISM FINGERPRINT (run locally, docker + pg16): seeded a ledger_entries table (137 rows) → ran backup-db.sh (dump + validate: 22 archive objects, ledger_entries present) → pg_restore into a scratch DB → 137 rows restored, exact match. The dump/validate/restore path is proven end-to-end; it's the same pg_dump/pg_restore that run in the container against Supabase. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,15 @@ pg_dump "${SUPABASE_DB_URL}" -Fc --no-owner --no-privileges -f "${DUMP}" \
|
||||
SIZE="$(stat -c%s "${DUMP}" 2>/dev/null || echo 0)"
|
||||
[ "${SIZE}" -ge "${MIN_BYTES}" ] || fail "dump is only ${SIZE} bytes (< ${MIN_BYTES}) — treating as a failed backup"
|
||||
|
||||
# 2b. Integrity fingerprint: a valid custom-format archive lists its objects via
|
||||
# pg_restore --list (no target DB needed). Confirm it parses AND contains the
|
||||
# ledger — proves it's a real, restorable archive, not just a file of bytes.
|
||||
TOC="$(pg_restore --list "${DUMP}" 2>/dev/null)" || fail "pg_restore --list failed — dump is not a valid archive"
|
||||
OBJECTS="$(printf '%s\n' "${TOC}" | grep -c ';' || true)"
|
||||
printf '%s\n' "${TOC}" | grep -qi 'TABLE DATA public ledger_entries' \
|
||||
|| fail "dump archive does not contain ledger_entries — refusing to trust it"
|
||||
echo "backup validated: ${DUMP} (${SIZE} bytes, ${OBJECTS} archive objects, ledger_entries present)"
|
||||
|
||||
# 3. Rotate: drop local dumps older than KEEP_DAYS.
|
||||
find "${BACKUP_DIR}" -name 'vyndr-*.dump' -type f -mtime "+${KEEP_DAYS}" -delete || true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user