WordPress Website Backup with Bash Script
Automatically WordPress Website Backup (with Bash Script or WordPress Plugin) is one of the most important things to have on the server where the website is located. In case that some unwanted changes occur on the site or the site is hacked, the easiest way to fix it and return the site to an running state is to restore the backup.
There are many plugins that do this job, but I decided to create a script that will do this job directly on the server. The script creates a backup of the database and the directory where the WordPress site is located.
To optimize server storage, I decided to compress the WordPress folder. However, this caused errors when the web server was running. To prevent such issues, I implemented a process where the folder’s contents are first copied to a temporary location. The temporary copy is then compressed and moved to the designated backup location, ensuring a seamless and error-free operation.
Exploring My Self-Hosted WordPress Website Setup
My website is self-hosted, running on an Ubuntu 22.04 Server. This setup allows me complete control over the environment and configuration. The setup includes Apache as the web server and the WordPress platform runns the site itself.
All website data, including WordPress files, are located in /srv/www/wordpress
, providing a centralized structure for easy management.
For security, a proxy server directs just traffic through HTTPS, enhancing performance and protecting sensitive data. Backups are automated through a custom Bash script that ensures both the WordPress folder and database are secured regularly in multiple locations.
This self-hosted setup approach allows me to maintain not only the website but also the server infrastructure, providing a deeper understanding of Linux, web hosting, and networking.
It is essential to maintain backups of both the WordPress folder and its database in multiple locations to ensure data safety and recovery in case of unexpected issues.
Implementation of the Backup Bash Script
Bellow are the steps to implement backup scirpt.

Step 1: Create a Script
sudo nano /opt/scripts/wordpress_backup_online.sh
#!/bin/bash
# Variables
WEB_DIR="/srv/www"
TEMP_DIR="/opt/scripts/temp"
BACKUP_DIR="/opt/scripts/backup"
LOG_DIR="/opt/scripts/log"
DATE=$(date +%F)
LOG_FILE="$LOG_DIR/wordpress_backup_$DATE.log"
DB_NAME="wordpress"
# Create necessary directories
mkdir -p "$TEMP_DIR" "$BACKUP_DIR" "$LOG_DIR"
# Start logging
echo "Script executed on $(date)" >> $LOG_FILE
# Copy WordPress files to a temporary directory
if cp -r $WEB_DIR/* $TEMP_DIR/ 2>> $LOG_FILE; then
echo "$(date): Files copied to temporary directory." >> $LOG_FILE
else
echo "$(date): ERROR: Failed to copy files!" >> $LOG_FILE
exit 1
fi
# Compress the temporary directory
if tar -czf $BACKUP_DIR/wordpress-data-backup-$DATE.tar.gz -C $TEMP_DIR . 2>> $LOG_FILE; then
echo "$(date): Files compressed successfully." >> $LOG_FILE
else
echo "$(date): ERROR: Compression failed!" >> $LOG_FILE
rm -rf $TEMP_DIR
exit 1
fi
# Clean up the temporary directory
rm -rf $TEMP_DIR
# Backup WordPress database
if mysqldump $DB_NAME > $BACKUP_DIR/wordpress-db-backup-$DATE.sql 2>> $LOG_FILE; then
echo "$(date): Database backup successful." >> $LOG_FILE
else
echo "$(date): ERROR: Database backup failed!" >> $LOG_FILE
exit 1
fi
# Retention policy - keep only the last 3 backups
echo "$(date): Number of files in directory:" >> $LOG_FILE
find "$BACKUP_DIR" -name 'wordpress-backup-*' >> $LOG_FILE
find "$BACKUP_DIR" -name 'wordpress-db-backup-*' | sort -r | tail -n +4 | cut -d' ' -f2- | xargs rm -r
find "$BACKUP_DIR" -name 'wordpress-data-backup-*' | sort -r | tail -n +4 | cut -d' ' -f2- | xargs rm -r
echo "$(date): Retention policy applied. Keeping the last 3 backups." >> $LOG_FILE
# Log success
echo "$(date): Backup completed successfully." >> $LOG_FILE
Analysis of the Script
Variables Initialization
- Paths:
WEB_DIR
: Specifies the WordPress root directory.TEMP_DIR, BACKUP_DIR, LOG_DIR
: Temporary storage, backup location, and log file directory, respectively.DATE
: Generates a unique date string for timestamping logs and backups.LOG_FILE
: Ensures every run logs messages into a file specific to the day’s backup.
- Database Name:
DB_NAME
identifies the WordPress database for backup.
Directory Creation
mkdir -p "$TEMP_DIR" "$BACKUP_DIR" "$LOG_DIR"
- Ensures necessary directories exist before executing critical operations.
- Avoids script failures due to missing directories.
Logging
echo "Script executed on $(date)" >> $LOG_FILE
- Start Logging:
- Records when the script started for debugging and auditing.
- Error Logging:
- Redirection of error output (
2>> $LOG_FILE
) logs command failures for troubleshooting. - Logs success and failure conditions for all operations.
- Redirection of error output (
File Backup to Temporary Directory
cp -r $WEB_DIR/* $TEMP_DIR/
- Copies WordPress files to
TEMP_DIR:
- Validates success/failure and exits with
exit 1
if the operation fails. - Avoids proceeding with the script in the event of an error, which helps maintain backup integrity.
- Validates success/failure and exits with
Compression of Backup
tar -czf $BACKUP_DIR/wordpress-data-backup-$DATE.tar.gz -C $TEMP_DIR .
- Compresses the temporary directory to save storage space:
- Logs the result and performs cleanup if an error occurs.
Database Backup
mysqldump $DB_NAME > $BACKUP_DIR/wordpress-db-backup-$DATE.sql
- Uses
mysqldump
to export the WordPress database:- Success or failure is logged, and the script exits on failure to prevent incomplete backups.
Backup Retention Policy
find "$BACKUP_DIR" -name 'wordpress-backup-*' | sort -r | tail -n +4 | xargs rm -r
- Keeps the last 3 backups by:
- Listing all backup files using
find
. - Sorting them in reverse chronological order.
- Retaining the top 3 files and deleting the rest using
tail
andxargs rm
.
- Listing all backup files using
Step 2: Make a Backup Script Executable
To make a script executable the following line:
chmod +x /opt/scripts/wordpress_backup_online.sh
Step 3: Store WordPress Database Credentials
I decide to store Database Credetials in the script location:
cd /opt/scripts/
sudo nano .my.cnf
[client]
user = db_user
password = db_password
Step 4: Automate Backups with Cron
Open the crontab
editor using:
sudo crontab -e
Add the following line in the crontab:
# Daily backup of DB and WordPress Website Folder
30 23 * * * bash /opt/scripts/wordpress_backup_online.sh >/dev/null 2>&1