#!/bin/bash # GoChat Database Backup Script # Reference: Chatwoot uses pg_dump for backup in production deployments # Usage: ./scripts/db_backup.sh [env] set -euo pipefail ENV="${1:-production}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_DIR="${GOCHAT_BACKUP_DIR:-/var/backups/gochat}" DSN="${GOCHAT_DATABASE_DSN:-}" RETENTION_DAYS="${GOCHAT_BACKUP_RETENTION_DAYS:-30}" if [[ -z "$DSN" ]]; then echo "[$(date)] ERROR: GOCHAT_DATABASE_DSN is not set" exit 1 fi # Parse DSN: postgres://user:password@host:port/dbname?sslmode=... DB_USER=$(echo "$DSN" | sed 's|.*://||; s|:.*||') DB_PASS=$(echo "$DSN" | sed 's|.*://[^:]*:||; s|@.*||') DB_HOST=$(echo "$DSN" | sed 's|.*@||; s|:.*||') DB_PORT=$(echo "$DSN" | sed 's|.*@.*:||; s|/.*||') DB_NAME=$(echo "$DSN" | sed 's|.*/||; s|\?.*||') mkdir -p "${BACKUP_DIR}" BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.sql.gz" echo "[$(date)] Starting backup of ${DB_NAME} on ${DB_HOST}:${DB_PORT}" # pg_dump with compression — mirrors Chatwoot backup approach PGPASSWORD="${DB_PASS}" pg_dump \ -h "${DB_HOST}" \ -p "${DB_PORT}" \ -U "${DB_USER}" \ -d "${DB_NAME}" \ --format=custom \ --compress=9 \ | gzip > "${BACKUP_FILE}" BACKUP_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1) echo "[$(date)] Backup complete: ${BACKUP_FILE} (${BACKUP_SIZE})" # Prune old backups beyond retention period find "${BACKUP_DIR}" -name "*.sql.gz" -mtime +"${RETENTION_DAYS}" -delete echo "[$(date)] Pruned backups older than ${RETENTION_DAYS} days" # Verify backup integrity gunzip -t "${BACKUP_FILE}" && echo "[$(date)] Backup integrity verified" || { echo "[$(date)] ERROR: Backup integrity check failed!" rm -f "${BACKUP_FILE}" exit 1 }