# Backup & restore `backup.sh` produces a single bundle containing the Postgres database and the MinIO object store. Run it from this `deploy/` directory on the host that runs the stack. ## Back up ```bash ./backup.sh # → backups/provenance-backup-20260609T140000Z.tar ``` The bundle contains: - `db.sql.gz` — `pg_dump --clean --if-exists` of the database, gzipped. - `minio-data.tar.gz` — the MinIO `/data` directory (objects + bucket metadata). - `MANIFEST.txt` — what's inside and when it was made. Optional retention: `BACKUP_RETAIN_DAYS=30 ./backup.sh` also deletes bundles older than 30 days. Schedule it from cron for off-box copies, e.g.: ```cron 15 3 * * * cd /path/to/provenance/deploy && BACKUP_RETAIN_DAYS=30 ./backup.sh ``` (Copy the resulting bundle off the host — a backup on the same disk isn't one.) ## Restore Restoring overwrites live data — stop the app first. ```bash ts=20260609T140000Z # the bundle you're restoring mkdir -p /tmp/restore && tar xf backups/provenance-backup-$ts.tar -C /tmp/restore # 1. Database — the dump is --clean, so it drops & recreates objects. docker compose stop backend worker gunzip -c /tmp/restore/db.sql.gz \ | docker compose exec -T postgres psql -U "${POSTGRES_USER:-provenance}" -d "${POSTGRES_DB:-provenance}" # 2. Objects — replace the MinIO data directory. docker compose stop minio docker compose run --rm --no-deps -T -v provenance_miniodata:/data minio \ sh -c 'rm -rf /data/* && tar xzf - -C /data' < /tmp/restore/minio-data.tar.gz docker compose up -d rm -rf /tmp/restore ``` Notes: - The MinIO `/data` archive is filesystem-level; restore into the **same** MinIO major version it was taken from. - Verify the volume name (`docker volume ls | grep miniodata`) — compose prefixes it with the project name; adjust the `-v` mount accordingly.