diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index ce25ad1..020a6cf 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -109,6 +109,16 @@ POSTGRES_PASSWORD='use-secret-storage' \ ./scripts/restore-postgres.sh ``` +Verify a dump before scheduling a restore: + +```sh +BACKUP_FILE=/secure/backups/inventory-20260909T000000Z.dump \ +./scripts/verify-postgres-backup.sh +``` + +This checks that the file is a readable PostgreSQL custom-format archive without +changing any database. + Back up image storage and the deployment `.env` through the NAS secret/backup system as well. Never commit either one. Before upgrading, record the current image tags and database migration state. To roll back, stop the application diff --git a/scripts/verify-postgres-backup.sh b/scripts/verify-postgres-backup.sh new file mode 100755 index 0000000..05b4eba --- /dev/null +++ b/scripts/verify-postgres-backup.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -eu + +: "${BACKUP_FILE:?Set BACKUP_FILE to a PostgreSQL custom-format dump}" + +if [ ! -f "$BACKUP_FILE" ]; then + printf '%s\n' "Backup file not found: $BACKUP_FILE" >&2 + exit 1 +fi + +if [ ! -s "$BACKUP_FILE" ]; then + printf '%s\n' "Backup file is empty: $BACKUP_FILE" >&2 + exit 1 +fi + +docker compose -f compose.production.yaml run --rm -T postgres \ + pg_restore --list < "$BACKUP_FILE" >/dev/null + +printf '%s\n' "Backup archive is readable: $BACKUP_FILE" diff --git a/scripts/verify-postgres-backup.test.sh b/scripts/verify-postgres-backup.test.sh new file mode 100755 index 0000000..a515999 --- /dev/null +++ b/scripts/verify-postgres-backup.test.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -eu + +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +test_dir=$(mktemp -d) +trap 'rm -rf "$test_dir"' EXIT + +printf '%s\n' 'fake dump' > "$test_dir/backup.dump" +mkdir -p "$test_dir/bin" +printf '%s\n' '#!/bin/sh' 'exit 0' > "$test_dir/bin/docker" +chmod +x "$test_dir/bin/docker" + +PATH="$test_dir/bin:$PATH" BACKUP_FILE="$test_dir/backup.dump" \ + sh "$script_dir/verify-postgres-backup.sh" >/dev/null + +if BACKUP_FILE="$test_dir/missing.dump" sh "$script_dir/verify-postgres-backup.sh" >/dev/null 2>&1; then + printf '%s\n' 'Expected missing backup to fail.' >&2 + exit 1 +fi + +printf '%s\n' 'verify-postgres-backup tests passed.'