Hey there! If you’ve ever managed two CyberPanel servers running OpenLiteSpeed, you know how challenging it can be to keep them in sync manually. I was in the same boat until I decided to automate the process using a Bash script. In this guide, I’ll walk you through how I automated the synchronization between my servers using SSH, MySQL, rsync, and Pushover notifications. Let’s dive right in!
Table of Contents
- Why Automate CyberPanel Server Synchronization?
- Essential Tools for Automation
- Step-by-Step Guide to Automate Server Sync
- Full Script for Easy Setup
- Conclusion
Why Automate CyberPanel Server Sync?
Managing multiple servers manually isn’t just time-consuming; it’s also prone to errors. By automating the sync process, you can:
- Save time by eliminating repetitive tasks.
- Reduce errors caused by manual operations.
- Ensure consistency across all your servers.
- Focus on more important aspects of server management.
Essential Tools for CyberPanel Automation
Before we get started, make sure you have:
- SSH access to both servers.
- MySQL credentials for database operations.
- A Pushover account for notifications.
- Basic knowledge of Bash scripting.
Step-by-Step Guide to Automate CyberPanel Server Sync
Step 1: Define Essential Variables
First, we’ll define all the essential variables in our script. This includes SSH details, Pushover tokens, MySQL credentials, and the log file location.
# Define variables
REMOTE_USER=root
REMOTE_SERVER=<your-server-ip>
SSH_PORT=<your-ssh-port>
PUSHOVER_USER=<your-pushover-user-key>
PUSHOVER_TOKEN=<your-pushover-token>
LOG_FILE="/var/log/sync.log"
DB_USER="<your-db-user>"
DB_PASSWORD="<your-db-password>"
MYSQL_ROOT_PASSWORD="<your-mysql-root-password>"
DUMP_FILE="/tmp/alldbs.sql"
<your-server-ip>
with your actual server details.Step 2: Set Up Pushover Notifications
I use Pushover to get real-time notifications on my phone whenever the script runs into an issue.
# Function to send notification using Pushover
send_notification() {
local message=$1
curl -s \
--form-string "token=$PUSHOVER_TOKEN" \
--form-string "user=$PUSHOVER_USER" \
--form-string "message=$message" \
https://api.pushover.net/1/messages.json
}
Why Use Pushover?
Pushover provides instant notifications, so you can quickly address any issues that arise during synchronization.
Step 3: Write Logs to a File
Logging is essential to track what happens during script execution, especially when it’s running as a cron job.
# Function to write to log
log() {
local message=$1
echo "$(date +'%Y-%m-%d %H:%M:%S') - $message" >> $LOG_FILE
}
Step 4: Check SSH Connection
Before initiating the sync process, the script checks the SSH connection to the remote server.
# Check SSH connection
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "exit" || {
send_notification "SSH connection failed"
log "SSH connection failed"
exit 1
}
# Send notification that syncing has started
send_notification "Syncing started."
log "Syncing started."
Step 5: Transfer User and Group Information
This ensures that user IDs and group IDs are consistent across both servers.
# Dump user and group information on the source server
getent passwd > /tmp/passwd_dump
getent group > /tmp/group_dump
# Transfer user and group information to the destination server
scp -P $SSH_PORT /tmp/passwd_dump /tmp/group_dump $REMOTE_USER@$REMOTE_SERVER:/tmp/ || {
send_notification "Transfer of user/group information failed"
log "Transfer of user/group information failed"
exit 1
}
Synchronizing CyberPanel Databases and Directories
Step 6: Sync Users, Groups, MySQL User, and Install WP-CLI
On the remote server, the script creates any missing users and groups, sets up MySQL user permissions, and installs WP-CLI if it’s not already installed.
# Create missing users and groups on the destination server, check and setup MySQL user, and check and install wp-cli
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "
while IFS=: read -r username x uid gid x x x; do
id -u \$username &>/dev/null || (groupadd -g \$gid \$username; useradd -u \$uid -g \$gid \$username)
done < /tmp/passwd_dump
while IFS=: read -r groupname x gid x; do
getent group \$groupname &>/dev/null || groupadd -g \$gid \$groupname
done < /tmp/group_dump
rm /tmp/passwd_dump /tmp/group_dump
# Check and setup MySQL user
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"SELECT 1 FROM mysql.user WHERE user = '$DB_USER'\" | grep -q 1 || {
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"
CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$DB_USER'@'localhost';
FLUSH PRIVILEGES;
\"
}
# Check and install wp-cli
command -v wp &>/dev/null || {
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
}
" || {
send_notification "User/group creation or MySQL user setup or wp-cli installation failed"
log "User/group creation or MySQL user setup or wp-cli installation failed"
exit 1
}
Step 7: Database Backup and Transfer
Back up all databases on the source server and import them on the remote server.
# Dump all local databases
mysqldump -u$DB_USER -p$DB_PASSWORD --all-databases > $DUMP_FILE || {
send_notification "MySQL dump failed"
log "MySQL dump failed"
exit 1
}
# Transfer the dump file to the remote server
scp -P $SSH_PORT $DUMP_FILE $REMOTE_USER@$REMOTE_SERVER:$DUMP_FILE || {
send_notification "Transfer of dump file failed"
log "Transfer of dump file failed"
exit 1
}
# Import the dump file on the remote server
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "mysql -u$DB_USER -p$DB_PASSWORD < $DUMP_FILE" || {
send_notification "MySQL import failed"
log "MySQL import failed"
exit 1
}
Step 8: Directory Synchronization Using rsync
Use rsync to mirror specific directories from the source to the destination server.
# Sync specified directories using rsync
for dir in /usr/local/lsws/ /home/ /etc/cyberpanel/ /etc/letsencrypt/ /etc/pure-ftpd/ /etc/firewalld/ /usr/local/lscp/ /usr/local/CyberCP/ /usr/local/CyberPanel/; do
rsync -avP --delete -e "ssh -p $SSH_PORT" $dir $REMOTE_USER@$REMOTE_SERVER:$dir || {
send_notification "Rsync failed for directory $dir"
log "Rsync failed for directory $dir"
exit 1
}
done
Finalizing the CyberPanel Sync Process
Step 9: Flush LiteSpeed Cache on the Remote Server
Clear the LiteSpeed cache for each WordPress installation on the destination server.
# Flush LiteSpeed Cache on the remote server for all WordPress installations
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "
find /home/ -type f -name wp-config.php | while read wp_config; do
wp_path=\$(dirname \"\$wp_config\")
wp --allow-root --path=\"\$wp_path\" litespeed-purge all || {
echo \"Error: Unable to purge LiteSpeed Cache for \$wp_path\"
}
done
" || {
send_notification "LiteSpeed Cache flush failed"
log "LiteSpeed Cache flush failed"
exit 1
}
Step 10: Clean Up and Reboot
Finally, remove the database dump from both servers and reboot the remote server.
# Remove the dump file from both local and remote servers
rm $DUMP_FILE
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "rm $DUMP_FILE"
# Reboot the remote server
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "reboot" || true
# Send notification that syncing has completed successfully
send_notification "Synchronization completed successfully. Remote server is rebooting."
log "Synchronization completed successfully. Remote server is rebooting."
Full Script for Easy Setup
Here's the complete script for you to set up your automated synchronization. Remember to replace all placeholders with your actual server details.
#!/bin/bash
# Define variables
REMOTE_USER=root
REMOTE_SERVER=<your-server-ip>
SSH_PORT=<your-ssh-port>
PUSHOVER_USER=<your-pushover-user-key>
PUSHOVER_TOKEN=<your-pushover-token>
LOG_FILE="/var/log/sync.log"
DB_USER="<your-db-user>"
DB_PASSWORD="<your-db-password>"
MYSQL_ROOT_PASSWORD="<your-mysql-root-password>"
DUMP_FILE="/tmp/alldbs.sql"
# Function to send notification using Pushover
send_notification() {
local message=$1
curl -s \
--form-string "token=$PUSHOVER_TOKEN" \
--form-string "user=$PUSHOVER_USER" \
--form-string "message=$message" \
https://api.pushover.net/1/messages.json
}
# Function to write to log
log() {
local message=$1
echo "$(date +'%Y-%m-%d %H:%M:%S') - $message" >> $LOG_FILE
}
# Check SSH connection
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "exit" || {
send_notification "SSH connection failed"
log "SSH connection failed"
exit 1
}
# Send notification that syncing has started
send_notification "Syncing started."
log "Syncing started."
# Dump user and group information on the source server
getent passwd > /tmp/passwd_dump
getent group > /tmp/group_dump
# Transfer user and group information to the destination server
scp -P $SSH_PORT /tmp/passwd_dump /tmp/group_dump $REMOTE_USER@$REMOTE_SERVER:/tmp/ || {
send_notification "Transfer of user/group information failed"
log "Transfer of user/group information failed"
exit 1
}
# Create missing users and groups on the destination server, check and setup MySQL user, and check and install wp-cli
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "
while IFS=: read -r username x uid gid x x x; do
id -u \$username &>/dev/null || (groupadd -g \$gid \$username; useradd -u \$uid -g \$gid \$username)
done < /tmp/passwd_dump
while IFS=: read -r groupname x gid x; do
getent group \$groupname &>/dev/null || groupadd -g \$gid \$groupname
done < /tmp/group_dump
rm /tmp/passwd_dump /tmp/group_dump
# Check and setup MySQL user
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"SELECT 1 FROM mysql.user WHERE user = '$DB_USER'\" | grep -q 1 || {
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e \"
CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$DB_USER'@'localhost';
FLUSH PRIVILEGES;
\"
}
# Check and install wp-cli
command -v wp &>/dev/null || {
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
}
" || {
send_notification "User/group creation or MySQL user setup or wp-cli installation failed"
log "User/group creation or MySQL user setup or wp-cli installation failed"
exit 1
}
# Dump all local databases
mysqldump -u$DB_USER -p$DB_PASSWORD --all-databases > $DUMP_FILE || {
send_notification "MySQL dump failed"
log "MySQL dump failed"
exit 1
}
# Transfer the dump file to the remote server
scp -P $SSH_PORT $DUMP_FILE $REMOTE_USER@$REMOTE_SERVER:$DUMP_FILE || {
send_notification "Transfer of dump file failed"
log "Transfer of dump file failed"
exit 1
}
# Import the dump file on the remote server
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "mysql -u$DB_USER -p$DB_PASSWORD < $DUMP_FILE" || {
send_notification "MySQL import failed"
log "MySQL import failed"
exit 1
}
# Sync specified directories using rsync
for dir in /usr/local/lsws/ /home/ /etc/cyberpanel/ /etc/letsencrypt/ /etc/pure-ftpd/ /etc/firewalld/ /usr/local/lscp/ /usr/local/CyberCP/ /usr/local/CyberPanel/; do
rsync -avP --delete -e "ssh -p $SSH_PORT" $dir $REMOTE_USER@$REMOTE_SERVER:$dir || {
send_notification "Rsync failed for directory $dir"
log "Rsync failed for directory $dir"
exit 1
}
done
# Flush LiteSpeed Cache on the remote server for all WordPress installations
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "
find /home/ -type f -name wp-config.php | while read wp_config; do
wp_path=\$(dirname \"\$wp_config\")
wp --allow-root --path=\"\$wp_path\" litespeed-purge all || {
echo \"Error: Unable to purge LiteSpeed Cache for \$wp_path\"
}
done
" || {
send_notification "LiteSpeed Cache flush failed"
log "LiteSpeed Cache flush failed"
exit 1
}
# Remove the dump file from both local and remote servers
rm $DUMP_FILE
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "rm $DUMP_FILE"
# Reboot the remote server
ssh -p $SSH_PORT $REMOTE_USER@$REMOTE_SERVER "reboot" || true
# Send notification that syncing has completed successfully
send_notification "Synchronization completed successfully. Remote server is rebooting."
log "Synchronization completed successfully. Remote server is rebooting."
Conclusion
Automating the synchronization between two CyberPanel servers with OpenLiteSpeed has been a game-changer for me. Not only does it save time, but it also ensures that both servers are always up-to-date without manual intervention. I hope this guide helps you streamline your server management. Happy syncing!