Ver 1.7 Improved restoration script, Automatic Backup Tagging, Resolved issues with incorrect handling of database restoration paths

main
Anthony 2025-01-08 00:46:12 +08:00
parent a2f0cf6634
commit a36be25ae9
5 changed files with 292 additions and 157 deletions

View File

@ -1,5 +1,50 @@
# Changelog # Changelog
## Version 1.7
### Added
- **`restore_backup_direct.sh` Enhancements**:
- Improved restoration script to handle specific backup types (core files, media files, database backups) based on tags.
- Integrated functionality to restore databases directly by piping `.sql` files from Restic to MySQL.
- Added automatic detection of database credentials from `wp-config.php` with fallback to default values for `DB_HOST`.
- Ensured proper environment setup with `RESTIC_PASSWORD` retrieved securely from `/etc/restic-password`.
- **Automatic Backup Tagging**:
- Modified `backup_all.sh` to differentiate between manual (`manual-backup-YYYY-MM-DD_HH-MM-SS`) and automated (`auto-backup-YYYY-MM-DD_HH-MM-SS`) backups.
- Ensured backups triggered by cron jobs are tagged appropriately for easy identification.
- **`manage_backup_schedule.sh` Enhancements**:
- Ensured `backup_all.sh` runs in `auto` mode when added to cron, guaranteeing automated backups have the correct tags.
- Validated cron job syntax and dependencies to avoid misconfigurations.
- Added explicit logging of cron actions, including schedule additions, updates, removals, and listing.
- **Improved Error Messaging**:
- Enhanced restoration script to provide detailed error messages when database restoration fails, including incorrect credentials or insufficient privileges.
### Fixed
- Resolved issues with incorrect handling of database restoration paths, ensuring `.sql` files are restored directly into MySQL when detected.
- Addressed potential confusion in tagging by clearly segregating manual and automated backups in logs and tags.
- Corrected empty `DB_HOST` values in the restoration script by setting a default to `localhost` when no value is provided in `wp-config.php`.
### Updated
- **Logging and Traceability**:
- Enhanced all relevant scripts (`restore_backup_direct.sh`, `backup_all.sh`, `manage_backup_schedule.sh`) to log detailed timestamps and descriptive messages.
- Improved consistency in log formatting across scripts for better traceability.
- Added detailed logs for all cron operations in `manage_backup_schedule.sh` to track automated backups effectively.
### Improved
- **Backup and Restore Modularity**:
- Streamlined the orchestration of backups and restores to ensure modularity and easier debugging.
- Improved robustness of `restore_backup_direct.sh` by handling different backup types dynamically using snapshot tags.
- Simplified management of cron schedules with better error handling and validation in `manage_backup_schedule.sh`.
- **Error Handling**:
- Ensured all scripts exit gracefully on errors with detailed logs to pinpoint issues.
- Enhanced dependency validation to check for all required tools (`restic`, `mysql`, `jq`, `crontab`, etc.) before execution.
- **Code Maintenance**:
- Centralized key operations such as password retrieval, lock handling, and backup tagging across scripts for easier maintenance and fewer redundancies.
## Version 1.6 ## Version 1.6
### Added ### Added

View File

