Files
Assistant/deploy/backup-postgres.sh
m e9594306e5
CI / test (push) Successful in 10s
ops: add verified PostgreSQL backups
2026-08-16 17:53:40 +03:00

67 lines
2.2 KiB
Bash
Executable File

#!/bin/sh
set -eu
umask 077
container="${ASSISTANT_POSTGRES_CONTAINER:-assistant-postgres-1}"
backup_root="${ASSISTANT_BACKUP_DIR:-/home/m/assistant-backups/postgres}"
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
partial_dir="${backup_root}/.${timestamp}.partial"
backup_dir="${backup_root}/${timestamp}"
cleanup() {
if [ -d "$partial_dir" ]; then
rm -f -- "$partial_dir/assistant.dump" "$partial_dir/globals.sql" \
"$partial_dir/database.name" "$partial_dir/owner.name" "$partial_dir/SHA256SUMS"
rmdir -- "$partial_dir" 2>/dev/null || true
fi
}
trap cleanup EXIT HUP INT TERM
if ! docker inspect "$container" >/dev/null 2>&1; then
echo "PostgreSQL container not found: $container" >&2
exit 1
fi
if [ "$(docker inspect -f '{{.State.Running}}' "$container")" != "true" ]; then
echo "PostgreSQL container is not running: $container" >&2
exit 1
fi
mkdir -p -- "$backup_root"
chmod 700 -- "$backup_root"
if [ -e "$partial_dir" ] || [ -e "$backup_dir" ]; then
echo "Backup destination already exists for $timestamp" >&2
exit 1
fi
mkdir -- "$partial_dir"
database="$(docker exec "$container" sh -c 'printf %s "$POSTGRES_DB"')"
owner="$(docker exec "$container" sh -c 'printf %s "$POSTGRES_USER"')"
[ -n "$database" ] && [ -n "$owner" ] || {
echo "Database metadata is empty" >&2
exit 1
}
case "$database:$owner" in
*[!A-Za-z0-9_:.-]*) echo "Unsafe database metadata" >&2; exit 1 ;;
esac
printf '%s\n' "$database" >"$partial_dir/database.name"
printf '%s\n' "$owner" >"$partial_dir/owner.name"
docker exec "$container" sh -c 'exec pg_dump --format=custom --compress=9 --no-password -U "$POSTGRES_USER" -d "$POSTGRES_DB"' >"$partial_dir/assistant.dump"
docker exec "$container" sh -c 'exec pg_dumpall --globals-only --no-role-passwords --no-password -U "$POSTGRES_USER"' >"$partial_dir/globals.sql"
if [ ! -s "$partial_dir/assistant.dump" ] || [ ! -s "$partial_dir/globals.sql" ]; then
echo "Backup output is incomplete" >&2
exit 1
fi
(
cd "$partial_dir"
sha256sum assistant.dump globals.sql database.name owner.name >SHA256SUMS
sha256sum -c SHA256SUMS >/dev/null
)
chmod 600 "$partial_dir"/*
mv -- "$partial_dir" "$backup_dir"
trap - EXIT HUP INT TERM
printf '%s\n' "$backup_dir"