#!/usr/bin/env bash # Бэкап БД tradein-postgres — pg_dump по cron + retention (#397). # # Запускается из cron на прод-хосте. pg_dump идёт через `docker exec` # (локальный сокет внутри контейнера — пароль не нужен). # # Crontab пример (ежедневно в 04:30 UTC): # 30 4 * * * /opt/gendesign/tradein-mvp/deploy/backup-tradein-db.sh >> /tmp/tradein-backup.log 2>&1 # # Restore: # gunzip -c tradein-YYYYMMDD-HHMMSS.sql.gz | \ # docker exec -i tradein-postgres psql -U tradein -d tradein set -euo pipefail BACKUP_DIR="${BACKUP_DIR:-/opt/gendesign/backups/tradein}" KEEP="${KEEP:-7}" # сколько копий хранить PG_CONTAINER="${PG_CONTAINER:-tradein-postgres}" mkdir -p "$BACKUP_DIR" ts=$(date -u +'%Y%m%d-%H%M%S') out="$BACKUP_DIR/tradein-$ts.sql.gz" # --clean --if-exists → дамп самодостаточен для восстановления «с нуля». # --no-owner → restore не требует тех же ролей. docker exec "$PG_CONTAINER" pg_dump -U tradein -d tradein \ --no-owner --clean --if-exists 2>/dev/null | gzip -6 > "$out" if [[ ! -s "$out" ]]; then echo "[$(date -u +%H:%M:%S)] ОШИБКА: дамп пустой — $out" >&2 rm -f "$out" exit 1 fi # Retention — оставляем KEEP самых свежих, остальные tradein-*.sql.gz удаляем. ls -1t "$BACKUP_DIR"/tradein-*.sql.gz 2>/dev/null \ | tail -n +"$((KEEP + 1))" \ | xargs -r rm -f size=$(du -h "$out" | cut -f1) count=$(ls -1 "$BACKUP_DIR"/tradein-*.sql.gz 2>/dev/null | wc -l | tr -d ' ') echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] backup ok: $out ($size), копий хранится: $count"