Files
transcription/docs/backup_restore.md
T
Jim LancasterandCopilot App 34c7b16675
Quality Gate / gate (push) Failing after 47s
Refine Synology backup workflow
Co-authored-by: Copilot App <[email protected]>
2026-08-26 17:32:20 -05:00

3.4 KiB

Backup and Restore (V6.0 Phase 4)

This guide defines operational backup/restore for clean-slate recovery of the Docker runtime and Synology replication.

1. Backup artifacts (clean-slate recovery set)

  • Primary local backup location: ./data/backups
  • Local files created per run:
    • postgres-YYYYMMDD-HHMMSS.dump (PostgreSQL custom dump via pg_dump -Fc)
    • backup-YYYYMMDD-HHMMSS.manifest (artifact index)
  • Synology files created per run (when SYNOLOGY_BACKUP_DIR is set):
    • postgres-YYYYMMDD-HHMMSS.dump (copied from local)
    • config-YYYYMMDD-HHMMSS.tar.gz (deployment config snapshot: .env.production, docker-compose.production.yml, deploy/cloudflared/config.yml when present)
    • logs-YYYYMMDD-HHMMSS.tar.gz (snapshot of /app/data/logs)
    • backup-YYYYMMDD-HHMMSS.manifest
  • Synology incremental media mirror (copied only if missing):
    • uploads/homepage.md
    • uploads/documents/**
    • uploads/photos/**

2. Creating backups

Use the scripted command from the repository root:

sh deploy/backup/create_postgres_backup.sh

Environment overrides:

  • BACKUP_DIR (default ./data/backups)
  • BACKUP_RETENTION_DAYS (default 14)
  • SYNOLOGY_BACKUP_DIR (if set, dump/config/log/manifest are copied to this mounted path and media is synced incrementally)
  • ENV_FILE (default .env.production)
  • COMPOSE_FILE (default docker-compose.production.yml)

Example with Synology mount:

SYNOLOGY_BACKUP_DIR=/mnt/synology-backups sh deploy/backup/create_postgres_backup.sh

2.1 Persisting Synology mount (LXC)

The backup copy step depends on a mounted NAS path. Manual mount commands are lost after reboot unless persisted.

Use the template (copy, edit placeholders, then run):

cp deploy/backup/mount_synology_cifs.example.sh /root/mount_synology_cifs.sh
nano /root/mount_synology_cifs.sh
sh /root/mount_synology_cifs.sh

Then add the printed /etc/fstab line (with your real values) so the mount survives reboot.

Recommended pattern:

  • Keep NAS credentials in a local file like /etc/samba/credentials/transcription-synology with chmod 600.
  • Keep SYNOLOGY_BACKUP_DIR in .env.production aligned to that mount point (for example /mnt/synology-backups).
  • The script will also read SYNOLOGY_BACKUP_DIR from ENV_FILE when not exported in the shell.

3. Restoring from backup

Restore requires downtime for app + worker writes.

  1. Stop app and worker:
    • docker compose --env-file .env.production -f docker-compose.production.yml stop app worker
  2. Restore:
    • sh deploy/backup/restore_postgres_backup.sh ./data/backups/postgres-YYYYMMDD-HHMMSS.dump
    • if SYNOLOGY_BACKUP_DIR/uploads exists, media is restored from the Synology mirror.
    • if SYNOLOGY_BACKUP_DIR/config-YYYYMMDD-HHMMSS.tar.gz exists, config is restored from that archive.
  3. Start app and worker:
    • docker compose --env-file .env.production -f docker-compose.production.yml start app worker
  4. Validate /healthz and run one smoke workflow.

Notes:

  • Config restore extracts the archived files back into the current repository path.
  • Legacy full-archive restores (uploads-*.tar.gz, config-*.tar.gz beside the dump) are still supported for older backups.

4. Retention and recovery targets

  • Retention baseline: keep at least 14 days of backups locally.
  • Synology copy: replicate each backup artifact set to DS420j mounted path.
  • Periodic restore drill: run at least once per release cycle to verify recovery.