Files
wownerogue/scripts/deploy/wowngeon-db-backup.sh
T

49 lines
2.0 KiB
Bash

#!/bin/sh
set -eu
# Atomic daily custom-format dumps for both production instances. Run as the postgres OS user;
# the service unit grants write access only to this dedicated directory.
backup_root=${BACKUP_ROOT:-/var/backups/wowngeon/daily}
retention_days=${BACKUP_RETENTION_DAYS:-14}
stamp=$(/usr/bin/date -u +%Y%m%dT%H%M%SZ)
[ "$backup_root" = /var/backups/wowngeon/daily ] || {
echo "Refusing an unapproved backup root: $backup_root" >&2
exit 64
}
case "$retention_days" in
''|*[!0-9]*) echo "BACKUP_RETENTION_DAYS must be a positive integer" >&2; exit 64 ;;
esac
[ "$retention_days" -gt 0 ] || { echo "BACKUP_RETENTION_DAYS must be positive" >&2; exit 64; }
[ -d "$backup_root" ] && [ ! -L "$backup_root" ] || {
echo "Backup root is missing or is a symlink" >&2
exit 66
}
for database_name in wownerogue monerogue; do
final_path="${backup_root}/${database_name}-${stamp}.dump"
temporary_path="${backup_root}/.${database_name}-${stamp}.dump.tmp"
checksum_path="${final_path}.sha256"
checksum_temporary="${checksum_path}.tmp"
/usr/bin/pg_dump --format=custom --no-owner --file="$temporary_path" "$database_name"
/usr/bin/pg_restore --list "$temporary_path" >/dev/null
/usr/bin/chmod 0600 "$temporary_path"
/usr/bin/mv "$temporary_path" "$final_path"
(
cd "$backup_root"
/usr/bin/sha256sum "$(/usr/bin/basename "$final_path")"
) >"$checksum_temporary"
/usr/bin/chmod 0600 "$checksum_temporary"
/usr/bin/mv "$checksum_temporary" "$checksum_path"
done
# Local copies are an operational convenience, not the retention archive. The independently
# encrypted restic vault keeps GFS history; bound this same-disk directory so it cannot fill `/`.
/usr/bin/find "$backup_root" -maxdepth 1 -type f \
\( -name 'monerogue-*.dump' -o -name 'monerogue-*.dump.sha256' \
-o -name 'wownerogue-*.dump' -o -name 'wownerogue-*.dump.sha256' \) \
-mtime "+$retention_days" -delete
/usr/bin/find "$backup_root" -maxdepth 1 -type f -name '.*.tmp' -mtime +1 -delete