#!/bin/bash # Horux360 Database Backup Script # Backs up all databases (central + tenant) with daily/weekly rotation # Requires: .pgpass file at /root/.pgpass with format: localhost:5432:*:postgres: # # Usage: Add to crontab: # 0 1 * * * /root/Horux/scripts/backup.sh >> /var/log/horux-backup.log 2>&1 set -euo pipefail BACKUP_DIR="/var/horux/backups" DAILY_DIR="$BACKUP_DIR/daily" WEEKLY_DIR="$BACKUP_DIR/weekly" PG_USER="postgres" PG_HOST="localhost" DATE=$(date +%Y-%m-%d) DAY_OF_WEEK=$(date +%u) # Retention DAILY_KEEP=7 WEEKLY_KEEP=4 echo "=== Horux360 Backup Started: $(date) ===" # Create directories mkdir -p "$DAILY_DIR" "$WEEKLY_DIR" # Get list of all horux databases (central + tenant) DATABASES=$(psql -h "$PG_HOST" -U "$PG_USER" -t -c \ "SELECT datname FROM pg_database WHERE datname = 'horux360' OR datname LIKE 'horux_%' AND datname NOT LIKE '%_deleted_%'" \ | tr -d ' ') TOTAL=0 ERRORS=0 for DB in $DATABASES; do echo "Backing up: $DB" DUMP_FILE="$DAILY_DIR/${DB}_${DATE}.sql.gz" if pg_dump -h "$PG_HOST" -U "$PG_USER" "$DB" | gzip > "$DUMP_FILE"; then # Verify file is not empty if [ -s "$DUMP_FILE" ]; then TOTAL=$((TOTAL + 1)) echo " OK: $(du -h "$DUMP_FILE" | cut -f1)" else echo " WARNING: Empty backup file for $DB" rm -f "$DUMP_FILE" ERRORS=$((ERRORS + 1)) fi else echo " ERROR: Failed to backup $DB" ERRORS=$((ERRORS + 1)) fi done # Weekly backup on Sundays (day 7) if [ "$DAY_OF_WEEK" -eq 7 ]; then echo "Creating weekly backup..." cp "$DAILY_DIR"/*_"${DATE}".sql.gz "$WEEKLY_DIR/" 2>/dev/null || true fi # Clean old daily backups echo "Cleaning daily backups older than $DAILY_KEEP days..." find "$DAILY_DIR" -name "*.sql.gz" -mtime "+$DAILY_KEEP" -delete # Clean old weekly backups echo "Cleaning weekly backups older than $WEEKLY_KEEP weeks..." find "$WEEKLY_DIR" -name "*.sql.gz" -mtime "+$((WEEKLY_KEEP * 7))" -delete echo "=== Backup Complete: $TOTAL databases backed up, $ERRORS errors ===" echo "=== Finished: $(date) ==="