Drupal Backup Scripts

Backup a Drupal Server with Cron and SSH/SCP

When running a Drupal web server with multiple sites you will want to be taking backups at regular intervals. Here's how I did it using my Debian Linux desktop. The neat thing about this solution is that you don't need to install anything on the web server for it to work - so long as you have SSH shell access to the box.

Setting up Password-less Login

Ultimately we want to schedule this backup to run as a Cron job, probably in the middle of the night. This means that we can't have SSH asking us for a password to log in to the web server.

To set up password-less logins we first need to generate a public/private key pair on the desktop machine.

  1. Open a terminal window.
  2. Type "ssh-keygen" (without the quotes) and hit [Enter].
  3. Accept the default values when prompted, but make a note of the file names that are output.

You should now see something like this in the .ssh folder within your home folder:

id_rsa
id_rsa.pub

The file "id_rsa" is very important, and you should check that ssh-keygen has made the file viewable only by yourself. "id_rsa.pub" is the public part of your new key, and this is what we want to copy up to the web server.

In your terminal window on the desktop, type the following:

cd ~/.ssh
scp id_rsa.pub drupal@your_web_server.com:/home/drupal/.ssh/new_key.pub

  • Substitute "drupal" with the user name on your web server that runs your website(s).
  • Check that the destination folder is correct for the user that you are logging with.

Now that we've copied the public key to the web server, we need to login to the web server and add this key to the list of recognised keys.

ssh drupal@your_web_server.com
cd .ssh
cat new_key.pub >> authorized_keys
exit

Your keys should now be ready to use. Test this by logging in to the web server via SSH again, and you should no longer be prompted for a password. If you are asked for a password then delete authorized_keys from the ".ssh" folder on the web server and repeat the above steps.

Backup the Drupal Database(s)

We will use two scripts to back up the Drupal website(s) - the first will backup the databases.

Open a terminal on your desktop and create a folder to store your scripts.

mkdir ~/scripts
cd ~/scripts
gedit backup-drupal-databases.sh

Now paste the following into gedit.