@ -1,5 +1,5 @@
type: update type: update
jpsVersion: 1.6 jpsVersion: 1.7
name: MightyBox WordPress Backup/Restore Addon name: MightyBox WordPress Backup/Restore Addon
id: mb-backup-manager id: mb-backup-manager
description: Custom Backup and Restore Addon for WordPress using Restic. Supports backing up databases, core files, media files, and full backups with scheduling and retention policies. description: Custom Backup and Restore Addon for WordPress using Restic. Supports backing up databases, core files, media files, and full backups with scheduling and retention policies.
@ -52,6 +52,12 @@ menu:
title: Configure Automated Backup Schedule title: Configure Automated Backup Schedule
submitButtonText: Save Schedule submitButtonText: Save Schedule
- caption: List Scheduled Backups
action: listScheduledBackups
confirmText: List scheduled backups?
loadingText: Listing scheduled backups...
successText: Scheduled backups listed successfully
- caption: Remove Auto Backup - caption: Remove Auto Backup
action: removeAutoBackup action: removeAutoBackup
confirmText: Remove automated backup schedule? confirmText: Remove automated backup schedule?
@ -160,6 +166,14 @@ actions:
type: info type: info
message: "Daily backup schedule configured successfully" message: "Daily backup schedule configured successfully"
listScheduledBackups:
- cmd[cp]:
user: root
commands: bash /home/litespeed/mb-backups/manage_backup_schedule.sh list
- return:
type: info
message: "${response.out}"
removeAutoBackup: removeAutoBackup:
- cmd[cp]: - cmd[cp]:
user: root user: root
@ -179,7 +193,7 @@ actions:
backupnow: backupnow:
- cmd[cp]: - cmd[cp]:
user: root user: root
commands: bash /home/jelastic/mb-backups/backup_all.sh backup_now commands: bash /home/jelastic/mb-backups/backup_all.sh manual
- return: - return:
type: info type: info
message: "${response.out}" message: "${response.out}"
@ -332,7 +346,8 @@ actions:
- mkdir -p /home/litespeed/mb-backups/logs/auto - mkdir -p /home/litespeed/mb-backups/logs/auto
- mkdir -p /home/litespeed/mb-backups/logs/manual - mkdir -p /home/litespeed/mb-backups/logs/manual
- mkdir -p /home/litespeed/mb-backups/logs/restore - mkdir -p /home/litespeed/mb-backups/logs/restore
- chown -R litespeed:litespeed /home/litespeed/mb-backups - sudo chown -R litespeed:litespeed /home/litespeed/mb-backups/logs
- sudo chmod -R u+rw /home/litespeed/mb-backups/logs
- cd /home/jelastic/mb-backups - cd /home/jelastic/mb-backups
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/backup_all.sh - curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/backup_all.sh
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/backup_core_files.sh - curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/backup_core_files.sh

View File

@ -9,7 +9,7 @@ LOG_DIR="/home/jelastic/mb-backups/logs"
CORE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_core_files.sh" CORE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_core_files.sh"
DATABASE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_database.sh" DATABASE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_database.sh"
MEDIA_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_media.sh" MEDIA_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_media.sh"
MANUAL_BACKUP_TAG="manual-backup-$(date +'%Y-%m-%d_%H-%M-%S')" TIMESTAMP=$(date +'%Y-%m-%d_%H-%M-%S')
# Ensure log directory exists # Ensure log directory exists
mkdir -p "$LOG_DIR" mkdir -p "$LOG_DIR"
@ -22,24 +22,37 @@ log_message() {
# Main execution # Main execution
main() { main() {
log_message "Starting full backup process with tag: $MANUAL_BACKUP_TAG" local backup_type="$1"
local backup_tag=""
# Determine the backup tag based on the type
if [ "$backup_type" == "manual" ]; then
backup_tag="manual-backup-$TIMESTAMP"
log_message "Starting manual backup process with tag: $backup_tag"
elif [ "$backup_type" == "auto" ]; then
backup_tag="automated-backup-$TIMESTAMP"
log_message "Starting automated backup process with tag: $backup_tag"
else
log_message "ERROR: Invalid backup type. Use 'manual' or 'auto'."
exit 1
fi
# Run individual backup scripts # Run individual backup scripts
if bash "$CORE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$MANUAL_BACKUP_TAG"; then if bash "$CORE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Core files backup completed successfully." log_message "Core files backup completed successfully."
else else
log_message "ERROR: Core files backup failed." log_message "ERROR: Core files backup failed."
exit 1 exit 1
fi fi
if bash "$DATABASE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$MANUAL_BACKUP_TAG"; then if bash "$DATABASE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Database backup completed successfully." log_message "Database backup completed successfully."
else else
log_message "ERROR: Database backup failed." log_message "ERROR: Database backup failed."
exit 1 exit 1
fi fi
if bash "$MEDIA_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$MANUAL_BACKUP_TAG"; then if bash "$MEDIA_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Media files backup completed successfully." log_message "Media files backup completed successfully."
else else
log_message "ERROR: Media files backup failed." log_message "ERROR: Media files backup failed."
@ -50,9 +63,20 @@ main() {
} }
# Argument handling # Argument handling
if [ "$1" == "backup_now" ]; then if [ "$#" -ne 1 ]; then
main echo "Usage: $0 {manual|auto}"
else
echo "Usage: $0 backup_now"
exit 1 exit 1
fi fi
case "$1" in
manual)
main "manual"
;;
auto)
main "auto"
;;
*)
echo "Usage: $0 {manual|auto}"
exit 1
;;
esac

View File

