67 lines
2.2 KiB
Bash
Executable File
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"
|