Backups for your linux server



In this guide I describe how to setup backups for your Linux server. We will backup both locally and remotely for extra security. We will backup...

Setting up the folder structure

We start out with creating a folder structure like this:

mkdir /backup
chmod 755 /backup
mkdir /backup/local
mkdir /backup/local/mysql
mkdir /backup/local/files

The new root-level folder /backup is the storage location we will use for any kind of backups. The folder local inside it is where we will save the backup-files for that computer itself. Later on we will add sibling folders that contain backups from other computers.

Note that the folder /backup not necessarily need to be a folder on your main storage device. It could for example be a mount point or a symlink to a folder on another storage device.

Backup MySQL-databases

For MySQL-databases we will use the tool automysqlbackup. This tool is in the Ubuntu repositories. The versions are Ubuntu 12.04 with automysqlbackup 2.5 right now when I write this.

apt-get install automysqlbackup

We need to make two changes in the config file /etc/default/automysqlbackup:

DBNAMES=`mysql --defaults-file=/etc/mysql/debian.cnf --execute="SHOW DATABASES" | awk '{print $1}' | grep -Ev '^phpmyadmin|test|information_schema|performance_schema|mysql|Database$' | tr \\\r\\\n ,\ `

...

BACKUPDIR="/backup/local/mysql"

The grep part in DBNAMES is to exclude databases. You may want to add additional databases there that you don't want to backup. You should now run it once to make sure it works:

automysqlbackup

Look through the contents in /backup/local/mysql to verify it looks the way you want it to.

Question: When will these backups run?
Answer: When installing automysqlbackup the file /etc/cron.daily/automysqlbackup was created. Check the content of /etc/crontab to see when daily cron runs. In my case it looks like this:

# m h dom mon dow user    command
17 *    * * *    root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *    root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

So it seems daily cron-tasks run at 06:25 on my system (Ubuntu 12.04).

Backup normal files

For backing up normal files we are going to use a tool called rdiff-backup that creates incremental backups.

apt-get install rdiff-backup

Question: How often should I backup?
Answer: I personally enjoy backing up once a day.

Question: How long should I save the backups?
Answer: I personally enjoy saving the backups for three months.

Question: What files should I backup?
Answer: A good start is /home, /etc and /root. You will however often need to setup some special exclude and include rules.

With this in mind I should create the file /etc/cron.daily/backupfiles with the following content:

#!/bin/bash

rdiff-backup \
--include /home \
--include /etc \
--include /root \
--exclude / \
/ /backup/local/files

rdiff-backup --force --remove-older-than 3M /backup/local/files

Ensure that file has the right permissions:

sudo chmod 755 /etc/cron.daily/backupfiles

Say however that I would like to ignore all home-files for the user "derp" and only want the folders "a" and "b" from the user "herp".

The file would then look like this instead:

#!/bin/bash

rdiff-backup \
--include /home/herp/b \
--include /home/herp/a \
--exclude /home/herp \
--exclude /home/derp \
--include /home \
--include /etc \
--include /root \
--exclude / \
/ /backup/local/files

rdiff-backup --force --remove-older-than 3M /backup/local/files

It is important to consider that:

"Multiple include and exclude options take precedence in the order they are given."
http://www.nongnu.org/rdiff-backup/examples.html#exclude

I prefer looking at the include/exclude order like this:

The deeper the directory paths - the higher up in that cron-file they should be written. We can visualize the end result by imagining we apply the includes/excludes from bottom up.

Backup normal files using crontab

I actually prefer having more fine grained control over when backups are run. For this we will use crontab. Start out with creating a folder for your cron-scripts:

mkdir /root/cron

And then create the file /root/cron/backupfiles.sh instead of the file /etc/cron.daily/backupfiles. Next we add a crontab entry as root:

crontab -e

If we want it to run the same time as automysqlbackup (06:25) the crontab entry would look like this:

#m      h       dom     mon     dow     command
25      6       *       *       *       /root/cron/backupfiles.sh

Backup special large folders per weekday

To be more precise I run a few Minecraft servers. The map files are huge and change often because they are compressed natively. If we took incremental backups (rdiff-backup) those increments would be very large due to the compression. I prefer creating this setup instead:

mkdir /backup/local/server
mkdir /backup/local/server/1
mkdir /backup/local/server/2
mkdir /backup/local/server/3
mkdir /backup/local/server/4
mkdir /backup/local/server/5
mkdir /backup/local/server/6
mkdir /backup/local/server/7

Monday is "1" and Sunday is "7". Next we create the script /root/cron/backupserver.sh.

#!/bin/bash
rsync -avz --delete /home/mc/files/server/ /backup/local/server/$(date '+%u')

Note that after the first week the old backups will start getting overwritten. Lets add it to the root crontab as well:

#m      h       dom     mon     dow     command
25      6       *       *       *       /root/cron/backupfiles.sh
35      6       *       *       *       /root/cron/backupserver.sh

Backup to a remote server

For extra security it makes sense to backup to a remote computer as well. Lets call the local computer torkel and the remote computer berit. Let's also assume entries for those are added to the file /etc/hosts so they resolve into actual ip-addresses.

For this we could simply rsync the folder torkel:/backup/local to berit:/backup/torkel but in our case the folder torkel:/backup/local/server will be huge. We thus only synchronize torkel:/backup/local/1 (the monday server backup).

Create a user for torkel@berit and create the backup folder:

ssh root@berit
adduser torkel
# * give it a password for now *
mkdir /backup/torkel
chown torkel.torkel /backup/torkel

Create a private key for root@torkel and transfer it to torkel@berit:

ssh root@berit
ssh-keygen
ssh-copy-id torkel@berit

Remove the password from torkel@berit:

ssh root@berit
passwd -d torkel

Create the script /root/cron/backupremote.sh.

#!/bin/bash
rsync -avz --delete \
--include server/1 \
--exclude server/* \
/backup/local/ torkel@berit:/backup/torkel

Note that the include/exclude syntaxes are different for rsync and rdiff-backup. Lets add it to the root crontab as well:

#m      h       dom     mon     dow     command
25      6       *       *       *       /root/cron/backupfiles.sh
35      6       *       *       *       /root/cron/backupserver.sh
0      7       *       *       *       /root/cron/backupremote.sh

Restoring MySQL-databases

TODO

Restoring normal files

TODO

Restoring special large folders

TODO