Everyone needs to have a backup plan for their live site. Not only can your server's disk get corrupted, but you can also erroneously overwrite your site with bad code or bad data, or your site can get hacked. Detecting the latter situations takes some time. Hours or days.

For this reason, you should have multiple backup copies at multiple time points.

The most convenient scheme is to have a 7 day sliding backup: that is, you have one backup snapshot for each day of the week, with today's backup overwriting the backup from 8 days ago.

The scheme we describe in this post uses the extremely flexible, popular and useful Drush the command line swiss army knife for Drupal.

It has the following advantage:

  • No need to know what user, password and host MySQL is running on.
  • Single self contained all-in-one backup file for database, Drupal and static files.
  • 7 Day sliding backups.

Note: The use of Drush for backup, or any other scheme that uses mysqldump, are suitable for sites that do not have a large database. If your site's database is large, then you may want to explore other backup schemes, such as using MyDumper for Fast Parallel MySQL backups.

Install Drush

You can install Drush using Composer, as discribed on Drush's github. Or you can install it via PHP PEAR.

Installing from PEAR is as follows:
First, install the PHP PEAR package from Ubuntu's repositories.

aptitude install php-pear

Then install dependencies:

pear upgrade --force pear
pear install Console_GetoptPlus
pear install Console_Table

Finally install Drush itself.

pear channel-discover pear.drush.org
pear install drush/drush

Now that you have Drush installed, we proceed for using it for backup.

Create A Backup Directory

We now create a directory to hold the backups, and change its permissions so no one could read it but someone with root access.

sudo mkdir /home/backup
sudo chmod 700 /home/backup

Create a Drush alias file

Then create an aliases file for Drush to know where your site is installed. Change example.com below to your real directory where the site is installed and its real URL.

<?php
# This file should be in ~/.drush/aliases.drushrc.php
$aliases['live'] = array(
  'uri'  => 'http://example.com',
  'root' => '/home/example.com/www',
);

Creating the drush backup script

Now create a file in /usr/local/bin/daily-backup.sh

#!/bin/sh

# Daily backup of the database, using Drush
#

# Backup directory
DIR_BACKUP=/home/backup

log_msg() {
  # Log to syslog
  logger -t `basename $0` "$*"

  # Echo to stdout
  LOG_TS=`date +'%H:%M:%S'`
  echo "$LOG_TS - $*"
}

DAY_OF_WEEK=`date '+%a'`
BACKUP_FILE=$DIR_BACKUP/backup.$DAY_OF_WEEK.tgz

log_msg "Backing up files and database to $BACKUP_FILE ..."

drush @live archive-dump \
  --destination=$BACKUP_FILE \
  --preserve-symlinks \
  --overwrite

RC=$?

if [ "$RC" = 0 ]; then
  log_msg "Backup completed successfully ..."
else
  log_msg "Backup exited with return code: $RC"
fi

Make the script executable:

chmod 755 /usr/local/bin/daily-backup.sh

Scheduling the daily backup

Now add the script to cron so as to run daily, for example at 2:30 am

30 2 * * * /usr/local/bin/daily-backup.sh

After a few days, you should see backups in the directory, kept for 7 days:

ls /home/backup/

backup.Fri.tgz
backup.Thu.tgz

It is also a good idea to copy the backup files to another server, ideally not in the same datacenter as the live site. At least do this weekly using an addition to the script using scp or rsync.

Comments

Tue, 2014/05/27 - 14:31

I've found that with a sizable database (e.g. from about 1GB), a shell script using mysqldump works better than drush (in terms of server load, where drush at some point even caused 503 service unavailable). Presumably because of the overhead from PHP.

For me a shell script + mysqldump works fine for now and doesn't require another package, though I'll keep mydumper in mind for the future.

Wed, 2014/05/28 - 04:18

I use the free Webmin (open source like Drupal. Webmin replaces sysadmins just like Drupal replaces CMSes.)

Webmin has excellent backup capabilities.

Thu, 2014/05/29 - 08:45

Yeah, Webmin is helpful.

But scripts work everywhere, and don't require more components that need updating, ...etc.

Wed, 2014/05/28 - 04:15

"you should have multiple backup copies at multiple time points"

AND multiple locations...

Wed, 2014/05/28 - 09:32

That is mentioned at the very end of the article.

Wed, 2014/05/28 - 05:36

Or you could just pop
/usr/bin/env php /var/aegir/drush/drush.php @live archive-dump --destination=/home/backup/backup.`date '+%a'` --preserve-symlinks --overwrite
straight into your crontab. :) Crontab error logging should take care of your logging needs.

Thu, 2014/05/29 - 08:57

Cron does not like back tick substitution. Your one liner will return this error:

Syntax error: EOF in backquote substitution

So it does not work as is. You can force it to work by escaping the % character by preceding it with a backslash.

But more importantly, your one liner provides no logging of the specific steps and outcome. Cron just logs that such and such command was run. Nothing about the success or failure of the command.

The script in the article does this logging, and you can go and check /var/log/syslog for what happened days or months ago. For something as crucial as backup, knowning the outcome and keeping a record of it is important.

Wed, 2014/05/28 - 19:24

Hi Khalid,

Maybe you'd benefit from taking a look at my personal script for keeping only most recent backups: http://jeh3.net/keeping-your-drupal-backups-under-control . It's quite flexible while being short and simple; logic for deleting old backups can be simplified, but I haven't had the time for that.

Thu, 2014/05/29 - 08:49

There are lots of scripts for that.

The drush way removes the need to parse settings.php for database credentials, and outputs a single file combinging the files and database in it.

It is also a standard format which can easily be imported using drush archive-restore.

Thu, 2014/05/29 - 11:06

My script does leverage drush for the backup. The reason I pointed you to it was because my script is callable from multiple cron jobs, which makes it more flexible: say you want to keep last three weekly + last six hourly backups, you can do it easily with it.

Guess you don't have the time to see it, but hopefully it'll be useful for somebody else.

Thanks for this post! as always, very useful.

Pages

Is your Drupal or Backdrop CMS site slow?
Is it suffering from server resources shortages?
Is it experiencing outages?
Contact us for Drupal or Backdrop CMS Performance Optimization and Tuning Consulting