#!/usr/bin/env bash # # glitchtip-backup.sh — daily postgres dump for the GlitchTip database. # # Usage: # bash scripts/glitchtip-backup.sh # # Cron example (production host): # # /etc/cron.d/glitchtip-backup # 0 3 * * * crewli /opt/crewli/scripts/glitchtip-backup.sh >> /var/log/glitchtip-backup.log 2>&1 # # Configurable via env vars (defaults shown): # GLITCHTIP_BACKUP_DIR=./backups/glitchtip # GLITCHTIP_BACKUP_RETENTION_DAYS=30 # GLITCHTIP_DB_CONTAINER=glitchtip-postgres # GLITCHTIP_DB_USER=postgres # GLITCHTIP_DB_NAME=glitchtip # # Restore (full): # gunzip < .gz \ # | docker exec -i glitchtip-postgres pg_restore -U postgres -d glitchtip --clean --if-exists # # Per RFC-WS-7-OBSERVABILITY §5 (daily postgres-backup) and acceptance # criterion 11. See dev-docs/GLITCHTIP.md for the full restore drill. set -euo pipefail BACKUP_DIR="${GLITCHTIP_BACKUP_DIR:-./backups/glitchtip}" RETENTION_DAYS="${GLITCHTIP_BACKUP_RETENTION_DAYS:-30}" DB_CONTAINER="${GLITCHTIP_DB_CONTAINER:-glitchtip-postgres}" DB_USER="${GLITCHTIP_DB_USER:-postgres}" DB_NAME="${GLITCHTIP_DB_NAME:-glitchtip}" mkdir -p "$BACKUP_DIR" timestamp="$(date +%Y%m%d-%H%M%S)" output="$BACKUP_DIR/glitchtip-${timestamp}.dump.gz" echo "[$(date -Iseconds)] Dumping ${DB_NAME} from ${DB_CONTAINER} to ${output}" # Stream pg_dump (custom format) directly through gzip — no intermediate file. # `set -o pipefail` already in effect so a pg_dump failure aborts before retention. docker exec -i "$DB_CONTAINER" \ pg_dump -U "$DB_USER" -d "$DB_NAME" --format=custom --no-owner --no-privileges \ | gzip -c > "$output" chmod 0600 "$output" size="$(wc -c < "$output" | tr -d ' ')" echo "[$(date -Iseconds)] Wrote ${output} (${size} bytes)" echo "[$(date -Iseconds)] Pruning dumps older than ${RETENTION_DAYS} days" find "$BACKUP_DIR" -type f -name 'glitchtip-*.dump.gz' -mtime "+${RETENTION_DAYS}" -print -delete echo "[$(date -Iseconds)] Done."