This tutorial is originally written by: Remy Van Elst @ www.raymii.org (original post here)
This tutorial will show you how you can back up your website and database with Duplicity. Duplicity is a very useful tool to make remote unassisted backups. The backups can be incremental, encrypted, and over a variety of transports.
There are a few steps involved in the process of setting this up, and also a few preconditions:
- The tutorial works best with a VPS, were you have full root access to the filesystem and database
- The tutorial is targeted at debian/ubuntu, but with adaption of commands will work under CentOS/RHEL.
- You need an off-site location to store the backups (other vps for example)
Basic web application backup
First I’ll try to educate you a little bit with some theory.
This tutorial works for all web applications, since they almost all share the same common structure:
- source code (.php files, .js files (node), .rb files (rails) etc.)
- database (MySQL, PostgreSQL, MongoDB etc.)
- configuration (apache config, nginx config, mysql config, application config)
We are going to back up files. Two of the three things above are already files, and the database will be exported to a file. The database will be exported so that it can be imported again using native tools (mysqldump, mongodump etc.), since just copying the database folders and files will almost always result in a corrupted database.
Duplicity has a few advantages to other backup tools and scripts:
- Incremental backups (Saving size)
- A lot of storage options (ssh, rsync, ftp, amazon S3, IMAP, google drive and more.)
- Encryption built in
- Easy to set up and maintain.
I myself have the following set up for almost all of my web application backups:
- Shell script to export the databases
- Duplicity backing up the files to a “storage” VPS
- The storage vps is just a server with a lot of HDD space doing nothing else.
- Some apps back up daily, some hourly and some weekly.
Your situation
For this tutorial I’m going to backup a basic Joomla website. Joomla is a PHP/MySQL CMS. The files are located in /var/www/joomla
, and the MySQL database is named db_054
. I’m also giving the same examples for a Node.js application using mongodb. The path for that application is /home/appusr/www/
and that database is named uptime
.
You will have to know some things yourself:
- Where is the application located (
/var/www/joomla
) - What database am I using (
MySQL, MongoDB
) - How do I export that database (
mysqldump, mongodump
) - How do I restore that database (
mongorestore
)
In this example we will use mysqldump
to backup the MySQL database, and use duplicity to backup the database dumps, the /var/www/joomla
folder and the /etc/apache2
folder (which has the webserver configuration). If this site ran over SSL then I would also backup the folder where my SSL certificate was.
We are going to put it all in a cronjob, which runs every 8 hours. We will also have a full weekly backup, via another cron job.
Software
Make sure you have the required software installed:
1 2 |
sudo apt-get install duplicity gzip python python-paramiko |
MySQL
The mysqldump command to backup the database:
1 2 |
mysqldump --single-transaction --routines --events --triggers --add-drop-table --extended-insert -u db_054_u -h 127.0.0.1 -pMyDatabsePassw0rd db_054 | gzip -9 > /var/backups/sql/db_054_$(date +"%H:%M_%d-%m-%Y").sql.gz |
You will have to replace the -u db_054_u
with your database user, the -pMyDatabasePassw0rd
with your database password and db_054
with the name of your database.
The above line will result in a file named like this: db_054_15:28_16-02-2013.sql.gz
in the folder /var/backups/sql
. You will need to create that folder and make sure you have write permissions to it.
MongoDB
For Mongodb I use the mongodump
command to create a backup of that database:
1 2 |
mongodump --host 127.0.0.1:28017 --db uptime --user uptime_u --password uptime_password --out /var/backups/mongo/ |
Note that if you want to backup all mongodb databases you can omit the --db database
option.
Again replace the corresponding options with your values, and make sure the /var/backups/mongo
folder exists and is writable to you.
Duplicity
Note: I will not cover the setup of encrypted backups with Duplicity. My backups go to a trusted server (located at my home). If you need that because you are backing up to S3, use a search engine to find tutorials on how to set up that.
First we need to create a ssh key to use. We do this with the ssh-keygen
program:
1 2 3 4 5 6 7 8 9 |
~$ ssh-keygen -C 'Duplicity Backup Key' Generating public/private rsa key pair. Enter file in which to save the key (/home/remy/.ssh/id_rsa): /home/remy/.ssh/backup_rsa Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/remy/.ssh/backup_rsa. Your public key has been saved in /home/remy/.ssh/backup_rsa.pub. |
Make sure you do not enter a passphrase. If you do that, the backup process does not work unattended.
Now copy over that key to your other (trusted) server:
1 2 |
ssh-copy-id -i /home/remy/.ssh/backup_rsa.pub "-p 22 trusted-backup-server.org" |
And test if you can login without a password with that key:
1 2 |
ssh -i /home/remy/.ssh/backup_rsa -p 22 remy@trusted-backup-server.org |
If that all works continue.
We are now going to set up duplicity. I use the following command to back up all the folders:
1 2 |
duplicity incremental --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/sql" --include="/etc/apache2/" --include="/var/www/joomla" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/joomla/ |
If you need to backup more folders, add another --include="/path/to/folder"
option. The --exclude="**" /
option is a trick to backup everything which is in the include list and nothing else.
For the Node.js/Mongodb application, I would use the following command:
1 2 |
duplicity incremental --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/mongo" --include="/home/appuser/www/" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/uptime/ |
Cron
Now putting everything in a cronjob. By using the ;
character after a command, you can specify multiple commands in one cronjob which run after each other. We combine the database dump with the duplicity command to set up the back up:
1 2 |
10 01 * * 1,2,3,4,5,6 mysqldump --single-transaction --routines --events --triggers --add-drop-table --extended-insert -u db_054_u -h 127.0.0.1 -pMyDatabsePassw0rd db_054 | gzip -9 > /var/backups/sql/db_054_$(date +"%H:%M_%d-%m-%Y").sql.gz; duplicity incremental --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/sql" --include="/etc/apache2/" --include="/var/www/joomla" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/joomla/ |
This schedule will create an incremental backup every day of the week at 01:10 AM except sunday. For sunday we have a different cronjob. The only thing different is the day of the week
and the duplicity command has the incremental
parameter replaced by full
. This forces duplicity to do a full backup:
1 2 |
10 01 * * 7 mysqldump --single-transaction --routines --events --triggers --add-drop-table --extended-insert -u db_054_u -h 127.0.0.1 -pMyDatabsePassw0rd db_054 | gzip -9 > /var/backups/sql/db_054_$(date +"%H:%M_%d-%m-%Y").sql.gz; duplicity full --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/sql" --include="/etc/apache2/" --include="/var/www/joomla" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/joomla/ |
For the node.js/mongodb application we use the following cronjobs:
Incremental:
1 2 |
10 01 * * 1,2,3,4,5,6 mongodump --host 127.0.0.1:28017 --db uptime --user uptime_u --password uptime_password --out /var/backups/mongo/; duplicity incremental --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/mongo" --include="/home/appuser/www/" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/uptime/ |
Full on sunday:
1 2 |
10 01 * * 7 mongodump --host 127.0.0.1:28017 --db uptime --user uptime_u --password uptime_password --out /var/backups/mongo/; duplicity full --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --include="/var/backups/mongo" --include="/home/appuser/www/" --exclude="**" / ssh://remy@trusted-backup-server.org:22/backups/uptime/ |
Restoring
Now that we have backups, how do we restore them? Files can just be copied to the right place, databases need to be imported.
First we get the backups from the backup server:
1 2 |
duplicity --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" --file-to-restore / ssh://remy@trusted-backup-server.org:22/backups/joomla/ |
If you need a backup from an earlier date:
1 2 |
duplicity --no-encryption --ssh-options="-oProtocol=2 -oIdentityFile=/home/remy/.ssh/backup_rsa" -t 3D --file-to-restore / ssh://remy@trusted-backup-server.org:22/backups/joomla/ |
The -t 3D
option means restore a backup from three days ago. Things like -t 1M
(for one month ago) or -t 5H
(for 5 hours ago) also work.
You will now have the folders and files you backed up. Copy the files back in place using cp
. For the databases we use their respective tools.
For MySQL, first gunzip
the archive, and then import it:
1 2 |
gunzip db_054_15:28_16-02-2013.sql.gz |
And then restore it:
1 2 |
mysql -u db_054_u -pMyDatabasePassw0rd db_054 < db_054_15:28_16-02-2013.sql |
For MongoDB:
1 2 |
mongorestore mongo/ |
Make sure you try to restore your backups at least one or twice a month. This will make sure the backups are usable when you need them!
4 comments for “Basic website and database backups with Duplicity”