← back to Watches
scripts/backup-automation.sh
345 lines
#!/bin/bash
################################################################################
# OMEGA WATCHES - AUTOMATED BACKUP SYSTEM
# Supports daily, weekly, monthly backups with retention policies
################################################################################
set -euo pipefail
# Configuration
APP_NAME="omega-watches"
APP_DIR="/root/Projects/watches"
BACKUP_ROOT="$APP_DIR/backups"
DAILY_DIR="$BACKUP_ROOT/daily"
WEEKLY_DIR="$BACKUP_ROOT/weekly"
MONTHLY_DIR="$BACKUP_ROOT/monthly"
LOG_FILE="$APP_DIR/logs/backup-$(date +%Y%m%d).log"
# Retention policies (in days)
DAILY_RETENTION=7
WEEKLY_RETENTION=30
MONTHLY_RETENTION=365
# Remote backup (optional - configure as needed)
REMOTE_BACKUP_ENABLED=false
REMOTE_HOST=""
REMOTE_DIR=""
REMOTE_USER=""
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Logging
mkdir -p "$(dirname "$LOG_FILE")"
log() {
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}
log_error() {
echo -e "${RED}[$(date +'%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" | tee -a "$LOG_FILE"
}
log_warning() {
echo -e "${YELLOW}[$(date +'%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" | tee -a "$LOG_FILE"
}
# Create backup directories
setup_directories() {
mkdir -p "$DAILY_DIR" "$WEEKLY_DIR" "$MONTHLY_DIR"
mkdir -p "$APP_DIR/logs"
}
# Perform backup
perform_backup() {
local backup_type=$1
local backup_dir=$2
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="$backup_dir/backup-${backup_type}-${timestamp}.tar.gz"
log "Creating $backup_type backup..."
cd "$APP_DIR"
# Create backup archive
tar -czf "$backup_file" \
--exclude='node_modules' \
--exclude='backups' \
--exclude='logs/*.log' \
--exclude='.git' \
--exclude='deploy-green' \
--exclude='*.tmp' \
data/ \
dist/ \
server.js \
package.json \
public/ \
ecosystem.config.cjs \
monitoring/ \
nginx/ \
scripts/ \
2>/dev/null || true
if [ -f "$backup_file" ]; then
local size=$(du -h "$backup_file" | cut -f1)
log "Backup created: $(basename "$backup_file") (Size: $size) ✓"
# Calculate checksum
local checksum=$(sha256sum "$backup_file" | cut -d' ' -f1)
echo "$checksum $(basename "$backup_file")" > "$backup_file.sha256"
echo "$backup_file"
return 0
else
log_error "Backup creation failed!"
return 1
fi
}
# Daily backup
daily_backup() {
log "=== DAILY BACKUP STARTED ==="
if perform_backup "daily" "$DAILY_DIR"; then
cleanup_old_backups "$DAILY_DIR" $DAILY_RETENTION
log "Daily backup completed ✓"
else
log_error "Daily backup failed!"
return 1
fi
}
# Weekly backup
weekly_backup() {
log "=== WEEKLY BACKUP STARTED ==="
if perform_backup "weekly" "$WEEKLY_DIR"; then
cleanup_old_backups "$WEEKLY_DIR" $WEEKLY_RETENTION
log "Weekly backup completed ✓"
else
log_error "Weekly backup failed!"
return 1
fi
}
# Monthly backup
monthly_backup() {
log "=== MONTHLY BACKUP STARTED ==="
if perform_backup "monthly" "$MONTHLY_DIR"; then
cleanup_old_backups "$MONTHLY_DIR" $MONTHLY_RETENTION
log "Monthly backup completed ✓"
else
log_error "Monthly backup failed!"
return 1
fi
}
# Cleanup old backups
cleanup_old_backups() {
local dir=$1
local retention_days=$2
log "Cleaning up backups older than $retention_days days in $(basename "$dir")..."
find "$dir" -name "backup-*.tar.gz" -mtime +$retention_days -delete 2>/dev/null || true
find "$dir" -name "backup-*.tar.gz.sha256" -mtime +$retention_days -delete 2>/dev/null || true
local count=$(ls -1 "$dir"/backup-*.tar.gz 2>/dev/null | wc -l)
log "Remaining backups in $(basename "$dir"): $count"
}
# Upload to remote server (if enabled)
upload_to_remote() {
local backup_file=$1
if [ "$REMOTE_BACKUP_ENABLED" != "true" ]; then
return 0
fi
if [ -z "$REMOTE_HOST" ] || [ -z "$REMOTE_DIR" ] || [ -z "$REMOTE_USER" ]; then
log_warning "Remote backup not configured properly. Skipping upload."
return 0
fi
log "Uploading backup to remote server..."
scp "$backup_file" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" 2>&1 | tee -a "$LOG_FILE"
scp "$backup_file.sha256" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" 2>&1 | tee -a "$LOG_FILE"
if [ $? -eq 0 ]; then
log "Remote upload completed ✓"
else
log_error "Remote upload failed!"
fi
}
# List all backups
list_backups() {
echo ""
echo "=== BACKUP INVENTORY ==="
echo ""
echo "DAILY BACKUPS:"
ls -lh "$DAILY_DIR"/backup-*.tar.gz 2>/dev/null || echo " No daily backups found"
echo ""
echo "WEEKLY BACKUPS:"
ls -lh "$WEEKLY_DIR"/backup-*.tar.gz 2>/dev/null || echo " No weekly backups found"
echo ""
echo "MONTHLY BACKUPS:"
ls -lh "$MONTHLY_DIR"/backup-*.tar.gz 2>/dev/null || echo " No monthly backups found"
echo ""
}
# Show backup statistics
show_stats() {
echo ""
echo "=== BACKUP STATISTICS ==="
echo ""
local daily_count=$(ls -1 "$DAILY_DIR"/backup-*.tar.gz 2>/dev/null | wc -l)
local weekly_count=$(ls -1 "$WEEKLY_DIR"/backup-*.tar.gz 2>/dev/null | wc -l)
local monthly_count=$(ls -1 "$MONTHLY_DIR"/backup-*.tar.gz 2>/dev/null | wc -l)
local daily_size=$(du -sh "$DAILY_DIR" 2>/dev/null | cut -f1)
local weekly_size=$(du -sh "$WEEKLY_DIR" 2>/dev/null | cut -f1)
local monthly_size=$(du -sh "$MONTHLY_DIR" 2>/dev/null | cut -f1)
local total_size=$(du -sh "$BACKUP_ROOT" 2>/dev/null | cut -f1)
echo "Daily Backups: $daily_count files ($daily_size)"
echo "Weekly Backups: $weekly_count files ($weekly_size)"
echo "Monthly Backups: $monthly_count files ($monthly_size)"
echo ""
echo "Total Backup Size: $total_size"
echo ""
# Latest backups
echo "Latest Backups:"
echo " Daily: $(ls -t "$DAILY_DIR"/backup-*.tar.gz 2>/dev/null | head -1 | xargs basename 2>/dev/null || echo 'None')"
echo " Weekly: $(ls -t "$WEEKLY_DIR"/backup-*.tar.gz 2>/dev/null | head -1 | xargs basename 2>/dev/null || echo 'None')"
echo " Monthly: $(ls -t "$MONTHLY_DIR"/backup-*.tar.gz 2>/dev/null | head -1 | xargs basename 2>/dev/null || echo 'None')"
echo ""
}
# Restore from backup
restore_backup() {
local backup_file=$1
if [ -z "$backup_file" ]; then
log_error "No backup file specified!"
echo "Usage: $0 restore <backup-file>"
return 1
fi
if [ ! -f "$backup_file" ]; then
log_error "Backup file not found: $backup_file"
return 1
fi
# Verify checksum if available
if [ -f "$backup_file.sha256" ]; then
log "Verifying backup integrity..."
if sha256sum -c "$backup_file.sha256" 2>&1 | grep -q OK; then
log "Backup integrity verified ✓"
else
log_error "Backup integrity check failed!"
return 1
fi
fi
log "Restoring from: $backup_file"
# Create restore point
local restore_point="$BACKUP_ROOT/pre-restore-$(date +%Y%m%d_%H%M%S).tar.gz"
log "Creating restore point: $restore_point"
perform_backup "pre-restore" "$BACKUP_ROOT" > /dev/null
# Stop application
log "Stopping application..."
pm2 stop $APP_NAME 2>/dev/null || true
# Extract backup
log "Extracting backup..."
cd "$APP_DIR"
tar -xzf "$backup_file"
# Restart application
log "Restarting application..."
pm2 restart $APP_NAME 2>/dev/null || pm2 start ecosystem.config.cjs --name $APP_NAME
log "Restore completed ✓"
log "Application URL: http://45.61.58.125:7500"
}
# Verify backup integrity
verify_backups() {
log "Verifying backup integrity..."
local failed=0
for backup_dir in "$DAILY_DIR" "$WEEKLY_DIR" "$MONTHLY_DIR"; do
for backup in "$backup_dir"/backup-*.tar.gz; do
if [ -f "$backup" ]; then
if [ -f "$backup.sha256" ]; then
if sha256sum -c "$backup.sha256" 2>&1 | grep -q OK; then
log "✓ $(basename "$backup")"
else
log_error "✗ $(basename "$backup") - Checksum mismatch!"
((failed++))
fi
else
log_warning "⚠ $(basename "$backup") - No checksum file"
fi
fi
done
done
if [ $failed -eq 0 ]; then
log "All backups verified successfully ✓"
else
log_error "$failed backup(s) failed verification!"
fi
}
# Main function
main() {
setup_directories
case "${1:-daily}" in
daily)
daily_backup
;;
weekly)
weekly_backup
;;
monthly)
monthly_backup
;;
list)
list_backups
;;
stats)
show_stats
;;
restore)
restore_backup "${2:-}"
;;
verify)
verify_backups
;;
*)
echo "Usage: $0 {daily|weekly|monthly|list|stats|restore <file>|verify}"
exit 1
;;
esac
}
# Run main function
main "$@"