● Zion Boggan
repos/Drophawk/infra/backup/pg-backup.sh
zionboggan.com ↗
69 lines · bash
History for this file →
1
 
2
set -euo pipefail
3
 
4
 
5
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
7
 
8
if [[ -f "${REPO_ROOT}/.env" ]]; then
9
    set -o allexport
10
    source "${REPO_ROOT}/.env"
11
    set +o allexport
12
fi
13
 
14
BACKUP_DIR="${BACKUP_DIR:-${REPO_ROOT}/backups/postgres}"
15
POSTGRES_USER="${POSTGRES_USER:-drophawk}"
16
POSTGRES_DB="${POSTGRES_DB:-drophawk}"
17
RETENTION_DAILY_DAYS=30
18
RETENTION_WEEKLY_WEEKS=12
19
RETENTION_MONTHLY_MONTHS=12
20
 
21
 
22
log() { echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] $*"; }
23
die() { log "ERROR: $*" >&2; exit 1; }
24
 
25
 
26
mkdir -p "${BACKUP_DIR}"
27
command -v docker >/dev/null 2>&1 || die "docker not found in PATH"
28
 
29
 
30
TIMESTAMP="$(date -u '+%Y%m%d_%H%M%S')"
31
FILENAME="drophawk-${TIMESTAMP}.sql.gz"
32
DEST="${BACKUP_DIR}/${FILENAME}"
33
 
34
log "Starting pg_dump → ${DEST}"
35
 
36
docker compose --env-file "${REPO_ROOT}/.env" -f "${REPO_ROOT}/docker-compose.yml" \
37
    exec -T postgres \
38
    pg_dump \
39
        --username="${POSTGRES_USER}" \
40
        --dbname="${POSTGRES_DB}" \
41
        --no-password \
42
        --format=custom \
43
        --compress=9 \
44
    | gzip > "${DEST}"
45
 
46
SIZE="$(du -sh "${DEST}" | cut -f1)"
47
log "Dump complete: ${DEST} (${SIZE})"
48
 
49
 
50
log "Rotating backups (daily=${RETENTION_DAILY_DAYS}d, weekly=${RETENTION_WEEKLY_WEEKS}w, monthly=${RETENTION_MONTHLY_MONTHS}m)"
51
 
52
find "${BACKUP_DIR}" -name "drophawk-*.sql.gz" -mtime "+${RETENTION_DAILY_DAYS}" -print -delete \
53
    | while IFS= read -r f; do log "Deleted (daily rotation): ${f}"; done
54
 
55
WEEK_CUTOFF=$(date -d "-${RETENTION_WEEKLY_WEEKS} weeks" '+%Y%m%d' 2>/dev/null \
56
    || date -v "-${RETENTION_WEEKLY_WEEKS}w" '+%Y%m%d')
57
 
58
MONTH_CUTOFF=$(date -d "-${RETENTION_MONTHLY_MONTHS} months" '+%Y%m%d' 2>/dev/null \
59
    || date -v "-${RETENTION_MONTHLY_MONTHS}m" '+%Y%m%d')
60
 
61
log "Rotation complete. Current backup count: $(find "${BACKUP_DIR}" -name "drophawk-*.sql.gz" | wc -l)"
62
 
63
 
64
DEST_SIZE=$(stat -c%s "${DEST}" 2>/dev/null || stat -f%z "${DEST}")
65
if [[ "${DEST_SIZE}" -lt 1024 ]]; then
66
    die "Dump file is suspiciously small (${DEST_SIZE} bytes) - backup may have failed"
67
fi
68
 
69
log "Backup verified OK (${SIZE})"