#!/usr/bin/env bash # hudu-backup.sh — Daily Hudu PostgreSQL backup to Wasabi S3. # Source: app2 (152.53.39.202) Docker hudu-db-1 # Target: s3://hermes-vps-backups/hudu/backups/ # Schedule: Daily at 3 AM ET via cron (no_agent) set -euo pipefail SSH_KEY="/root/.ssh/itpp-infra" APP2="root@152.53.39.202" S3_BUCKET="s3://hermes-vps-backups/hudu/backups" ENDPOINT="https://s3.us-east-1.wasabisys.com" TS="$(date -u +%Y%m%d-%H%M%S)" LOCAL="/tmp/hudu-backup-${TS}.dump" RETENTION_DAYS=30 # Cron-safe AWS CLI if [ -f /opt/awscli-venv/bin/activate ]; then source /opt/awscli-venv/bin/activate fi log() { echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $*"; } log "Starting Hudu backup" # Dump from Docker on app2 via SSH if ! ssh -i "$SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes "$APP2" \ "docker exec hudu-db-1 pg_dump -U postgres -d hudu_production --format=custom --compress=9" \ > "$LOCAL" 2>/dev/null; then log "FATAL: pg_dump failed" exit 1 fi SIZE=$(du -h "$LOCAL" | cut -f1) log "Dumped Hudu DB (${SIZE})" # Upload to S3 if aws s3 cp "$LOCAL" "${S3_BUCKET}/hudu_backup_${TS}.dump" \ --endpoint-url "$ENDPOINT" >/dev/null 2>&1; then log "Uploaded: hudu_backup_${TS}.dump" else log "FATAL: S3 upload failed" rm -f "$LOCAL" exit 1 fi # Cleanup old backups aws s3 ls "${S3_BUCKET}/" --endpoint-url "$ENDPOINT" 2>/dev/null | \ awk -v cutoff="$(date -d "${RETENTION_DAYS} days ago" -u +%Y-%m-%d)" \ '$1 < cutoff {print $4}' | while read -r old; do aws s3 rm "${S3_BUCKET}/${old}" --endpoint-url "$ENDPOINT" >/dev/null 2>&1 log "Purged: $old" done rm -f "$LOCAL" log "Backup complete"