Add pg_dump/pg_restore backup and restore scripts
For moving this project to a new server: git tracks code, not the Postgres data directory, and raw volume/data-dir copying is fragile across Postgres versions or architectures (this repo already hit a collation-version mismatch once from just changing the Postgres image). pg_dump/pg_restore is the portable way to move the actual data instead. scripts/backup-db.sh dumps the running postgres container's database in pg_dump's custom format into ./backups/ (gitignored — dumps contain real user data and don't belong in git history). It reads POSTGRES_USER/POSTGRES_DB from the container's own environment rather than re-parsing .env, so it can't drift out of sync with the actual running config. scripts/restore-db.sh restores a dump into the running container (--clean --if-exists --single-transaction, so a failure rolls back atomically instead of leaving a half-restored database), with a confirmation prompt since it's destructive, skippable via -y. Added .gitattributes forcing LF on *.sh — Windows git would otherwise check these out as CRLF, breaking the bash shebang on the Linux server they're meant to run on. Verified end to end: took a real backup of the live database, restored it back over itself, and confirmed exact row-count matches across every table plus that pgvector similarity search still works on the restored embeddings (not just that the bytes round-tripped). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
* text=auto
|
||||||
|
*.sh text eol=lf
|
||||||
@@ -12,6 +12,7 @@ build/
|
|||||||
caddy_data/
|
caddy_data/
|
||||||
caddy_config/
|
caddy_config/
|
||||||
pgdata/
|
pgdata/
|
||||||
|
backups/
|
||||||
frontend/dist/
|
frontend/dist/
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Dumps the Postgres database from the running "postgres" container into ./backups/,
|
||||||
|
# in pg_dump's custom format (compressed, restorable with pg_restore — see restore-db.sh).
|
||||||
|
#
|
||||||
|
# Usage: scripts/backup-db.sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
mkdir -p backups
|
||||||
|
timestamp="$(date +%Y%m%d_%H%M%S)"
|
||||||
|
out="backups/dnd_backup_${timestamp}.dump"
|
||||||
|
trap 'rm -f "${out}"' ERR
|
||||||
|
|
||||||
|
echo "Dumping database into ${out} ..."
|
||||||
|
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -F c' > "${out}"
|
||||||
|
|
||||||
|
size="$(du -h "${out}" | cut -f1)"
|
||||||
|
echo "Done: ${out} (${size})"
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Restores a dump produced by backup-db.sh into the running "postgres" container.
|
||||||
|
# Destructive: drops and recreates every object in the target database before restoring.
|
||||||
|
#
|
||||||
|
# Usage: scripts/restore-db.sh path/to/dnd_backup_20260101_120000.dump [-y]
|
||||||
|
# -y skip the confirmation prompt (for non-interactive/scripted use)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
skip_confirm=false
|
||||||
|
file=""
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [ "$arg" = "-y" ]; then
|
||||||
|
skip_confirm=true
|
||||||
|
else
|
||||||
|
file="$arg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$file" ]; then
|
||||||
|
echo "Usage: $0 path/to/backup.dump [-y]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo "Error: file not found: $file" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$skip_confirm" = false ]; then
|
||||||
|
read -r -p "This will DROP and recreate every table in the target database. Continue? [y/N] " reply
|
||||||
|
case "$reply" in
|
||||||
|
[yY]|[yY][eE][sS]) ;;
|
||||||
|
*) echo "Aborted."; exit 1 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Restoring ${file} ..."
|
||||||
|
docker compose exec -T postgres sh -c \
|
||||||
|
'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists --no-owner --no-privileges --single-transaction' \
|
||||||
|
< "$file"
|
||||||
|
|
||||||
|
echo "Done."
|
||||||
Reference in New Issue
Block a user