#!/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"