#!/bin/bash
#
# Search for settings.php files for all Druapl websites.
#
CONFIG_FILES=`find ~/htdocs/sites -name settings.php`
TIMESTAMP=`date +%Y%m%d-%H%M`
BACKUPS_FOLDER_REL=databases-${TIMESTAMP}
BACKUPS_FOLDER=~/${BACKUPS_FOLDER_REL}
INDEX=0
#
# You may need to change this for your web server's version of mysqldump.
#
MYSQLDUMP_BIN=/opt/mysql-5.0/bin/mysqldump
#
# Make the backup folder if it doesn't already exist.
#
if [ -d ${BACKUPS_FOLDER} ]; then
rm -f ${BACKUPS_FOLDER}/*
else
mkdir ${BACKUPS_FOLDER}
fi
#
# Loop through each settings.php file and extract the MySQL login details.
#
if [ -d ${BACKUPS_FOLDER} ]; then
for CONFIG_FILE in $CONFIG_FILES ;
do
MYSQL_URL=`grep '^\$db_url' ${CONFIG_FILE}`
MYSQL_URL=${MYSQL_URL//\$db_url = \'/}
MYSQL_URL=${MYSQL_URL//\'\;/}
MYSQL_URL=${MYSQL_URL//mysql\:\/\//}
MYSQL_USER=`echo ${MYSQL_URL} | cut -d: -f1`
MYSQL_PASS=`echo ${MYSQL_URL} | cut -d: -f2`
MYSQL_PASS=`echo ${MYSQL_PASS} | cut -d@ -f1`
MYSQL_HOST=`echo ${MYSQL_URL} | cut -d@ -f2`
MYSQL_HOST=`echo ${MYSQL_HOST} | cut -d/ -f1`
MYSQL_DATABASE=`echo ${MYSQL_URL} | cut -d/ -f2`
MYSQL_DATABASE=`echo ${MYSQL_DATABASE} | cut -d/ -f1`
GZIP_FILE_NAME=${BACKUPS_FOLDER}/${MYSQL_DATABASE}-${TIMESTAMP}.sql.gz
#
# Dump the database to a file in our backup folder.
#
echo Archiving ${GZIP_FILE_NAME} 1>&2
${MYSQLDUMP_BIN} \
-u${MYSQL_USER} \
-h${MYSQL_HOST} \
-p${MYSQL_PASS} \
${MYSQL_DATABASE} | gzip > ${GZIP_FILE_NAME}
let "INDEX++"
done
#
# Output the resulting backup files to the terminal,
# back to the desktop client.
#
echo Downloading at `date "+%H:%M:%S %d/%m/%Y"` 1>&2
tar -cf - ${BACKUPS_FOLDER_REL}
echo Finished at `date "+%H:%M:%S %d/%m/%Y"` 1>&2
#
# Clean up afterwards.
#
rm -fR ${BACKUPS_FOLDER}
fi

Don't forget to make your script executable:

chmod +x ~/scripts/backup-drupal-databases.sh

You can test this script from your terminal by typing the following:

cat ~/scripts/backup-drupal-databases.sh \
| ssh -T drupal@your_web_server.com > /usr/local/share/backups/drupal-databases.tar
tar -tf /usr/local/share/backups/drupal-databases.tar

Backup the Drupal 'htdocs' folder

The folder backup script uses the same process but is much simpler. In a terminal window on your desktop, type the following:

gedit ~/scripts/backup-drupal-htdocs.sh

Here is the script for backing up the contents of htdocs on the web server:

#!/bin/bash
tar -czf - htdocs

This creates a zipped TAR of your server's htdocs folder and returns it to the terminal. Don't forget to make your script executable:

chmod +x ~/scripts/backup-drupal-htdocs.sh

Bringing it all Together

These two scripts can be a bit of a faff to run manually, so we will use a wrapper script that takes two arguments. Create a new script called backup-drupal.sh and paste the following into it:

#!/bin/bash
#
# The folder on your desktop machine that we will store our backups in.
# You will need to create this folder, or enter something more
# appropriate for your system.
#
BACKUP_DIR_DRUPAL=/usr/local/share/backups/
#
# What do we want to backup?
#
DO_DATABASES=n
DO_HTDOCS=n
TIMESTAMP=`date +%Y%m%d`
#
# Pass the --databases parameter to backup your databases.
#
if [ "${1}" = "--databases" ] || [ "${2}" = "--databases" ]; then
DO_DATABASES=y
fi
#
# Pass the --htdocs parameter to backup your files.
#
if [ "${1}" = "--htdocs" ] || [ "${2}" = "--htdocs" ]; then
DO_HTDOCS=y
fi
#
# If your backups folder is on an external disk then you may need to
# spin the disk up first.
#
touch ${BACKUP_DIR_DRUPAL}
sleep 10s
#
# Backup the databases.
#
if [ "${DO_DATABASES}" = "y" ]; then
cat ~/scripts/backup-drupal-databases.sh | \
ssh -T drupal@your_web_server.com > ${BACKUP_DIR_DRUPAL}databases-${TIMESTAMP}.tar
fi
#
# Backup the files.
#
if [ "${DO_HTDOCS}" = "y" ]; then
cat ~/scripts/backup-drupal-htdocs.sh | ssh -T drupal@your_web_server.com > \
${BACKUP_DIR_DRUPAL}htdocs-${TIMESTAMP}.tgz
fi

Don't forget to make your script executable:

chmod +x ~/scripts/backup-drupal.sh

Now try out your new backup script by entering the following at your terminal:

~/scripts/backup-drupal.sh --databases
~/scripts/backup-drupal.sh --htdocs

If all has gone well then you should now have two files in your /usr/local/share/backups/ folder.

Scheduling the Backup

If you are happy with your scripts and backup folder settings then it's time to create the cron job so that the script runs automatically during the night. If you are unfamiliar with Cron then you should first check out some online guides.

crontab -e

Here is my crontab for reference:

# m h dom mon dow command
0 4 * * * $HOME/scripts/backup-drupal.sh --databases
30 4 * * 1 $HOME/scripts/backup-drupal.sh --htdocs

This states that my databases are backed up daily at 4:00am every day of the week, and the files are backed up weekly, every Monday morning at 4:30am.

There you have it - automated Drupal backups without installing anything on your web server.