Securing CloudPanel on Ubuntu 24.04 Part 11

22/11/2024 22/11/2024 security 6 mins read
Table Of Contents

Part 11: Automated Backup and Disaster Recovery System #

Let’s create a comprehensive backup and recovery system that ensures both data integrity and quick recovery capabilities.

#!/bin/bash
# Create backup management script
sudo nano /usr/local/bin/cloudpanel-backup-manager.sh

#

#!/bin/bash
# Initialize paths and configuration
CP_HOME="/home/clp"
DB_PATH="${CP_HOME}/htdocs/app/data/db.sq3"
BACKUP_ROOT="/backup/cloudpanel"
LOG_DIR="${CP_HOME}/logs/backup"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# Create necessary directories
mkdir -p "${BACKUP_ROOT}/{system,sites,databases,ssl,logs}" "$LOG_DIR"
# Function to read site configurations from CloudPanel database
get_site_configurations() {
sqlite3 "$DB_PATH" "
SELECT
s.id,
s.domain_name,
s.user,
s.root_directory,
d.name as db_name
FROM site s
LEFT JOIN database d ON s.id = d.site_id
WHERE s.type = 'vhost';"
}
# Function to backup CloudPanel system files
backup_system_files() {
local backup_dir="${BACKUP_ROOT}/system/${TIMESTAMP}"
echo "Backing up system files to $backup_dir"
# Create backup directories
mkdir -p "$backup_dir"/{config,services,database,ssl}
# Backup core configuration
tar -czf "$backup_dir/config/cloudpanel_config.tar.gz" \
"${CP_HOME}/services/nginx/nginx.conf" \
"${CP_HOME}/services/php-fpm" \
"${CP_HOME}/services/nginx/sites-enabled" \
--exclude='*.log'
# Backup SSL certificates
cp -r "${CP_HOME}/services/nginx/ssl-certificates" "$backup_dir/ssl/"
# Backup CloudPanel database
sqlite3 "$DB_PATH" ".backup '${backup_dir}/database/cloudpanel.sq3'"
# Create backup manifest
{
echo "CloudPanel System Backup - $(date)"
echo "================================="
echo "Backup Type: System Files"
echo "Timestamp: $TIMESTAMP"
find "$backup_dir" -type f -exec ls -lh {} \;
} > "$backup_dir/MANIFEST.txt"
}
# Function to backup individual sites
backup_site() {
local domain="$1"
local user="$2"
local root_dir="$3"
local db_name="$4"
local site_backup_dir="${BACKUP_ROOT}/sites/${domain}/${TIMESTAMP}"
echo "Backing up site: $domain to $site_backup_dir"
# Create site backup directory
mkdir -p "$site_backup_dir"/{files,database,logs,config}
# Backup site files
tar -czf "$site_backup_dir/files/site_files.tar.gz" \
"$root_dir" \
--exclude='*/cache/*' \
--exclude='*/tmp/*' \
--exclude='*/logs/*'
# Backup site database if exists
if [ ! -z "$db_name" ]; then
mysqldump --single-transaction \
--quick \
--lock-tables=false \
"$db_name" > "$site_backup_dir/database/${db_name}.sql"
# Compress database backup
gzip "$site_backup_dir/database/${db_name}.sql"
fi
# Backup site configuration
cp "/home/clp/services/nginx/sites-enabled/${domain}.conf" \
"$site_backup_dir/config/"
# Create site backup manifest
{
echo "Site Backup - $domain"
echo "================================="
echo "Backup Type: Site Files and Configuration"
echo "Timestamp: $TIMESTAMP"
echo "User: $user"
echo "Database: $db_name"
find "$site_backup_dir" -type f -exec ls -lh {} \;
} > "$site_backup_dir/MANIFEST.txt"
}
# Function to verify backup integrity
verify_backup() {
local backup_dir="$1"
local backup_type="$2"
local verification_log="${LOG_DIR}/verification_${TIMESTAMP}.log"
echo "Verifying backup integrity for $backup_type"
# Verify tar archives
find "$backup_dir" -name "*.tar.gz" -type f | while read -r archive; do
if ! tar -tzf "$archive" >/dev/null 2>&1; then
echo "ERROR: Corrupt archive detected: $archive" >> "$verification_log"
return 1
fi
done
# Verify database backups
find "$backup_dir" -name "*.sql.gz" -type f | while read -r db_backup; do
if ! gunzip -t "$db_backup" >/dev/null 2>&1; then
echo "ERROR: Corrupt database backup detected: $db_backup" >> "$verification_log"
return 1
fi
done
# Record successful verification
echo "Backup verification completed successfully for $backup_type" >> "$verification_log"
return 0
}
# Function to handle backup rotation
rotate_backups() {
local backup_path="$1"
local retention_days=7
echo "Rotating old backups in $backup_path"
# Remove backups older than retention period
find "$backup_path" -type d -mtime +$retention_days -exec rm -rf {} \;
}
# Function to create recovery script
create_recovery_script() {
local backup_dir="$1"
local recovery_script="${backup_dir}/recover.sh"
cat > "$recovery_script" <<'EOF'
#!/bin/bash
# CloudPanel Recovery Script
CP_HOME="/home/clp"
# Verify environment
if [ ! -d "$CP_HOME" ]; then
echo "ERROR: CloudPanel directory not found!"
exit 1
fi
# Restore system files
restore_system_files() {
echo "Restoring system files..."
tar -xzf config/cloudpanel_config.tar.gz -C /
# Restore SSL certificates
cp -r ssl/* "${CP_HOME}/services/nginx/ssl-certificates/"
# Restore database
sqlite3 "${CP_HOME}/htdocs/app/data/db.sq3" ".restore 'database/cloudpanel.sq3'"
}
# Restore site data
restore_site() {
local site_dir="$1"
echo "Restoring site from: $site_dir"
# Restore site files
tar -xzf "${site_dir}/files/site_files.tar.gz" -C /
# Restore database if exists
for db_backup in "${site_dir}"/database/*.sql.gz; do
if [ -f "$db_backup" ]; then
local db_name=$(basename "$db_backup" .sql.gz)
gunzip -c "$db_backup" | mysql "$db_name"
fi
done
# Restore configuration
cp "${site_dir}"/config/* "${CP_HOME}/services/nginx/sites-enabled/"
}
# Main recovery process
main() {
echo "Starting CloudPanel recovery process..."
# Restore system components
restore_system_files
# Restore individual sites
for site_backup in sites/*/${TIMESTAMP}; do
if [ -d "$site_backup" ]; then
restore_site "$site_backup"
fi
done
# Restart services
systemctl restart nginx php-fpm mysql
echo "Recovery process completed"
}
main "$@"
EOF
chmod +x "$recovery_script"
}
# Main execution
main() {
echo "Starting CloudPanel backup process..."
# Backup system files
backup_system_files
verify_backup "${BACKUP_ROOT}/system/${TIMESTAMP}" "system"
# Backup individual sites
while IFS='|' read -r site_id domain user root_dir db_name; do
backup_site "$domain" "$user" "$root_dir" "$db_name"
verify_backup "${BACKUP_ROOT}/sites/${domain}/${TIMESTAMP}" "site"
done < <(get_site_configurations)
# Create recovery script
create_recovery_script "${BACKUP_ROOT}/system/${TIMESTAMP}"
# Rotate old backups
rotate_backups "$BACKUP_ROOT"
echo "Backup process completed successfully"
}
main "$@"

This backup system provides:

  1. Comprehensive backup of CloudPanel system files
  2. Site-specific backups including files, databases, and configurations
  3. Backup verification and integrity checking
  4. Automated backup rotation
  5. Recovery script generation
  6. Integration with CloudPanel’s database structure

To implement this backup system:

Terminal window
# Make the script executable
chmod +x /usr/local/bin/cloudpanel-backup-manager.sh
# Add to crontab for daily execution
(crontab -l 2>/dev/null; echo "0 2 * * * /usr/local/bin/cloudpanel-backup-manager.sh") | crontab -