#!/bin/bash # Automated Database Backup Script # Runs as a Kubernetes CronJob for daily backups set -e # Configuration BACKUP_DIR="${BACKUP_DIR:-/backups/postgres}" DB_NAME="${DB_NAME:-sankofa}" DB_HOST="${DB_HOST:-postgres}" DB_PORT="${DB_PORT:-5432}" DB_USER="${DB_USER:-postgres}" RETENTION_DAYS="${RETENTION_DAYS:-7}" TIMESTAMP=$(date +%Y%m%d_%H%M%S) BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.sql" # Colors GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } # Create backup directory if it doesn't exist mkdir -p "$BACKUP_DIR" # Perform backup perform_backup() { log_info "Starting database backup..." log_info "Database: ${DB_NAME}" log_info "Backup file: ${BACKUP_FILE}" # Check if pg_dump is available if ! command -v pg_dump &> /dev/null; then log_error "pg_dump not found. Install PostgreSQL client tools." exit 1 fi # Perform backup if pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" \ -F p -f "$BACKUP_FILE" 2>&1; then log_info "Backup completed successfully" # Compress backup log_info "Compressing backup..." gzip "$BACKUP_FILE" BACKUP_FILE="${BACKUP_FILE}.gz" # Get backup size BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1) log_info "Backup size: ${BACKUP_SIZE}" # Verify backup integrity if gzip -t "$BACKUP_FILE" 2>/dev/null; then log_info "Backup integrity verified" else log_error "Backup integrity check failed" exit 1 fi return 0 else log_error "Backup failed" exit 1 fi } # Clean up old backups cleanup_old_backups() { log_info "Cleaning up backups older than ${RETENTION_DAYS} days..." local deleted_count=0 while IFS= read -r -d '' backup_file; do log_info "Deleting old backup: $(basename "$backup_file")" rm -f "$backup_file" ((deleted_count++)) done < <(find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" -type f -mtime +$RETENTION_DAYS -print0) if [ $deleted_count -gt 0 ]; then log_info "Deleted ${deleted_count} old backup(s)" else log_info "No old backups to delete" fi } # Upload to S3 (optional) upload_to_s3() { if [ -n "$S3_BUCKET" ] && command -v aws &> /dev/null; then log_info "Uploading backup to S3..." S3_PATH="s3://${S3_BUCKET}/postgres-backups/$(basename "$BACKUP_FILE")" if aws s3 cp "$BACKUP_FILE" "$S3_PATH"; then log_info "Backup uploaded to S3: ${S3_PATH}" else log_warn "Failed to upload backup to S3" fi fi } # Send notification (optional) send_notification() { if [ -n "$WEBHOOK_URL" ]; then local status="$1" local message="Database backup ${status}: ${BACKUP_FILE}" curl -X POST "$WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d "{\"text\": \"${message}\"}" \ > /dev/null 2>&1 || true fi } # Main execution main() { log_info "==========================================" log_info "Database Backup Automation" log_info "==========================================" log_info "" # Perform backup if perform_backup; then # Clean up old backups cleanup_old_backups # Upload to S3 if configured upload_to_s3 # Send success notification send_notification "succeeded" log_info "Backup process completed successfully" exit 0 else # Send failure notification send_notification "failed" log_error "Backup process failed" exit 1 fi } main "$@"