@ -5,44 +5,53 @@ BACKUP_SCRIPT="/home/litespeed/mb-backups/backup_all.sh"
LOG_DIR="/home/litespeed/mb-backups/logs/auto" LOG_DIR="/home/litespeed/mb-backups/logs/auto"
ACTION_LOG_FILE="${LOG_DIR}/schedule_actions.log" ACTION_LOG_FILE="${LOG_DIR}/schedule_actions.log"
BACKUP_LOG_PREFIX="${LOG_DIR}/backup_" BACKUP_LOG_PREFIX="${LOG_DIR}/backup_"
CRON_FILE="/var/spool/cron/crontabs/$(whoami)"
CRON_PATH="/usr/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Ensure the log directory exists # Ensure the log directory exists
mkdir -p "$LOG_DIR" mkdir -p "$LOG_DIR"
# Logging function
log_action() { log_action() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$ACTION_LOG_FILE" echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$ACTION_LOG_FILE"
} }
# Function: Validate dependencies
validate_dependencies() {
for cmd in dnf crontab systemctl restic; do
if ! command -v "$cmd" &>/dev/null; then
log_action "ERROR: Required command '$cmd' not found."
exit 1
fi
done
}
# Function: Install and start cron service if needed
check_and_install_cron() { check_and_install_cron() {
if ! command -v crontab &> /dev/null; then if ! command -v crontab &>/dev/null; then
echo "Cron is not installed. Installing..." log_action "Cron is not installed. Installing..."
sudo dnf install -y cronie || { echo "Failed to install cron."; exit 1; } sudo dnf install -y cronie || { log_action "Failed to install cron."; exit 1; }
fi fi
if ! systemctl is-active --quiet crond; then if ! systemctl is-active --quiet crond; then
echo "Starting cron service..." log_action "Starting cron service..."
sudo systemctl start crond sudo systemctl start crond
sudo systemctl enable crond sudo systemctl enable crond || { log_action "Failed to enable cron service."; exit 1; }
fi fi
if systemctl is-active --quiet crond; then log_action "Cron service is running and ready."
echo "Cron service is running."
else
echo "Failed to start cron service."
log_action "Failed to start cron service."
exit 1
fi
} }
# Function: Validate cron schedule format
validate_cron_syntax() { validate_cron_syntax() {
local schedule="$1" local schedule="$1"
if ! echo "$schedule" | grep -Eq '^(\*|[0-9]|[0-5][0-9]) (\*|[0-9]|1[0-9]|2[0-3]) (\*|[0-9]|3[0-1]) (\*|[1-9]|1[0-2]) (\*|[0-6])$'; then if ! echo "$schedule" | grep -Eq '^(\*|[0-9]|[0-5][0-9]) (\*|[0-9]|1[0-9]|2[0-3]) (\*|[0-9]|3[0-1]) (\*|[1-9]|1[0-2]) (\*|[0-6])$'; then
echo "Invalid cron schedule format: $schedule" log_action "ERROR: Invalid cron schedule format: $schedule"
log_action "Invalid cron schedule format: $schedule"
exit 1 exit 1
fi fi
} }
# Function: Add or update a cron job
add_update_cron_job() { add_update_cron_job() {
local action="$1" local action="$1"
local schedule="$2" local schedule="$2"
@ -51,46 +60,44 @@ add_update_cron_job() {
validate_cron_syntax "$schedule" validate_cron_syntax "$schedule"
if [ -z "$restic_password" ]; then if [ -z "$restic_password" ]; then
echo "Restic password is required." log_action "ERROR: Restic password is required."
log_action "Attempted to $action a schedule without providing a Restic password."
exit 1
fi
local restic_path="/usr/local/bin/restic"
if [ ! -x "$restic_path" ]; then
echo "Error: restic not found at $restic_path. Please verify installation."
log_action "restic not found at $restic_path"
exit 1 exit 1
fi fi
# Prepare the cron job command # Prepare the cron job command
local cmd="SHELL=/bin/bash" local cmd="SHELL=/bin/bash PATH=$CRON_PATH RESTIC_PASSWORD=\"$restic_password\""
cmd+=" PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" cmd+=" $BACKUP_SCRIPT auto"
cmd+=" RESTIC_PASSWORD=\"$restic_password\""
cmd+=" $BACKUP_SCRIPT"
cmd+=" > \"${BACKUP_LOG_PREFIX}\$(date +\\%Y-\\%m-\\%d_\\%H-\\%M-\\%S).log\" 2>&1" cmd+=" > \"${BACKUP_LOG_PREFIX}\$(date +\\%Y-\\%m-\\%d_\\%H-\\%M-\\%S).log\" 2>&1"
# Debug: Output the command to verify # Remove existing job and add a new one
echo "Adding the following cron job:"
echo "$schedule $cmd"
# Remove any existing lines containing $BACKUP_SCRIPT, then add the new one
(crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT"; echo "$schedule $cmd") | crontab - (crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT"; echo "$schedule $cmd") | crontab -
if crontab -l | grep -q "$BACKUP_SCRIPT"; then if crontab -l | grep -q "$BACKUP_SCRIPT auto"; then
echo "Cron job $action successfully."
log_action "Cron job $action successfully: $schedule" log_action "Cron job $action successfully: $schedule"
else else
echo "Failed to $action cron job. Please check logs for details." log_action "ERROR: Failed to $action cron job. Please check logs."
log_action "Failed to $action cron job: $schedule"
exit 1 exit 1
fi fi
} }
# Main execution # Function: Remove cron jobs
check_and_install_cron remove_cron_jobs() {
crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT auto" | crontab -
log_action "All backup schedules removed."
}
case $1 in # Function: List cron jobs
list_cron_jobs() {
log_action "Listing all current cron jobs:"
crontab -l 2>/dev/null | tee -a "$ACTION_LOG_FILE"
}
# Main execution
main() {
validate_dependencies
check_and_install_cron
case "$1" in
add|update) add|update)
if [ "$#" -ne 3 ]; then if [ "$#" -ne 3 ]; then
echo "Usage for add/update: $0 {add|update} 'schedule' 'restic_password'" echo "Usage for add/update: $0 {add|update} 'schedule' 'restic_password'"
@ -101,16 +108,18 @@ case $1 in
fi fi
;; ;;
remove) remove)
tmp_cron=$(mktemp) remove_cron_jobs
crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT" > "$tmp_cron" ;;
crontab "$tmp_cron" list)
rm -f "$tmp_cron" list_cron_jobs
echo "All backup schedules removed."
log_action "All backup schedules removed."
;; ;;
*) *)
echo "Invalid action: $1. Use add, update, or remove." echo "Usage: $0 {add|update|remove|list} [schedule] [restic_password]"
log_action "Invalid action attempted: $1" log_action "Invalid action attempted: $1"
exit 1 exit 1
;; ;;
esac esac
}
# Execute main function
main "$@"

