Configure automated MySQL database backups with compression, encryption, and rotation using systemd timers. Includes monitoring and alerting for backup failures.
Prerequisites
- MySQL server running
- Root or sudo access
- At least 2GB free disk space
What this solves
MySQL databases need regular backups to protect against data loss from hardware failures, accidental deletions, or corruption. Manual backups are unreliable and time-consuming. This tutorial sets up automated MySQL backups with compression to save disk space, rotation to manage retention periods, and monitoring to alert you when backups fail. You'll create a robust backup system that runs automatically without manual intervention.
Step-by-step installation
Install MySQL backup tools and dependencies
Install the necessary tools for creating compressed MySQL backups and handling encryption. These packages provide mysqldump for database exports and compression utilities.
sudo apt update
sudo apt install -y mysql-client gzip pigz gnupg2 mailutils
Create backup user and directories
Create a dedicated MySQL user for backups with minimal required privileges. This follows the principle of least privilege for security. Also create the backup directory structure with proper permissions.
sudo mysql -e "CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'SecureBackupPass123!';"
sudo mysql -e "GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON . TO 'backup_user'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
sudo mkdir -p /var/backups/mysql
sudo mkdir -p /var/log/mysql-backup
sudo groupadd mysql-backup
sudo useradd -r -g mysql-backup -s /bin/false mysql-backup
sudo chown mysql-backup:mysql-backup /var/backups/mysql /var/log/mysql-backup
sudo chmod 750 /var/backups/mysql /var/log/mysql-backup
Generate GPG encryption key for backups
Create a GPG key pair for encrypting backup files. This ensures that even if backup files are compromised, the data remains protected without the private key.
sudo su - mysql-backup -s /bin/bash
gpg --batch --generate-key <
Create MySQL backup configuration file
Store MySQL credentials securely in a configuration file with restricted permissions. This prevents passwords from appearing in process lists or command history.
[client]
user=backup_user
password=SecureBackupPass123!
host=localhost
port=3306
[mysql]
default-character-set=utf8mb4
[mysqldump]
single-transaction=true
routines=true
triggers=true
events=true
opt=true
sudo chown mysql-backup:mysql-backup /etc/mysql/backup.cnf
sudo chmod 600 /etc/mysql/backup.cnf
Create comprehensive backup script
Create the main backup script that handles database dumps, compression, encryption, and rotation. This script includes error handling and logging for reliable operation.
#!/bin/bash
MySQL Backup Script with Compression and Rotation
Author: Infrastructure Team
Version: 2.1
set -euo pipefail
Configuration
BACKUP_DIR="/var/backups/mysql"
LOG_FILE="/var/log/mysql-backup/backup.log"
MYSQL_CONFIG="/etc/mysql/backup.cnf"
RETENTION_DAYS=30
COMPRESSION_LEVEL=6
GPG_RECIPIENT="backup@example.com"
ALERT_EMAIL="admin@example.com"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
HOSTNAME=$(hostname)
Logging function
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
Error handling
error_exit() {
log "ERROR: $1"
echo "MySQL backup failed on $HOSTNAME at $(date)" | mail -s "MySQL Backup Failed - $HOSTNAME" "$ALERT_EMAIL" 2>/dev/null || true
exit 1
}
Check prerequisites
check_prerequisites() {
log "Checking prerequisites..."
# Check if MySQL is accessible
if ! mysql --defaults-file="$MYSQL_CONFIG" -e "SELECT 1" >/dev/null 2>&1; then
error_exit "Cannot connect to MySQL server"
fi
# Check backup directory
if [[ ! -d "$BACKUP_DIR" ]]; then
mkdir -p "$BACKUP_DIR" || error_exit "Cannot create backup directory"
fi
# Check disk space (require at least 2GB free)
AVAILABLE_SPACE=$(df "$BACKUP_DIR" | awk 'NR==2 {print $4}')
if [[ $AVAILABLE_SPACE -lt 2097152 ]]; then
error_exit "Insufficient disk space. Available: ${AVAILABLE_SPACE}KB, Required: 2GB"
fi
log "Prerequisites check completed successfully"
}
Get list of databases
get_databases() {
mysql --defaults-file="$MYSQL_CONFIG" -e "SHOW DATABASES;" | grep -Ev '^(Database|information_schema|performance_schema|mysql|sys)$'
}
Backup individual database
backup_database() {
local db_name=$1
local backup_file="${BACKUP_DIR}/${HOSTNAME}_${db_name}_${TIMESTAMP}.sql"
local compressed_file="${backup_file}.gz"
local encrypted_file="${compressed_file}.gpg"
log "Starting backup for database: $db_name"
# Create database dump
if ! mysqldump --defaults-file="$MYSQL_CONFIG" \
--single-transaction \
--routines \
--triggers \
--events \
--add-drop-database \
--databases "$db_name" > "$backup_file"; then
error_exit "Failed to dump database: $db_name"
fi
# Compress backup
if ! pigz -"$COMPRESSION_LEVEL" "$backup_file"; then
rm -f "$backup_file"
error_exit "Failed to compress backup for database: $db_name"
fi
# Encrypt backup
if ! gpg --trust-model always --batch --yes --cipher-algo AES256 \
--compress-algo 1 --recipient "$GPG_RECIPIENT" \
--encrypt "$compressed_file"; then
rm -f "$compressed_file"
error_exit "Failed to encrypt backup for database: $db_name"
fi
# Remove unencrypted compressed file
rm -f "$compressed_file"
# Calculate and log file size
local file_size=$(stat -c%s "$encrypted_file")
local file_size_mb=$((file_size / 1024 / 1024))
log "Successfully backed up database: $db_name (${file_size_mb}MB)"
}
Rotate old backups
rotate_backups() {
log "Starting backup rotation (retention: $RETENTION_DAYS days)..."
local deleted_count=0
while IFS= read -r -d '' file; do
rm -f "$file"
((deleted_count++))
done < <(find "$BACKUP_DIR" -name "*.gpg" -type f -mtime +$RETENTION_DAYS -print0)
log "Backup rotation completed. Deleted $deleted_count old backup files"
}
Generate backup report
generate_report() {
local total_size=$(find "$BACKUP_DIR" -name "*.gpg" -type f -exec stat -c%s {} + | awk '{sum+=$1} END {print sum/1024/1024}')
local backup_count=$(find "$BACKUP_DIR" -name "*_${TIMESTAMP}.sql.gz.gpg" -type f | wc -l)
log "Backup completed successfully:"
log " - Databases backed up: $backup_count"
log " - Total backup size: ${total_size}MB"
log " - Backup location: $BACKUP_DIR"
log " - Retention period: $RETENTION_DAYS days"
}
Main execution
main() {
log "=== MySQL Backup Started ==="
check_prerequisites
# Get databases and backup each one
local databases
databases=$(get_databases)
if [[ -z "$databases" ]]; then
error_exit "No databases found to backup"
fi
while IFS= read -r database; do
backup_database "$database"
done <<< "$databases"
rotate_backups
generate_report
log "=== MySQL Backup Completed Successfully ==="
}
Run main function
main "$@"
Set script permissions and test
Configure proper permissions for the backup script and test it manually to ensure everything works correctly before automating it.
sudo chown mysql-backup:mysql-backup /usr/local/bin/mysql-backup.sh
sudo chmod 750 /usr/local/bin/mysql-backup.sh
Test the backup script
sudo -u mysql-backup /usr/local/bin/mysql-backup.sh
Create systemd service for backups
Create a systemd service unit that runs the backup script. This provides better logging and management compared to running scripts directly from cron.
[Unit]
Description=MySQL Database Backup Service
Wants=mysql-backup.timer
After=mysql.service
Requires=mysql.service
[Service]
Type=oneshot
User=mysql-backup
Group=mysql-backup
ExecStart=/usr/local/bin/mysql-backup.sh
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ReadWritePaths=/var/backups/mysql /var/log/mysql-backup
NoNewPrivileges=yes
UMask=0077
Security hardening
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictNamespaces=yes
SystemCallFilter=@system-service
SystemCallFilter=~@debug @mount @cpu-emulation @obsolete @privileged
[Install]
WantedBy=multi-user.target
Create systemd timer for automated scheduling
Configure a systemd timer to run backups automatically. This example runs backups daily at 2:00 AM with some randomization to prevent multiple servers from backing up simultaneously.
[Unit]
Description=MySQL Database Backup Timer
Requires=mysql-backup.service
[Timer]
Run daily at 2:00 AM with 30 minute randomization
OnCalendar=--* 02:00:00
RandomizedDelaySec=1800
Persistent=true
AccuracySec=1m
Prevent running if system was suspended
WakeSystem=false
[Install]
WantedBy=timers.target
Enable and start the backup timer
Enable the systemd timer and service so they start automatically on boot. The timer will handle scheduling the backup service.
sudo systemctl daemon-reload
sudo systemctl enable mysql-backup.service
sudo systemctl enable mysql-backup.timer
sudo systemctl start mysql-backup.timer
Create backup monitoring script
Create a monitoring script that checks backup status and sends alerts if backups fail or become too old. This provides proactive monitoring of your backup system.
#!/bin/bash
MySQL Backup Monitor Script
Checks backup status and sends alerts
set -euo pipefail
BACKUP_DIR="/var/backups/mysql"
LOG_FILE="/var/log/mysql-backup/backup.log"
ALERT_EMAIL="admin@example.com"
MAX_BACKUP_AGE_HOURS=26 # Alert if no backup in 26 hours
HOSTNAME=$(hostname)
Check if recent backups exist
check_backup_freshness() {
local latest_backup
latest_backup=$(find "$BACKUP_DIR" -name "*.gpg" -type f -newermt "-$MAX_BACKUP_AGE_HOURS hours" | head -1)
if [[ -z "$latest_backup" ]]; then
echo "No recent MySQL backups found on $HOSTNAME. Last backup is older than $MAX_BACKUP_AGE_HOURS hours." | \
mail -s "MySQL Backup Alert - No Recent Backups - $HOSTNAME" "$ALERT_EMAIL"
exit 1
fi
}
Check for errors in log file
check_backup_errors() {
if [[ -f "$LOG_FILE" ]]; then
local recent_errors
recent_errors=$(grep -i "error\|failed" "$LOG_FILE" | tail -5)
if [[ -n "$recent_errors" ]]; then
echo "Recent errors found in MySQL backup log on $HOSTNAME:\n\n$recent_errors" | \
mail -s "MySQL Backup Errors - $HOSTNAME" "$ALERT_EMAIL"
fi
fi
}
Check disk space
check_disk_space() {
local available_space
available_space=$(df "$BACKUP_DIR" | awk 'NR==2 {print $4}')
local available_gb=$((available_space / 1024 / 1024))
if [[ $available_gb -lt 1 ]]; then
echo "Low disk space for MySQL backups on $HOSTNAME. Available: ${available_gb}GB" | \
mail -s "MySQL Backup Disk Space Warning - $HOSTNAME" "$ALERT_EMAIL"
fi
}
Generate backup status report
generate_status_report() {
local backup_count
local total_size
local latest_backup_time
backup_count=$(find "$BACKUP_DIR" -name "*.gpg" -type f | wc -l)
total_size=$(find "$BACKUP_DIR" -name "*.gpg" -type f -exec stat -c%s {} + | awk '{sum+=$1} END {print sum/1024/1024/1024}')
latest_backup_time=$(find "$BACKUP_DIR" -name "*.gpg" -type f -printf '%T@ %p\n' | sort -n | tail -1 | awk '{print $2}' | xargs stat -c %y 2>/dev/null || echo "No backups found")
echo "MySQL Backup Status Report for $HOSTNAME:"
echo " - Total backup files: $backup_count"
echo " - Total backup size: ${total_size}GB"
echo " - Latest backup: $latest_backup_time"
echo " - Backup directory: $BACKUP_DIR"
}
Main monitoring function
main() {
check_backup_freshness
check_backup_errors
check_disk_space
# Optionally generate weekly status report
if [[ $(date +%u) == "1" ]]; then
generate_status_report | mail -s "Weekly MySQL Backup Status - $HOSTNAME" "$ALERT_EMAIL"
fi
}
main "$@"
Set up monitoring timer
Create a systemd timer to run the monitoring script every 6 hours. This ensures you're alerted quickly if backups stop working.
sudo chown mysql-backup:mysql-backup /usr/local/bin/mysql-backup-monitor.sh
sudo chmod 750 /usr/local/bin/mysql-backup-monitor.sh
[Unit]
Description=MySQL Backup Monitor Service
After=network.target
[Service]
Type=oneshot
User=mysql-backup
Group=mysql-backup
ExecStart=/usr/local/bin/mysql-backup-monitor.sh
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
[Unit]
Description=MySQL Backup Monitor Timer
Requires=mysql-backup-monitor.service
[Timer]
OnCalendar=--* 00,06,12,18:15:00
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable mysql-backup-monitor.timer
sudo systemctl start mysql-backup-monitor.timer
Configure log rotation
Set up logrotate to manage backup log files and prevent them from consuming excessive disk space over time.
/var/log/mysql-backup/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 mysql-backup mysql-backup
postrotate
systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
Verify your setup
Test your automated backup system to ensure all components are working correctly.
# Check timer status
sudo systemctl status mysql-backup.timer
sudo systemctl status mysql-backup-monitor.timer
List scheduled timers
sudo systemctl list-timers mysql-backup*
Test backup manually
sudo systemctl start mysql-backup.service
sudo systemctl status mysql-backup.service
Check backup files
sudo ls -la /var/backups/mysql/
Check logs
sudo tail -f /var/log/mysql-backup/backup.log
Test backup decryption
sudo -u mysql-backup gpg --decrypt /var/backups/mysql/$(ls /var/backups/mysql/ | head -1) | head -10
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Permission denied errors | Incorrect file ownership or permissions | Check ownership: sudo chown -R mysql-backup:mysql-backup /var/backups/mysql /var/log/mysql-backup |
| MySQL access denied | Wrong credentials in backup.cnf | Verify MySQL user permissions: mysql -u backup_user -p -e "SHOW GRANTS" |
| GPG encryption fails | GPG key not found or expired | Check GPG keys: sudo -u mysql-backup gpg --list-keys |
| Backup timer not running | Timer not enabled or started | Enable timer: sudo systemctl enable --now mysql-backup.timer |
| Email alerts not working | Mail system not configured | Configure postfix: sudo dpkg-reconfigure postfix |
| Disk space full | Backup retention too long or large databases | Reduce retention days or increase disk space |
| Backup files corrupt | Compression or encryption issues | Test pipeline manually: mysqldump | pigz | gpg --encrypt |
Next steps
- Implement Redis backup automation with compression and encryption
- Configure MongoDB 8.0 backup automation with systemd timers and compression
- Set up MySQL backup encryption and remote storage with rsync
- Monitor PostgreSQL performance with Prometheus and Grafana dashboards
- Setup remote backup storage with S3-compatible encryption and automated retention policies
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# MySQL Backup System Installation Script
# Installs automated MySQL database backups with compression and rotation
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Default configuration
BACKUP_USER="backup_user"
BACKUP_PASS=""
MYSQL_ROOT_PASS=""
# Functions
log() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
cleanup() {
if [[ $? -ne 0 ]]; then
error "Installation failed. Cleaning up..."
systemctl disable mysql-backup.timer 2>/dev/null || true
rm -f /etc/systemd/system/mysql-backup.{service,timer}
userdel mysql-backup 2>/dev/null || true
groupdel mysql-backup 2>/dev/null || true
fi
}
usage() {
echo "Usage: $0 --mysql-root-password PASSWORD [--backup-password PASSWORD]"
echo " --mysql-root-password: MySQL root password (required)"
echo " --backup-password: Password for backup user (auto-generated if not provided)"
exit 1
}
check_root() {
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
exit 1
fi
}
detect_distro() {
if [[ ! -f /etc/os-release ]]; then
error "Cannot detect OS distribution"
exit 1
fi
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
MAIL_PACKAGE="mailutils"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
MAIL_PACKAGE="mailx"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
MAIL_PACKAGE="mailx"
;;
*)
error "Unsupported distribution: $ID"
exit 1
;;
esac
}
generate_password() {
openssl rand -base64 32 | tr -d "=+/" | cut -c1-25
}
install_packages() {
echo "[1/7] Installing required packages..."
$PKG_UPDATE
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL mysql-client gzip pigz gnupg2 $MAIL_PACKAGE
else
$PKG_INSTALL mysql gnupg2 pigz $MAIL_PACKAGE
fi
log "Packages installed successfully"
}
setup_mysql_user() {
echo "[2/7] Setting up MySQL backup user..."
if [[ -z "$BACKUP_PASS" ]]; then
BACKUP_PASS=$(generate_password)
warn "Generated backup password: $BACKUP_PASS"
fi
mysql -u root -p"$MYSQL_ROOT_PASS" -e "CREATE USER IF NOT EXISTS '${BACKUP_USER}'@'localhost' IDENTIFIED BY '${BACKUP_PASS}';"
mysql -u root -p"$MYSQL_ROOT_PASS" -e "GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO '${BACKUP_USER}'@'localhost';"
mysql -u root -p"$MYSQL_ROOT_PASS" -e "FLUSH PRIVILEGES;"
log "MySQL backup user created successfully"
}
create_directories() {
echo "[3/7] Creating backup directories and user..."
groupadd -f mysql-backup
useradd -r -g mysql-backup -s /bin/false -d /var/lib/mysql-backup mysql-backup 2>/dev/null || true
mkdir -p /var/backups/mysql
mkdir -p /var/log/mysql-backup
mkdir -p /etc/mysql-backup
mkdir -p /var/lib/mysql-backup/.gnupg
chown mysql-backup:mysql-backup /var/backups/mysql /var/log/mysql-backup /var/lib/mysql-backup /var/lib/mysql-backup/.gnupg
chmod 750 /var/backups/mysql /var/log/mysql-backup /var/lib/mysql-backup
chmod 700 /var/lib/mysql-backup/.gnupg
log "Directories and user created successfully"
}
setup_mysql_config() {
echo "[4/7] Creating MySQL configuration..."
cat > /etc/mysql-backup/mysql.cnf << EOF
[client]
user=${BACKUP_USER}
password=${BACKUP_PASS}
host=localhost
EOF
chown mysql-backup:mysql-backup /etc/mysql-backup/mysql.cnf
chmod 600 /etc/mysql-backup/mysql.cnf
log "MySQL configuration created"
}
generate_gpg_key() {
echo "[5/7] Generating GPG encryption key..."
cat > /tmp/gpg-batch << EOF
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: MySQL Backup
Name-Email: mysql-backup@$(hostname -f)
Expire-Date: 0
%no-protection
%commit
EOF
sudo -u mysql-backup gpg --homedir /var/lib/mysql-backup/.gnupg --batch --generate-key /tmp/gpg-batch
rm -f /tmp/gpg-batch
log "GPG key generated successfully"
}
create_backup_script() {
echo "[6/7] Creating backup script..."
cat > /usr/local/bin/mysql-backup.sh << 'EOF'
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/var/backups/mysql"
LOG_FILE="/var/log/mysql-backup/backup.log"
CONFIG_FILE="/etc/mysql-backup/mysql.cnf"
RETENTION_DAYS=7
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
HOSTNAME=$(hostname -s)
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
error_exit() {
log "ERROR: $1"
exit 1
}
# Test MySQL connection
mysql --defaults-file="$CONFIG_FILE" -e "SELECT 1;" >/dev/null || error_exit "Cannot connect to MySQL"
# Get list of databases
DATABASES=$(mysql --defaults-file="$CONFIG_FILE" -e "SHOW DATABASES;" | grep -Ev '^(Database|information_schema|performance_schema|mysql|sys)$')
for db in $DATABASES; do
log "Backing up database: $db"
BACKUP_FILE="${BACKUP_DIR}/${HOSTNAME}_${db}_${TIMESTAMP}.sql"
# Create dump
mysqldump --defaults-file="$CONFIG_FILE" \
--single-transaction \
--routines \
--triggers \
--events \
--databases "$db" > "$BACKUP_FILE" || error_exit "Failed to dump $db"
# Compress
pigz -9 "$BACKUP_FILE" || error_exit "Failed to compress $db backup"
# Encrypt
gpg --homedir /var/lib/mysql-backup/.gnupg --trust-model always --batch --yes \
--cipher-algo AES256 --recipient mysql-backup@$(hostname -f) \
--encrypt "${BACKUP_FILE}.gz" || error_exit "Failed to encrypt $db backup"
rm -f "${BACKUP_FILE}.gz"
log "Successfully backed up database: $db"
done
# Cleanup old backups
find "$BACKUP_DIR" -name "*.gpg" -mtime +$RETENTION_DAYS -delete
log "Backup rotation completed"
log "All database backups completed successfully"
EOF
chmod 755 /usr/local/bin/mysql-backup.sh
chown mysql-backup:mysql-backup /usr/local/bin/mysql-backup.sh
log "Backup script created"
}
setup_systemd_timer() {
echo "[7/7] Setting up systemd timer..."
cat > /etc/systemd/system/mysql-backup.service << EOF
[Unit]
Description=MySQL Database Backup
After=mysqld.service mysql.service mariadb.service
[Service]
Type=oneshot
User=mysql-backup
Group=mysql-backup
ExecStart=/usr/local/bin/mysql-backup.sh
StandardOutput=journal
StandardError=journal
EOF
cat > /etc/systemd/system/mysql-backup.timer << EOF
[Unit]
Description=Run MySQL backup daily
Requires=mysql-backup.service
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1800
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable mysql-backup.timer
systemctl start mysql-backup.timer
log "Systemd timer configured and started"
}
verify_installation() {
log "Verifying installation..."
if systemctl is-active --quiet mysql-backup.timer; then
log "✓ Backup timer is active"
else
error "✗ Backup timer is not active"
return 1
fi
if sudo -u mysql-backup mysql --defaults-file=/etc/mysql-backup/mysql.cnf -e "SELECT 1;" >/dev/null 2>&1; then
log "✓ MySQL connection test passed"
else
error "✗ MySQL connection test failed"
return 1
fi
log "Installation completed successfully!"
log "Backups will run daily. Manual test: sudo -u mysql-backup /usr/local/bin/mysql-backup.sh"
warn "Save the backup password securely: $BACKUP_PASS"
}
# Main execution
trap cleanup ERR
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--mysql-root-password)
MYSQL_ROOT_PASS="$2"
shift 2
;;
--backup-password)
BACKUP_PASS="$2"
shift 2
;;
-h|--help)
usage
;;
*)
error "Unknown option: $1"
usage
;;
esac
done
if [[ -z "$MYSQL_ROOT_PASS" ]]; then
error "MySQL root password is required"
usage
fi
check_root
detect_distro
install_packages
setup_mysql_user
create_directories
setup_mysql_config
generate_gpg_key
create_backup_script
setup_systemd_timer
verify_installation
Review the script before running. Execute with: bash install.sh