Compare commits

...

5 Commits

10 changed files with 882 additions and 421 deletions

View File

@ -1,5 +1,139 @@
# Changelog
## Version 1.8
### Added
- **`view_snapshots.sh` Enhancements**:
- Introduced support for a new `all` tag to display all snapshots regardless of specific tags.
- Added functionality to dynamically fetch and display all available tags in the repository, improving usability and flexibility.
- Enhanced error handling for empty repositories or inaccessible snapshots with detailed log messages.
- **Improved Snapshot Display**:
- For the `all` tag, all snapshots are displayed in a formatted output including `short_id`, `time`, and associated tags.
- Enhanced the script to log raw snapshot data during errors for easier debugging.
### Fixed
- Resolved issues with fetching available tags when no snapshots existed in the repository, ensuring consistent script behavior.
- Fixed a missing password issue when executing `restic -r /mnt/backups snapshots --json`, ensuring `RESTIC_PASSWORD` is securely passed in all cases.
- Corrected formatting and display of available tags to ensure no duplicate or unnecessary entries are shown.
### Updated
- **Logging and Usability**:
- Improved log formatting to include more descriptive timestamps and detailed error or success messages for each step.
- Standardized output for snapshot retrieval by tag, including snapshot ID, timestamp, and tags in a clean and readable format.
- **Environment Validation**:
- Updated `view_snapshots.sh` to ensure all necessary environment variables (`RESTIC_REPOSITORY`, `RESTIC_PASSWORD`) are set before executing Restic commands.
- Validated repository access and password file existence at the start of the script to avoid runtime errors.
### Improved
- **Modularity and Robustness**:
- Refactored `view_snapshots.sh` to handle dynamic tags more effectively, making it easier to extend or customize in the future.
- Centralized dependency validation (`restic`, `jq`) and repository checks to reduce redundancy across script operations.
- **Error Handling**:
- Added detailed error messages when repository access fails or tags cannot be fetched, ensuring issues are easy to debug.
- Ensured graceful script exits with appropriate logs when critical validation checks fail.
- **Code Maintenance**:
- Reduced redundancy by consolidating snapshot and tag-related logic into reusable functions.
- Enhanced maintainability by improving script readability, modularity, and inline documentation.
## 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
### Added
- **`check_repo_stats.sh`**:
- Introduced a new script to automate the retrieval of repository statistics and perform maintenance tasks.
- Logs repository stats, retention policy application, and integrity checks to dynamically named log files (`repo_stats_YYYY-MM-DD.log`).
- Automatically applies a retention policy (`--keep-last 7 --prune`) to manage repository size.
- Includes an integrity check (`restic check --read-data-subset=5%`) to validate repository consistency and data reliability.
- Detects and removes stale locks before performing operations.
- Ensures dependencies (`restic`) and repository access are validated before execution.
- Handles errors gracefully with detailed logging for each step.
- **Enhanced `backup_repo_check` Functionality**:
- Created a standalone script `check_backup_repo.sh` to validate repository integrity and initialize repositories if empty.
- Logs actions and errors to `/home/litespeed/logs/backup_repo_check.log` for better traceability.
- Improved stale lock handling by detecting and removing locks when necessary.
- Validates or creates a password file (`/etc/restic-password`) to ensure smooth operation without prompts.
- Automatically initializes a new repository if no files are present in the backup path.
### Fixed
- Addressed permission issues in `check_backup_repo.sh` by ensuring the log directory and repository paths are writable by the correct user.
- Corrected potential errors in handling stale locks by adding proper validation before removing them.
### Improved
- Enhanced logging across `check_repo_stats.sh` and `check_backup_repo.sh` for better monitoring and traceability.
- Optimized script robustness with dependency validation, error handling, and reduced redundancy.
- Streamlined repository maintenance by combining retention policy application, stale lock removal, and integrity checks into `check_repo_stats.sh`.
## Version 1.5
### Added
- Simplified `backup_all.sh` by delegating backup tasks to individual scripts (`backup_core_files.sh`, `backup_database.sh`, `backup_media.sh`).
- Introduced centralized orchestration of all backups in `backup_all.sh` with a unified `manual-backup` tag for consistency.
- Ensured individual scripts can be reused independently or called as part of a larger workflow.
### Fixed
- Corrected `trap` command in `backup_all.sh` to ensure errors are properly logged to `backup_error.log`.
- Addressed issues with redundant logic in `backup_all.sh` by consolidating common functionality into the individual backup scripts.
- Resolved potential inconsistencies in tag usage by applying a standard `manual-backup` tag with the current server date across all backup scripts.
### Updated
- Refactored `backup_all.sh` to dynamically call individual backup scripts instead of duplicating logic for core, database, and media backups.
- Adjusted YAML configuration for `backupnow` to call `backup_all.sh` as the primary entry point for the backup process.
### Improved
- Centralized the backup process to enhance modularity and maintainability by separating core, database, and media backup logic.
- Ensured consistent tagging and logging across all backup types for easier monitoring and debugging.
- Streamlined the orchestration script (`backup_all.sh`) for improved readability and reduced duplication.
## Version 1.4
### Added

View File