View File

@ -1,23 +1,23 @@
#!/bin/bash #!/bin/bash
# Exit immediately on errors # Exit on errors and enable error tracing
set -e set -e
trap 'log "ERROR: An error occurred during the restoration process."' ERR
# Validate input parameters # Validate input parameters
if [ "$#" -ne 2 ]; then if [ "$#" -ne 1 ]; then
echo "Usage: $0 <snapshot_id> <restic_password>" echo "Usage: $0 <snapshot_id>"
exit 1 exit 1
fi fi
# Assign input to variables # Assign input to variables
SNAPSHOT_ID=$1 SNAPSHOT_ID=$1
RESTIC_PASSWORD=$2 RESTIC_PASSWORD_FILE="/etc/restic-password"
RESTIC_REPOSITORY="/mnt/backups" RESTIC_REPOSITORY="/mnt/backups"
LOG_DIR="/home/litespeed/mb-backups/logs/restore" LOG_DIR="/home/litespeed/mb-backups/logs/restore"
WP_CONFIG="/var/www/webroot/ROOT/wp-config.php" WP_CONFIG="/var/www/webroot/ROOT/wp-config.php"
# Set up the environment # Ensure the log directory exists
export RESTIC_PASSWORD
mkdir -p "$LOG_DIR" mkdir -p "$LOG_DIR"
LOG_FILE="${LOG_DIR}/restore_$(date +'%Y-%m-%d_%H-%M-%S').log" LOG_FILE="${LOG_DIR}/restore_$(date +'%Y-%m-%d_%H-%M-%S').log"
@ -26,95 +26,137 @@ log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
} }
# Check for required dependencies # Validate required dependencies
for cmd in restic jq mysql; do validate_dependencies() {
for cmd in restic jq mysql; do
if ! command -v $cmd >/dev/null 2>&1; then if ! command -v $cmd >/dev/null 2>&1; then
log "Error: '$cmd' command not found. Please install $cmd." log "ERROR: '$cmd' command not found. Please install $cmd."
exit 1 exit 1
fi fi
done done
}
# Ensure there are no stale locks in the repository # Set up Restic environment
log "Checking for stale locks in the repository..." setup_restic_environment() {
if restic -r "$RESTIC_REPOSITORY" list locks | grep -q "lock"; then if [ ! -f "$RESTIC_PASSWORD_FILE" ]; then
log "ERROR: Restic password file not found at $RESTIC_PASSWORD_FILE."
exit 1
fi
export RESTIC_PASSWORD=$(cat "$RESTIC_PASSWORD_FILE")
export RESTIC_REPOSITORY="$RESTIC_REPOSITORY"
log "Restic environment set up successfully."
}
# Ensure no stale locks exist in the repository
remove_stale_locks() {
log "Checking for stale locks in the repository..."
if restic list locks | grep -q "lock"; then
log "Stale lock detected. Unlocking repository..." log "Stale lock detected. Unlocking repository..."
restic -r "$RESTIC_REPOSITORY" unlock restic unlock || {
log "ERROR: Failed to remove stale locks."
exit 1
}
log "Repository unlocked successfully." log "Repository unlocked successfully."
else else
log "No stale locks found. Proceeding with restoration." log "No stale locks found. Proceeding with restoration."
fi fi
}
# Extract database credentials from wp-config.php # Extract database credentials from wp-config.php
if [ ! -f "$WP_CONFIG" ]; then extract_db_credentials() {
log "Error: wp-config.php not found at $WP_CONFIG. Ensure WordPress is installed." if [ ! -f "$WP_CONFIG" ]; then
exit 1 log "ERROR: wp-config.php not found at $WP_CONFIG. Ensure WordPress is installed."
fi
DB_NAME=$(awk -F"'" '/define\( *'"'"'DB_NAME'"'"'/{print $4}' "$WP_CONFIG")
DB_USER=$(awk -F"'" '/define\( *'"'"'DB_USER'"'"'/{print $4}' "$WP_CONFIG")
DB_PASSWORD=$(awk -F"'" '/define\( *'"'"'DB_PASSWORD'"'"'/{print $4}' "$WP_CONFIG")
if [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
log "Error: Could not extract database credentials from wp-config.php."
exit 1
fi
log "Starting restoration for snapshot ID: $SNAPSHOT_ID..."
# Retrieve snapshot data
SNAPSHOT_DATA=$(restic -r "$RESTIC_REPOSITORY" snapshots --json | jq -r ".[] | select(.short_id == \"$SNAPSHOT_ID\")")
if [ -z "$SNAPSHOT_DATA" ]; then
log "Error: Snapshot ID $SNAPSHOT_ID not found in repository."
exit 1
fi
SNAPSHOT_PATH=$(echo "$SNAPSHOT_DATA" | jq -r ".paths[] // empty")
SNAPSHOT_TAGS=$(echo "$SNAPSHOT_DATA" | jq -r ".tags[] // empty")
if [ -z "$SNAPSHOT_PATH" ]; then
log "Error: Snapshot $SNAPSHOT_ID does not contain valid paths."
exit 1
fi
log "Snapshot Data Retrieved: Path=$SNAPSHOT_PATH, Tags=$SNAPSHOT_TAGS"
# Determine the restoration type based on the tags
if [[ "$SNAPSHOT_TAGS" == *"wordpress_db"* ]] && [[ "$SNAPSHOT_PATH" == "/stdin" ]]; then
log "Detected database backup. Restoring database $DB_NAME..."
if restic -r "$RESTIC_REPOSITORY" dump "$SNAPSHOT_ID" stdin | mysql -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME"; then
log "Database restoration completed successfully for $DB_NAME from Snapshot ID: $SNAPSHOT_ID."
else
log "Error: Database restoration failed for Snapshot ID: $SNAPSHOT_ID."
exit 1 exit 1
fi fi
elif [[ "$SNAPSHOT_TAGS" == *"core_files"* ]]; then
DB_NAME=$(awk -F"'" '/define\( *'"'"'DB_NAME'"'"'/{print $4}' "$WP_CONFIG")
DB_USER=$(awk -F"'" '/define\( *'"'"'DB_USER'"'"'/{print $4}' "$WP_CONFIG")
DB_PASSWORD=$(awk -F"'" '/define\( *'"'"'DB_PASSWORD'"'"'/{print $4}' "$WP_CONFIG")
DB_HOST=$(awk -F"'" '/define\( *'"'"'DB_HOST'"'"'/{print $4}' "$WP_CONFIG")
# Set default DB_HOST if empty
if [ -z "$DB_HOST" ]; then
DB_HOST="localhost"
fi
if [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
log "ERROR: Could not extract database credentials from wp-config.php."
exit 1
fi
}
# Retrieve snapshot metadata
retrieve_snapshot_metadata() {
log "Retrieving metadata for snapshot ID: $SNAPSHOT_ID..."
SNAPSHOT_DATA=$(restic snapshots --json | jq -r ".[] | select(.short_id == \"$SNAPSHOT_ID\")")
if [ -z "$SNAPSHOT_DATA" ]; then
log "ERROR: Snapshot ID $SNAPSHOT_ID not found in the repository."
exit 1
fi
SNAPSHOT_PATH=$(echo "$SNAPSHOT_DATA" | jq -r ".paths[] // empty")
SNAPSHOT_TAGS=$(echo "$SNAPSHOT_DATA" | jq -r ".tags[] // empty")
if [ -z "$SNAPSHOT_PATH" ]; then
log "ERROR: Snapshot $SNAPSHOT_ID does not contain valid paths."
exit 1
fi
log "Snapshot metadata retrieved: Path=$SNAPSHOT_PATH, Tags=$SNAPSHOT_TAGS"
}
# Perform the restoration based on snapshot tags
restore_snapshot() {
if [[ "$SNAPSHOT_TAGS" == *"wordpress_db"* ]] && [[ "$SNAPSHOT_PATH" == *".sql"* ]]; then
log "Detected database backup. Restoring database $DB_NAME..."
log "Using DB credentials: User=$DB_USER, Host=$DB_HOST, DB=$DB_NAME"
if restic dump "$SNAPSHOT_ID" "$SNAPSHOT_PATH" | mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME"; then
log "Database restoration completed successfully for $DB_NAME."
else
log "ERROR: Database restoration failed. Verify MySQL credentials or permissions."
log "Check that 'DB_USER=$DB_USER' has necessary privileges on 'DB_NAME=$DB_NAME'."
exit 1
fi
elif [[ "$SNAPSHOT_TAGS" == *"core_files"* ]]; then
RESTORE_DIR="/var/www/webroot/ROOT" RESTORE_DIR="/var/www/webroot/ROOT"
log "Detected core files backup. Restoring to $RESTORE_DIR..." log "Detected core files backup. Restoring to $RESTORE_DIR..."
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then if restic restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Core files restoration completed successfully for Snapshot ID: $SNAPSHOT_ID." log "Core files restoration completed successfully."
else else
log "Error: Core files restoration failed for Snapshot ID: $SNAPSHOT_ID." log "ERROR: Core files restoration failed."
exit 1 exit 1
fi fi
elif [[ "$SNAPSHOT_TAGS" == *"media_themes"* ]]; then elif [[ "$SNAPSHOT_TAGS" == *"media_themes"* ]]; then
RESTORE_DIR="/var/www/webroot/ROOT/wp-content/uploads" RESTORE_DIR="/var/www/webroot/ROOT/wp-content/uploads"
log "Detected media files backup. Restoring to $RESTORE_DIR..." log "Detected media files backup. Restoring to $RESTORE_DIR..."
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then if restic restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Media files restoration completed successfully for Snapshot ID: $SNAPSHOT_ID." log "Media files restoration completed successfully."
else else
log "Error: Media files restoration failed for Snapshot ID: $SNAPSHOT_ID." log "ERROR: Media files restoration failed."
exit 1 exit 1
fi fi
else else
log "Unknown snapshot type. Attempting general restoration to /..." log "Unknown snapshot type. Attempting general restoration to a temporary directory..."
TEMP_RESTORE_DIR="/tmp/restoration_$SNAPSHOT_ID" TEMP_RESTORE_DIR="/tmp/restoration_$SNAPSHOT_ID"
mkdir -p "$TEMP_RESTORE_DIR" mkdir -p "$TEMP_RESTORE_DIR"
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$TEMP_RESTORE_DIR"; then if restic restore "$SNAPSHOT_ID" --target "$TEMP_RESTORE_DIR"; then
log "General file restoration completed successfully to temporary directory: $TEMP_RESTORE_DIR." log "General restoration completed successfully to $TEMP_RESTORE_DIR."
else else
log "Error: File restoration failed for Snapshot ID: $SNAPSHOT_ID." log "ERROR: General restoration failed."
exit 1 exit 1
fi fi
fi fi
}
# Main execution flow
validate_dependencies
setup_restic_environment
remove_stale_locks
extract_db_credentials
retrieve_snapshot_metadata
restore_snapshot
log "Restoration process completed successfully." log "Restoration process completed successfully."