#!/bin/bash set -e # Exit on error trap 'log_message "ERROR: An error occurred while executing $COMMAND for $ENV_NAME. Exiting."' ERR # Validate arguments if [ $# -lt 2 ]; then echo "Usage: $0 {backup|backup_wp_core|backup_uploads|backup_database|check_backup_repo|rotate_snapshots|create_snapshot|update_restic}" exit 1 fi # Extract ENV_NAME and COMMAND ENV_NAME="$1" COMMAND="$2" # Set dynamic configurations based on ENV_NAME LOG_FILE="/var/log/${ENV_NAME}_backup_script.log" BACKUP_REPO_PATH="/mnt/backups/${ENV_NAME}" PASSWORD_FILE="/etc/restic-password" LOCK_FILE="/tmp/restic_global.lock" # Ensure dynamic paths exist mkdir -p "$BACKUP_REPO_PATH" # Logging function log_message() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } # Validate password file and set Restic password if [ ! -f "$PASSWORD_FILE" ]; then log_message "ERROR: Password file not found at $PASSWORD_FILE." exit 1 fi export RESTIC_PASSWORD=$(cat "$PASSWORD_FILE") # Ensure Restic is installed install_restic() { if ! which restic &>/dev/null; then log_message "Restic not found. Installing..." if which dnf &>/dev/null; then dnf install -y epel-release && dnf install -y restic elif which yum &>/dev/null; then yum install -y restic else log_message "ERROR: Unsupported package manager." exit 1 fi fi log_message "Restic is installed." } # Acquire global lock to serialize operations acquire_lock() { log_message "Acquiring global lock for Restic operations..." exec 9>"$LOCK_FILE" if ! flock -n 9; then log_message "Another Restic operation is running. Exiting." exit 1 fi log_message "Global lock acquired." } # Release global lock release_lock() { exec 9>&- } # Check and remove stale locks check_stale_locks() { log_message "Checking for stale locks in the repository..." if restic -r "$BACKUP_REPO_PATH" list locks | grep -q "lock"; then log_message "Stale locks detected. Unlocking the repository..." restic -r "$BACKUP_REPO_PATH" unlock log_message "Repository unlocked successfully." else log_message "No stale locks found." fi } # Initialize or validate repository check_backup_repo() { if ! restic -r "$BACKUP_REPO_PATH" snapshots &>/dev/null; then log_message "Initializing new Restic repository..." restic -r "$BACKUP_REPO_PATH" init else log_message "Restic repository validated." fi } # Perform backup operations perform_backup() { local path="$1" local tag="$2" local exclude="$3" log_message "Backing up $path with tag $tag..." restic -r "$BACKUP_REPO_PATH" backup "$path" --tag "$tag" $exclude log_message "Backup for $path completed." } # Backup database backup_database() { log_message "Starting database backup for $ENV_NAME..." local db_dump db_dump=$(mktemp) mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" > "$db_dump" perform_backup "$db_dump" "database-backup" rm -f "$db_dump" log_message "Database backup completed." } # Handle commands case "$COMMAND" in backup) log_message "Starting full backup for environment: $ENV_NAME" install_restic acquire_lock check_stale_locks check_backup_repo perform_backup "/var/www/webroot/ROOT/wp-content" "wp-core" "--exclude /var/www/webroot/ROOT/wp-content/uploads" perform_backup "/var/www/webroot/ROOT/wp-content/uploads" "wp-uploads" backup_database release_lock ;; backup_wp_core) log_message "Backing up WordPress core files for environment: $ENV_NAME" acquire_lock check_stale_locks perform_backup "/var/www/webroot/ROOT/wp-content" "wp-core" "--exclude /var/www/webroot/ROOT/wp-content/uploads" release_lock ;; backup_uploads) log_message "Backing up WordPress uploads for environment: $ENV_NAME" acquire_lock check_stale_locks perform_backup "/var/www/webroot/ROOT/wp-content/uploads" "wp-uploads" release_lock ;; backup_database) acquire_lock check_stale_locks backup_database release_lock ;; check_backup_repo) log_message "Checking backup repository for environment: $ENV_NAME" acquire_lock check_stale_locks check_backup_repo release_lock ;; rotate_snapshots) log_message "Rotating snapshots for environment: $ENV_NAME" acquire_lock restic -r "$BACKUP_REPO_PATH" forget --keep-last 5 --prune release_lock log_message "Snapshot rotation completed." ;; create_snapshot) log_message "Creating snapshot for environment: $ENV_NAME" acquire_lock check_stale_locks restic -r "$BACKUP_REPO_PATH" backup --tag "manual-snapshot" release_lock log_message "Snapshot creation completed." ;; update_restic) log_message "Updating Restic for environment: $ENV_NAME" restic self-update ;; *) echo "Invalid command: $COMMAND" echo "Usage: $0 {backup|backup_wp_core|backup_uploads|backup_database|check_backup_repo|rotate_snapshots|create_snapshot|update_restic}" exit 1 ;; esac