@ -1,5 +1,5 @@
type: update
jpsVersion: 1.4
jpsVersion: 1.8
name: MightyBox WordPress Backup/Restore Addon
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.
@ -52,6 +52,12 @@ menu:
title: Configure Automated Backup 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
action: removeAutoBackup
confirmText: Remove automated backup schedule?
@ -107,10 +113,10 @@ menu:
title: Restore from Snapshot
submitButtonText: Restore Now
- caption: View Full Backups
action: viewFullBackups
confirmText: Are you sure you want to view full backups?
successText: Full backups listed successfully.
- caption: View All Backups
action: viewAllBackups
confirmText: Are you sure you want to view all backups?
successText: All backups listed successfully.
- caption: View Core Backups
action: viewCoreBackups
@ -127,6 +133,12 @@ menu:
confirmText: Are you sure you want to view database backups?
successText: Database backups listed successfully.
- caption: Check Repository Stats
confirmText: Check repository stats?
loadingText: Checking repository stats...
action: checkRepoStats
successText: Repository stats checked successfully.
onUninstall:
- removeScript
@ -154,6 +166,14 @@ actions:
type: info
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:
- cmd[cp]:
user: root
@ -165,7 +185,7 @@ actions:
checkBackupRepo:
- cmd[cp]:
user: root
commands: bash /home/jelastic/mb-backups/backup-logic.sh check_backup_repo
commands: bash /home/jelastic/mb-backups/check_backup_repo.sh
- return:
type: info
message: "${response.out}"
@ -173,7 +193,7 @@ actions:
backupnow:
- cmd[cp]:
user: root
commands: bash /home/jelastic/mb-backups/backup-logic.sh "$(cat /etc/restic-password)" "backup"
commands: bash /home/jelastic/mb-backups/backup_all.sh manual
- return:
type: info
message: "${response.out}"
@ -210,7 +230,7 @@ actions:
type: info
message: "${response.out}"
viewFullBackups:
viewAllBackups:
- cmd[cp]:
user: root
commands: bash /home/jelastic/mb-backups/view_snapshots.sh main_backup
@ -250,6 +270,14 @@ actions:
type: info
message: "${response.out}"
checkRepoStats:
- cmd[cp]:
user: root
commands: bash /home/jelastic/mb-backups/check_repo_stats.sh
- return:
type: info
message: "${response.out}"
checkAddons:
- script: |-
var onAfterReturn = { setGlobals: {} },
@ -318,9 +346,9 @@ actions:
- mkdir -p /home/litespeed/mb-backups/logs/auto
- mkdir -p /home/litespeed/mb-backups/logs/manual
- 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
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/backup-logic.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_database.sh
@ -329,5 +357,7 @@ actions:
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/manage_backup_schedule.sh
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/restore_backup_direct.sh
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/view_snapshots.sh
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/check_backup_repo.sh
- curl -O https://deploy-proxy.mightybox.io/addons/mb-backup-manager/raw/branch/main/scripts/imports/check_repo_stats.sh
- chmod +x /home/litespeed/mb-backups/*.sh
- sudo chown -R litespeed:litespeed /home/litespeed/mb-backups

253
readme.md
View File

@ -2,23 +2,31 @@
## Overview
The **MB Backup Manager** is a comprehensive backup solution designed for managing automated backups of web applications, particularly those running on the Virtuozzo Application Platform. This tool leverages cron jobs for scheduling backups and utilizes Restic for efficient backup storage and management.
The **MB Backup Manager** is a comprehensive backup solution designed for managing automated backups of web applications, particularly those running on the Virtuozzo Application Platform. This tool leverages Restic for efficient backup storage and management, with support for automated scheduling through cron jobs.
## Features
- **Automated Backups**: Schedule daily, weekly, or custom backups using cron jobs.
- **Backup Types**: Supports backing up core files, media files, and databases.
- **Logging**: Detailed logging of backup operations for monitoring and troubleshooting.
- **Backup Rotation**: Automatically manages old backups to save storage space.
- **Automated Backups**: Schedule and manage backups using `manage_backup_schedule.sh`
- **Backup Types**:
- Core files backup (`backup_core_files.sh`)
- Media files backup (`backup_media.sh`)
- Database backup (`backup_database.sh`)
- **Backup Management**:
- View snapshots with tag filtering (`view_snapshots.sh`)
- Direct backup restoration (`restore_backup_direct.sh`)
- Repository statistics and maintenance (`check_repo_stats.sh`)
- Repository validation (`check_backup_repo.sh`)
- **Logging**: Comprehensive logging system with separate directories for automated and manual backups
- **Backup Orchestration**: Centralized backup management through `backup_all.sh`
## Installation
1. **Clone the Repository**:
Clone the repository containing the backup manager scripts to your local machine or server. The repository can be found at:
Clone the repository containing the backup manager scripts to your local machine or server.
[MB Backup Manager Repository](https://deploy.mightybox.io/addons/mb-backup-manager)
2. **Install Dependencies**:
Ensure that `Restic` and `cron` are installed on your system. You can install them using the following commands:
Ensure that `Restic` and `cron` are installed on your system:
```bash
sudo dnf install -y cronie
@ -26,7 +34,7 @@ The **MB Backup Manager** is a comprehensive backup solution designed for managi
```
3. **Set Up Directory Structure**:
Create the necessary directories for logs and scripts:
Create the necessary directories for logs:
```bash
mkdir -p /home/litespeed/mb-backups/logs/auto
@ -34,136 +42,167 @@ The **MB Backup Manager** is a comprehensive backup solution designed for managi
```
4. **Configure Environment**:
Ensure that the environment variables and configuration files are set up correctly, including the Restic password stored in `/etc/restic-password`.
Ensure the Restic password is stored in `/etc/restic-password`.
5. **Install from the Virtuozzo Marketplace**:
To install the MB Backup Manager from the Virtuozzo Marketplace, follow these steps:
- Log in to your Virtuozzo Application Platform dashboard.
- Navigate to the **Marketplace** section.
- Search for "MB Backup Manager" in the marketplace.
- Click on the application to view its details and click the **Install** button.
- Follow the prompts to complete the installation process.
## Core Scripts and Usage
For more detailed instructions on using the Virtuozzo Marketplace, refer to the official documentation: [Virtuozzo Marketplace Documentation](https://www.virtuozzo.com/application-platform-docs/marketplace/).
### Backup Management
## Usage
1. **Viewing Snapshots** (`view_snapshots.sh`):
- View all snapshots or filter by specific tags
- Displays snapshot IDs, timestamps, and associated tags
- Supports an `all` tag to show all snapshots regardless of tags
### Managing Backup Schedules
2. **Direct Backup Restoration** (`restore_backup_direct.sh`):
- Restores specific backup types based on tags
- Handles direct database restoration by piping SQL files from Restic to MySQL
- Automatically detects database credentials from `wp-config.php`
The `manage_backup_schedule.sh` script is used to add, update, or remove backup schedules.
3. **Backup Scheduling** (`manage_backup_schedule.sh`):
- Add or update backup schedules with cron
- Remove existing backup schedules
- Validates cron syntax and dependencies
- Logs all scheduling actions
- **Add or Update a Backup Schedule**:
4. **Repository Maintenance** (`check_repo_stats.sh`):
- Retrieves repository statistics
- Applies retention policies (keeps last 7 backups by default)
- Performs integrity checks
- Removes stale locks
- Logs to `repo_stats_YYYY-MM-DD.log`
To add or update a backup schedule, run the following command:
5. **Repository Validation** (`check_backup_repo.sh`):
- Validates repository integrity
- Initializes empty repositories
- Handles stale locks
- Logs to `/home/litespeed/logs/backup_repo_check.log`
```bash
./manage_backup_schedule.sh add '0 1 * * *' 'your_restic_password'
```
### Backup Components
This example schedules a backup to run daily at 1 AM.
1. **Complete Backup** (`backup_all.sh`):
- Orchestrates the entire backup process
- Calls individual backup scripts for core, media, and database
- Applies consistent tagging (`manual-backup` or `auto-backup` with timestamps)
- Handles error logging and reporting
- **Remove a Backup Schedule**:
2. **Individual Backup Scripts**:
- `backup_core_files.sh`: Backs up essential application files
- `backup_media.sh`: Handles media file backups
- `backup_database.sh`: Manages database backups
- Each script can run independently or as part of `backup_all.sh`
To remove an existing backup schedule, use:
```bash
./manage_backup_schedule.sh remove
```
### Checking Scheduled Backups
You can check the current scheduled backups using the `check_sched.sh` script:
### Schedule Monitoring
**Check Scheduled Backups** (`check_sched.sh`):
```bash
./check_sched.sh
```
Displays current backup-related cron jobs and automation status.
This will log the current cron jobs related to the backup script and indicate whether automated backups are enabled.
## Available Commands
### Running Backups Manually
To run backups manually, you can execute the `backup_all.sh` script directly:
### Backup Management Commands
1. **Schedule Management** (`manage_backup_schedule.sh`):
```bash
bash /home/litespeed/mb-backups/backup_all.sh
# Add or update a backup schedule
./manage_backup_schedule.sh add "0 0 * * *" "your_restic_password"
# Remove all backup schedules
./manage_backup_schedule.sh remove
# List current backup schedules
./manage_backup_schedule.sh list
```
2. **Manual Backup Operations** (`backup_all.sh`):
```bash
# Run a manual backup
./backup_all.sh manual
# Run an automated backup (used by cron)
./backup_all.sh auto
```
3. **Individual Backup Components**:
```bash
# Core files backup
./backup_core_files.sh "restic_password" "backup_tag"
# Database backup
./backup_database.sh "restic_password" "backup_tag"
# Media files backup
./backup_media.sh "restic_password" "backup_tag"
```
4. **Repository Management**:
```bash
# Check repository status
./check_repo_stats.sh
# Validate repository
./check_backup_repo.sh
# View snapshots (all or by tag)
./view_snapshots.sh
```
5. **Schedule Monitoring**:
```bash
# Check current backup schedules
./check_sched.sh
```
6. **Backup Restoration**:
```bash
# Restore backups directly
./restore_backup_direct.sh
```
### Environment Variables
The following environment variables are used by the scripts:
- `RESTIC_PASSWORD`: Stored in `/etc/restic-password`
- `RESTIC_REPOSITORY`: Default path `/mnt/backup`
### Log File Locations
- Automated backup logs: `/home/litespeed/mb-backups/logs/auto/`
- Manual backup logs: `/home/litespeed/mb-backups/logs/manual/`
- Repository stats: `repo_stats_YYYY-MM-DD.log`
- Repository check logs: `/home/litespeed/logs/backup_repo_check.log`
- Schedule actions log: `/home/litespeed/mb-backups/logs/auto/schedule_actions.log`
- Backup addon log: `/var/log/backup_addon.log`
## Troubleshooting
1. **Cron Service Issues**:
- If the cron service is not running, ensure it is installed and started:
```bash
sudo systemctl status crond
sudo systemctl start crond
sudo systemctl enable crond
```
- To check the status of the cron service, you can run:
2. **Log Locations**:
- Automated backup logs: `/home/litespeed/mb-backups/logs/auto/`
- Manual backup logs: `/home/litespeed/mb-backups/logs/manual/`
- Repository stats: `repo_stats_YYYY-MM-DD.log`
- Repository check logs: `/home/litespeed/logs/backup_repo_check.log`
3. **Common Issues**:
- Stale locks: Automatically handled by scripts
- Repository access: Verify Restic password in `/etc/restic-password`
- Backup failures: Check corresponding log files for error messages
- Cron job issues: Verify cron service status and job configuration
4. **Permissions**:
```bash
systemctl status crond
chmod +x /home/litespeed/mb-backups/scripts/imports/*.sh
```
- If the service fails to start, check the system logs for any error messages related to cron:
```bash
journalctl -xe | grep crond
```
2. **Log Files**:
- Check the log files located in `/home/litespeed/mb-backups/logs/auto` for any errors or issues during backup operations.
- Each backup run generates a log file with a timestamp, which can help identify when issues occurred.
3. **Restic Issues**:
- Ensure that Restic is installed and configured correctly. You can verify its installation by running:
```bash
restic version
```
- If you encounter issues with Restic, check the Restic logs for detailed error messages. You can enable verbose logging by adding the `-v` flag to your Restic commands.
4. **Backup Failures**:
- If a backup fails, check the corresponding log file for detailed error messages. The logs are typically located in `/var/log/backup_addon.log`.
- Look for specific error messages that indicate what went wrong during the backup process.
5. **Cron Job Not Found**:
- If the scheduled cron job is not found, ensure that the `manage_backup_schedule.sh` script was executed successfully and that the cron job was added correctly.
- You can list the current cron jobs by running:
```bash
crontab -l
```
- If the job is missing, re-run the `manage_backup_schedule.sh` script with the correct parameters.
6. **Debugging Cron Jobs**:
- If your cron job is not executing as expected, you can redirect the output and error messages to a log file by modifying the cron command in the `manage_backup_schedule.sh` script. For example:
```bash
CMD="RESTIC_PASSWORD=\"$3\" $BACKUP_SCRIPT > \"${BACKUP_LOG_PREFIX}\$(date +\\%Y-\\%m-\\%d_\\%H-\\%M-\\%S).log\" 2>&1"
```
- This will help capture any errors that occur when the cron job runs.
7. **Environment Variables**:
- Ensure that any environment variables required by your scripts (like `RESTIC_PASSWORD`) are set correctly. You can check the environment variables in your cron jobs by adding a command to print them to a log file:
```bash
env > /home/litespeed/mb-backups/logs/cron_env.log
```
8. **Permissions**:
- Ensure that the scripts have the correct permissions to execute. You can set the executable permission using:
```bash
chmod +x /home/litespeed/mb-backups/*.sh
```
9. **Testing Scripts Manually**:
- If you suspect an issue with a specific script, try running it manually in the terminal to see if it executes without errors. This can help isolate the problem.
10. **Check for Running Processes**:
- If you suspect that a backup process is already running, you can check for running instances of your backup scripts using:
```bash
pgrep -f backup_all.sh
```
- This will show you if there are any active processes related to your backup operations.
By following these debugging tips, you can effectively troubleshoot issues related to the MB Backup Manager and ensure that your backup processes run smoothly.
## Conclusion
The MB Backup Manager provides a robust solution for managing backups in a cloud environment. By following the guidelines outlined in this documentation, developers can effectively set up, manage, and troubleshoot the backup processes. For further assistance, please refer to the log files or reach out to the development team.
## Repository Information
For the latest updates and commit history, you can find the repository at:
For the latest updates and commit history:
[MB Backup Manager Repository](https://deploy.mightybox.io/addons/mb-backup-manager)

View File

@ -1,7 +1,7 @@
#!/bin/bash
set -e # Exit on error
trap 'echo "ERROR: An error occurred while executing $COMMAND for $ENV_NAME. Exiting."' ERR
trap 'log_message "ERROR: An error occurred while executing $COMMAND for $ENV_NAME. Exiting."' ERR
# Validate arguments
if [ $# -lt 2 ]; then
@ -17,30 +17,23 @@ COMMAND="$2"
LOG_FILE="/var/log/${ENV_NAME}_backup_script.log"
BACKUP_REPO_PATH="/mnt/backups/${ENV_NAME}"
PASSWORD_FILE="/etc/restic-password"
# Validate ENV_NAME
if [ -z "$ENV_NAME" ]; then
echo "Error: ENV_NAME is not provided or empty."
exit 1
fi
LOCK_FILE="/tmp/restic_global.lock"
# Ensure dynamic paths exist
mkdir -p "$BACKUP_REPO_PATH"
# Set environment variables
if [ ! -f "$PASSWORD_FILE" ]; then
echo "Error: Password file not found at $PASSWORD_FILE."
exit 1
fi
export RESTIC_REPOSITORY="$BACKUP_REPO_PATH"
export RESTIC_PASSWORD=$(cat "$PASSWORD_FILE")
# 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
@ -57,6 +50,34 @@ install_restic() {
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
@ -95,34 +116,54 @@ 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)

View File

@ -2,125 +2,81 @@
# Enable error handling
set -e
# Define log file path
LOG_DIR="/home/jelastic/mb-backups/logs"
mkdir -p "$LOG_DIR"
# Properly escape the trap command
trap 'echo "[$(date +'%Y-%m-%d %H:%M:%S')] Backup failed" >> "$LOG_DIR/backup_error.log"' ERR
# Load the backup logic functions
source /home/jelastic/mb-backups/backup-logic.sh
trap 'echo "[$(date +%Y-%m-%d %H:%M:%S)] Backup failed" >> "$LOG_DIR/backup_error.log"' ERR
# Configuration
password_file="/etc/restic-password"
APP_PATH="/var/www/webroot/ROOT"
WP_CONFIG="${APP_PATH}/wp-config.php"
backupPath="/mnt/backups"
TEMP_DIR="/tmp/wp_backup_tmp"
MAX_BACKUP_SIZE=$((10 * 1024 * 1024 * 1024)) # 10GB
LOG_DIR="/home/jelastic/mb-backups/logs"
CORE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_core_files.sh"
DATABASE_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_database.sh"
MEDIA_BACKUP_SCRIPT="/home/jelastic/mb-backups/backup_media.sh"
TIMESTAMP=$(date +'%Y-%m-%d_%H-%M-%S')
# Function: Ensure required commands are available
validate_dependencies() {
for cmd in restic mysqldump jq; do
if ! command -v "$cmd" &>/dev/null; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: Required command '$cmd' not found" | tee -a "$LOG_DIR/backup_error.log"
exit 1
fi
done
}
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Function: Initialize logging
# Logging function
log_message() {
local log_file="$1"
local message="$2"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $message" | tee -a "$log_file"
}
# Function: Check if backup size exceeds limit
check_backup_size() {
local path="$1"
local size
size=$(du -sb "$path" | cut -f1)
if [ "$size" -gt "$MAX_BACKUP_SIZE" ]; then
log_message "$LOG_DIR/backup_warning.log" "Warning: Backup size exceeds 10GB for $path"
return 1
fi
return 0
}
# Function: Verify backup
verify_backup() {
local tag="$1"
local latest_snapshot
latest_snapshot=$(restic snapshots --latest 1 --tag "$tag" --json | jq -r '.[0].id')
if [ -n "$latest_snapshot" ]; then
restic check --read-data "$latest_snapshot"
return $?
fi
return 1
}
# Function: Initialize backup
initialize_backup() {
if [ ! -f "$password_file" ]; then
log_message "$LOG_DIR/backup_error.log" "ERROR: Password file not found at $password_file"
exit 1
fi
export RESTIC_PASSWORD=$(cat "$password_file")
export RESTIC_REPOSITORY="$backupPath"
}
# Function: Backup core files
backup_core_files() {
local log_file="${LOG_DIR}/backup_core_files_$(date +'%Y-%m-%d').log"
log_message "$log_file" "Starting Core Files Backup"
check_backup_size "$APP_PATH" || return 1
local excludePaths=("$APP_PATH/wp-content/uploads")
local excludeOptions=""
for path in "${excludePaths[@]}"; do
excludeOptions+="--exclude $path "
done
if restic backup $excludeOptions "$APP_PATH" --tag core_files --tag full_backup; then
verify_backup "core_files" || return 1
log_message "$log_file" "Core files backup completed successfully"
return 0
fi
return 1
local message="$1"
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $message" | tee -a "${LOG_DIR}/backup_all.log"
}
# Main execution
main() {
validate_dependencies
initialize_backup
local backup_type="$1"
local backup_tag=""
local start_time=$(date +%s)
local backup_date=$(date +'%Y-%m-%d_%H-%M-%S')
local main_log="${LOG_DIR}/full_backup_${backup_date}.log"
# 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
log_message "$main_log" "Starting full backup process"
# Run individual backup scripts
if bash "$CORE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Core files backup completed successfully."
else
log_message "ERROR: Core files backup failed."
exit 1
fi
backup_core_files || exit 1
backup_media_themes || exit 1
backup_database || exit 1
if bash "$DATABASE_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Database backup completed successfully."
else
log_message "ERROR: Database backup failed."
exit 1
fi
cleanup_old_backups
if bash "$MEDIA_BACKUP_SCRIPT" "$(cat /etc/restic-password)" "$backup_tag"; then
log_message "Media files backup completed successfully."
else
log_message "ERROR: Media files backup failed."
exit 1
fi
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log_message "$main_log" "Full backup completed in $duration seconds"
log_message "Full backup process completed successfully."
}
# Argument handling
if [ "$1" == "backup_now" ]; then
main
else
echo "Usage: $0 backup_now"
if [ "$#" -ne 1 ]; then
echo "Usage: $0 {manual|auto}"
exit 1
fi
case "$1" in
manual)
main "manual"
;;
auto)
main "auto"
;;
*)
echo "Usage: $0 {manual|auto}"
exit 1
;;
esac

View File

@ -0,0 +1,65 @@
#!/bin/bash
# Exit on errors
set -e
# Configuration
BACKUP_REPO_PATH="/mnt/backups"
PASSWORD_FILE="/etc/restic-password"
LOG_FILE="/var/log/backup_repo_check.log"
# Ensure the log file exists
mkdir -p "$(dirname "$LOG_FILE")"
# Logging function
log_message() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Main function to check the backup repository
check_backup_repo() {
# Ensure the backup repository path exists
mkdir -p "$BACKUP_REPO_PATH"
# Validate or create the password file
if [ ! -f "$PASSWORD_FILE" ]; then
log_message "Password file not found. Creating a new one with a default password."
echo "default-password" > "$PASSWORD_FILE"
fi
# Export the password and repository path for Restic
export RESTIC_PASSWORD=$(cat "$PASSWORD_FILE")
export RESTIC_REPOSITORY="$BACKUP_REPO_PATH"
# Check if the repository contains files
if [ "$(find "$BACKUP_REPO_PATH" -mindepth 1 | wc -l)" -gt 0 ]; then
log_message "Checking the backup repository integrity and consistency."
# Remove stale locks if they exist
if [ -d "$BACKUP_REPO_PATH/locks" ] && [ "$(ls -A "$BACKUP_REPO_PATH/locks")" ]; then
log_message "Stale lock detected in the repository. Removing lock."
if ! restic -r "$BACKUP_REPO_PATH" unlock; then
log_message "Failed to remove stale lock. Exiting."
exit 1
fi
fi
# Perform repository integrity check
if ! restic -q -r "$BACKUP_REPO_PATH" check --read-data-subset=5%; then
log_message "Repository integrity check failed. Please investigate."
exit 1
fi
log_message "Backup repository integrity check passed."
else
# Initialize a new Restic repository if empty
log_message "No files found in the backup repository. Initializing a new repository."
if ! restic init -r "$BACKUP_REPO_PATH"; then
log_message "Failed to initialize the backup repository. Exiting."
exit 1
fi
log_message "Backup repository initialized successfully."
fi
}
# Execute the function
check_backup_repo

View File

@ -0,0 +1,109 @@
#!/bin/bash
# Exit on error
set -e
# Configuration
BACKUP_REPO_PATH="/mnt/backups"
PASSWORD_FILE="/etc/restic-password"
LOG_DIR="/home/litespeed/logs"
LOG_FILE="${LOG_DIR}/repo_stats_$(date +'%Y-%m-%d').log"
RETENTION_POLICY="--keep-last 7 --prune" # Modify retention policy as needed
# Ensure the log directory exists
mkdir -p "$LOG_DIR"
# Logging function
log_message() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Function: Validate dependencies
validate_dependencies() {
for cmd in restic; do
if ! command -v "$cmd" &>/dev/null; then
log_message "ERROR: Required command '$cmd' not found."
exit 1
fi
done
}
# Function: Validate repository access
validate_repository() {
if [ ! -f "$PASSWORD_FILE" ]; then
log_message "ERROR: Password file not found at $PASSWORD_FILE."
exit 1
fi
export RESTIC_PASSWORD=$(cat "$PASSWORD_FILE")
export RESTIC_REPOSITORY="$BACKUP_REPO_PATH"
if ! restic snapshots &>/dev/null; then
log_message "ERROR: Unable to access the Restic repository. Check password and repository path."
exit 1
fi
log_message "Repository access validated."
}
# Function: Check repository stats
check_repository_stats() {
log_message "Fetching repository stats..."
if restic stats --mode restore-size >> "$LOG_FILE" 2>&1; then
log_message "Repository stats fetched successfully."
else
log_message "ERROR: Failed to fetch repository stats."
exit 1
fi
}
# Function: Apply retention policy
apply_retention_policy() {
log_message "Applying retention policy: $RETENTION_POLICY"
if restic forget $RETENTION_POLICY >> "$LOG_FILE" 2>&1; then
log_message "Retention policy applied successfully. Unnecessary snapshots pruned."
else
log_message "ERROR: Failed to apply retention policy."
exit 1
fi
}
# Function: Check for stale locks
check_and_remove_stale_locks() {
log_message "Checking for stale locks in the repository..."
if [ -d "${BACKUP_REPO_PATH}/locks" ] && [ "$(ls -A "${BACKUP_REPO_PATH}/locks" 2>/dev/null)" ]; then
log_message "Stale locks detected. Removing locks..."
if restic unlock; then
log_message "Stale locks removed successfully."
else
log_message "ERROR: Failed to remove stale locks."
exit 1
fi
else
log_message "No stale locks found."
fi
}
# Function: Perform integrity check
perform_integrity_check() {
log_message "Performing repository integrity check..."
if restic check --read-data-subset=5% >> "$LOG_FILE" 2>&1; then
log_message "Repository integrity check passed."
else
log_message "ERROR: Repository integrity check failed."
exit 1
fi
}
# Main execution
main() {
log_message "Starting repository stats check and maintenance..."
validate_dependencies
validate_repository
check_and_remove_stale_locks
check_repository_stats
apply_retention_policy
perform_integrity_check
log_message "Repository stats check and maintenance completed successfully."
}
# Execute main function
main

View File

@ -5,44 +5,53 @@ BACKUP_SCRIPT="/home/litespeed/mb-backups/backup_all.sh"
LOG_DIR="/home/litespeed/mb-backups/logs/auto"
ACTION_LOG_FILE="${LOG_DIR}/schedule_actions.log"
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
mkdir -p "$LOG_DIR"
# Logging function
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() {
if ! command -v crontab &>/dev/null; then
echo "Cron is not installed. Installing..."
sudo dnf install -y cronie || { echo "Failed to install cron."; exit 1; }
log_action "Cron is not installed. Installing..."
sudo dnf install -y cronie || { log_action "Failed to install cron."; exit 1; }
fi
if ! systemctl is-active --quiet crond; then
echo "Starting cron service..."
log_action "Starting cron service..."
sudo systemctl start crond
sudo systemctl enable crond
sudo systemctl enable crond || { log_action "Failed to enable cron service."; exit 1; }
fi
if systemctl is-active --quiet crond; then
echo "Cron service is running."
else
echo "Failed to start cron service."
log_action "Failed to start cron service."
exit 1
fi
log_action "Cron service is running and ready."
}
# Function: Validate cron schedule format
validate_cron_syntax() {
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
echo "Invalid cron schedule format: $schedule"
log_action "Invalid cron schedule format: $schedule"
log_action "ERROR: Invalid cron schedule format: $schedule"
exit 1
fi
}
# Function: Add or update a cron job
add_update_cron_job() {
local action="$1"
local schedule="$2"
@ -51,46 +60,44 @@ add_update_cron_job() {
validate_cron_syntax "$schedule"
if [ -z "$restic_password" ]; then
echo "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"
log_action "ERROR: Restic password is required."
exit 1
fi
# Prepare the cron job command
local cmd="SHELL=/bin/bash"
cmd+=" PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
cmd+=" RESTIC_PASSWORD=\"$restic_password\""
cmd+=" $BACKUP_SCRIPT"
local cmd="SHELL=/bin/bash PATH=$CRON_PATH RESTIC_PASSWORD=\"$restic_password\""
cmd+=" $BACKUP_SCRIPT auto"
cmd+=" > \"${BACKUP_LOG_PREFIX}\$(date +\\%Y-\\%m-\\%d_\\%H-\\%M-\\%S).log\" 2>&1"
# Debug: Output the command to verify
echo "Adding the following cron job:"
echo "$schedule $cmd"
# Remove any existing lines containing $BACKUP_SCRIPT, then add the new one
# Remove existing job and add a new one
(crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT"; echo "$schedule $cmd") | crontab -
if crontab -l | grep -q "$BACKUP_SCRIPT"; then
echo "Cron job $action successfully."
if crontab -l | grep -q "$BACKUP_SCRIPT auto"; then
log_action "Cron job $action successfully: $schedule"
else
echo "Failed to $action cron job. Please check logs for details."
log_action "Failed to $action cron job: $schedule"
log_action "ERROR: Failed to $action cron job. Please check logs."
exit 1
fi
}
# Function: Remove cron jobs
remove_cron_jobs() {
crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT auto" | crontab -
log_action "All backup schedules removed."
}
# 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
case "$1" in
add|update)
if [ "$#" -ne 3 ]; then
echo "Usage for add/update: $0 {add|update} 'schedule' 'restic_password'"
@ -101,16 +108,18 @@ case $1 in
fi
;;
remove)
tmp_cron=$(mktemp)
crontab -l 2>/dev/null | grep -v "$BACKUP_SCRIPT" > "$tmp_cron"
crontab "$tmp_cron"
rm -f "$tmp_cron"
echo "All backup schedules removed."
log_action "All backup schedules removed."
remove_cron_jobs
;;
list)
list_cron_jobs
;;
*)
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"
exit 1
;;
esac
}
# Execute main function
main "$@"

View File

@ -1,23 +1,23 @@
#!/bin/bash
# Exit immediately on errors
# Exit on errors and enable error tracing
set -e
trap 'log "ERROR: An error occurred during the restoration process."' ERR
# Validate input parameters
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <snapshot_id> <restic_password>"
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <snapshot_id>"
exit 1
fi
# Assign input to variables
SNAPSHOT_ID=$1
RESTIC_PASSWORD=$2
RESTIC_PASSWORD_FILE="/etc/restic-password"
RESTIC_REPOSITORY="/mnt/backups"
LOG_DIR="/home/litespeed/mb-backups/logs/restore"
WP_CONFIG="/var/www/webroot/ROOT/wp-config.php"
# Set up the environment
export RESTIC_PASSWORD
# Ensure the log directory exists
mkdir -p "$LOG_DIR"
LOG_FILE="${LOG_DIR}/restore_$(date +'%Y-%m-%d_%H-%M-%S').log"
@ -26,45 +26,73 @@ log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Check for required dependencies
# Validate required dependencies
validate_dependencies() {
for cmd in restic jq mysql; do
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
fi
done
}
# Ensure there are no stale locks in the repository
# Set up Restic environment
setup_restic_environment() {
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 -r "$RESTIC_REPOSITORY" list locks | grep -q "lock"; then
if restic list locks | grep -q "lock"; then
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."
else
log "No stale locks found. Proceeding with restoration."
fi
}
# Extract database credentials from wp-config.php
extract_db_credentials() {
if [ ! -f "$WP_CONFIG" ]; then
log "Error: wp-config.php not found at $WP_CONFIG. Ensure WordPress is installed."
log "ERROR: wp-config.php not found at $WP_CONFIG. Ensure WordPress is installed."
exit 1
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")
DB_HOST=$(awk -F"'" '/define\( *'"'"'DB_HOST'"'"'/{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
# Set default DB_HOST if empty
if [ -z "$DB_HOST" ]; then
DB_HOST="localhost"
fi
log "Starting restoration for snapshot ID: $SNAPSHOT_ID..."
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\")")
# 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."
log "ERROR: Snapshot ID $SNAPSHOT_ID not found in the repository."
exit 1
fi
@ -72,49 +100,63 @@ 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."
log "ERROR: Snapshot $SNAPSHOT_ID does not contain valid paths."
exit 1
fi
log "Snapshot Data Retrieved: Path=$SNAPSHOT_PATH, Tags=$SNAPSHOT_TAGS"
log "Snapshot metadata retrieved: Path=$SNAPSHOT_PATH, Tags=$SNAPSHOT_TAGS"
}
# Determine the restoration type based on the tags
if [[ "$SNAPSHOT_TAGS" == *"wordpress_db"* ]] && [[ "$SNAPSHOT_PATH" == "/stdin" ]]; then
# 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..."
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."
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 for Snapshot ID: $SNAPSHOT_ID."
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"
log "Detected core files backup. Restoring to $RESTORE_DIR..."
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Core files restoration completed successfully for Snapshot ID: $SNAPSHOT_ID."
if restic restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Core files restoration completed successfully."
else
log "Error: Core files restoration failed for Snapshot ID: $SNAPSHOT_ID."
log "ERROR: Core files restoration failed."
exit 1
fi
elif [[ "$SNAPSHOT_TAGS" == *"media_themes"* ]]; then
RESTORE_DIR="/var/www/webroot/ROOT/wp-content/uploads"
log "Detected media files backup. Restoring to $RESTORE_DIR..."
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Media files restoration completed successfully for Snapshot ID: $SNAPSHOT_ID."
if restic restore "$SNAPSHOT_ID" --target "$RESTORE_DIR"; then
log "Media files restoration completed successfully."
else
log "Error: Media files restoration failed for Snapshot ID: $SNAPSHOT_ID."
log "ERROR: Media files restoration failed."
exit 1
fi
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"
mkdir -p "$TEMP_RESTORE_DIR"
if restic -r "$RESTIC_REPOSITORY" restore "$SNAPSHOT_ID" --target "$TEMP_RESTORE_DIR"; then
log "General file restoration completed successfully to temporary directory: $TEMP_RESTORE_DIR."
if restic restore "$SNAPSHOT_ID" --target "$TEMP_RESTORE_DIR"; then
log "General restoration completed successfully to $TEMP_RESTORE_DIR."
else
log "Error: File restoration failed for Snapshot ID: $SNAPSHOT_ID."
log "ERROR: General restoration failed."
exit 1
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."

View File

@ -3,42 +3,78 @@
# Exit immediately on error
set -e
# Display usage if no tag is provided
if [ "$#" -ne 1 ]; then
# Configuration
backupPath='/mnt/backups'
password_file="/etc/restic-password"
LOG_FILE="/var/log/restic_snapshot.log"
# Logging function
log_message() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Function: Display usage
display_usage() {
echo "Usage: $0 <tag>"
echo "Available tags: main_backup, wordpress_db, core_files, media_themes, full_backup"
echo "Available tags:"
restic -r "$RESTIC_REPOSITORY" snapshots --json 2>/dev/null | jq -r '.[].tags[]' | sort -u || echo "main_backup, wordpress_db, core_files, media_themes, full_backup"
exit 1
}
# Ensure dependencies are installed
validate_dependencies() {
for cmd in restic jq; do
if ! command -v "$cmd" &>/dev/null; then
log_message "ERROR: Required command '$cmd' not found. Please install it."
exit 1
fi
done
}
# Validate environment
validate_environment() {
if [ ! -f "$password_file" ]; then
log_message "ERROR: Password file not found at $password_file"
exit 1
fi
if [ ! -d "$backupPath" ]; then
log_message "ERROR: Backup path '$backupPath' does not exist or is not accessible."
exit 1
fi
}
# Main script logic
main() {
# Ensure a tag is provided
if [ "$#" -ne 1 ]; then
display_usage
fi
# Assign input argument
TAG=$1
backupPath='/mnt/backups'
password_file="/etc/restic-password" # Use a password file instead of embedding the password
# Validate if the password file exists
if [ ! -f "$password_file" ]; then
echo "Error: Password file not found at $password_file"
exit 1
fi
# Set Restic environment variables
export RESTIC_REPOSITORY="$backupPath"
export RESTIC_PASSWORD=$(cat "$password_file")
# Validate the provided tag against known tags
case "$TAG" in
main_backup|wordpress_db|core_files|media_themes|full_backup)
# Use the --json flag to output the snapshots in JSON format
if restic -r "$RESTIC_REPOSITORY" snapshots --tag "$TAG" --json; then
echo "Snapshots for tag '$TAG' displayed successfully."
# Validate the tag
if ! restic -r "$RESTIC_REPOSITORY" snapshots --json 2>/dev/null | jq -e ".[] | select(.tags[] == \"$TAG\")" &>/dev/null; then
log_message "ERROR: Unknown or unused tag '$TAG'."
display_usage
fi
# Display snapshots for the provided tag
log_message "Retrieving snapshots for tag '$TAG'..."
if restic -r "$RESTIC_REPOSITORY" snapshots --tag "$TAG" --json | jq -r '.[] | "\(.short_id) \(.time) \(.tags | join(", "))"' 2>/dev/null; then
log_message "Snapshots for tag '$TAG' displayed successfully."
else
echo "Error: Unable to display snapshots for tag '$TAG'."
log_message "ERROR: Unable to display snapshots for tag '$TAG'."
exit 1
fi
;;
*)
echo "Error: Unknown tag '$TAG'."
echo "Available tags: main_backup, wordpress_db, core_files, media_themes, full_backup"
exit 1
;;
esac
}
# Run validations and execute the main function
validate_dependencies
validate_environment
main "$@"