Rsync over SSH backups (backing up UNIX machines)

Backups are important!

Many years ago, one of my wife's clients experienced a hard drive crash on her business machine -- unfortunately she had gotten tired of replacing the tapes in her drive, so her backups were completely useless. She was quite upset, so I was looking for something helpful to say -- unfortunately the only thing that came to mind was somthing I had read in some magazine that morning: "Did you know that, according to the Gartner Group, 95% of all companies that experience a data loss like your go out of business within 6 months".

The sad thing is that I thought that I was helping...

 


This is the rsync based backup system that I use to backup my servers / workstations, etc.

Notes:

backuppc is the name of the server to back things up to!
You need to setup SSH keys so that this machine can login to the backup server. I use chroot'ed jails and a key just for this, In the example it just logs in as root.
This uses rsyncs bandwith limit -- it is in KiloBytes, NOT KiloBits!
This also dumps your MYSQL databases and backs them up.

ssh keys

First I need an ssh key so that the client can login to the backup machine. In order to make this more secure, I use "forced command" keys.

 

root@vimes:~# ssh-keygen -C "SSH Single Use Key -- backup from Source to BackupDest -- generated on Source"
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/.ssh/source_to_backupdest_rsync
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/source_to_backupdest_rsync.
Your public key has been saved in /root/.ssh/source_to_backupdest_rsync.pub.

 

Now I copy the .pub file over to the backup machine and place it in /root/.ssh/authorized_keys2. The super important bit to do is to add:

command="/usr/local/sbin/secure_rsync",no-port-forwarding,no-X11-forwarding,no-agent-forwarding 

before the key to make sure that this key can only be used for backups.

Example:

command="/usr/local/sbin/secure_rsync",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-dss AAAdFAaefat4re43tr... 56lblAzAT5K9w== SSH Single Use Key (rsync) -- generated on Homer

I am planning on soon moving to SSH certificates where I can use certificate constraints to further enforce limits, but am waiting to get an HSM first, as having an unprotected CA cert lurking makes me itch..

 

The list of things to include or exclude is in /etc/backup/backup_include and /etc/backup/backup_exclude. Example files below.

backup.sh

#!/bin/bash
unset PATH
# USER VARIABLES
BACKUPDIR=/backup # Folder on the backup server
KEY=/root/.ssh/id_rsa # What key to use to login to the backup server
MYSQLUSER=root
MYSQLPWD= **** PUT PASSWORD HERE! ***
MYSQLHOST=localhost
MYSQLBACKUPDIR=/mysql_backup
BACKUP_USER=root@backuppc
EXCLUDES=/etc/backup/backup_exclude # File containing exludes
INCLUDES=/etc/backup/backup_include # What to backup.
# PATH VARIABLES
CP=/bin/cp;
MK=/bin/mkdir;
SSH=/usr/bin/ssh;
DATE=/bin/date;
RM=/bin/rm;
GREP=/bin/grep;
MYSQL=/usr/bin/mysql;
MYSQLDUMP=/usr/bin/mysqldump;
RSYNC=/usr/bin/rsync;
TOUCH=/bin/touch;
HOSTNAME=`/bin/hostname`;
CAT=/bin/cat;
##
# CREATING CURRENT DATE / TIME
NOW=`$DATE '+%Y-%m'-%d_%H:%M`
MKDIR=$BACKUPDIR/$NOW/
# CREATE MYSQL BACKUP
# Remove existing backup dir
$RM -Rf $MYSQLBACKUPDIR
# Create new backup dir
$MK $MYSQLBACKUPDIR
#Dump new files
for i in $(echo 'SHOW DATABASES;' | $MYSQL -u$MYSQLUSER -p$MYSQLPWD -h$MYSQLHOST|$GREP -v '^Database$'); do
$MYSQLDUMP \
-u$MYSQLUSER -p$MYSQLPWD -h$MYSQLHOST \
-Q -c -C --add-drop-table --add-locks --quick --lock-tables \
$i > $MYSQLBACKUPDIR/$i.sql;
done;
# CREATE NEW BACKUPDIR
$SSH -i $KEY $BACKUP_USER "$MK -p $MKDIR"
# RUN RSYNC INTO CURRENT
for TODO in `$CAT ${INCLUDES}`; do
echo "-------- Begin backup: $TODO --------";
$SSH -i $KEY $BACKUP_USER "$MK -p $BACKUPDIR/current/$HOSTNAME$TODO"
$RSYNC \
-apcz --stats --bwlimit=50 --delete --delete-excluded \
--exclude-from="$EXCLUDES" \
-e "$SSH -i $KEY" \
$TODO/ $BACKUP_USER:$BACKUPDIR/current/$HOSTNAME$TODO ;
echo "------- End backup: $TODO -------";
echo
echo
echo
done
# UPDATE THE MTIME TO REFELCT THE SNAPSHOT TIME
$SSH -I $KEY $BACKUP_USER "$TOUCH $BACKUPDIR/current"
# MAKE HARDLINK COPY
$SSH -i $KEY $BACKUP_USER "$CP -al $BACKUPDIR/current/* $MKDIR"

backup_include and backup_exclude

[root@homer ~]#  cat /etc/backup/backup_include 
/etc
/home/wkumari
/root
/mysql_backup
/var/www
/usr/local
/usr/share
[root@homer ~]# cat /etc/backup/backup_exclude
/backup/
/backups/
/bin/
/boot/
/dev/
/etc/selinux/
/lib/
/lost+found/
/mnt/
/media/
/opt/
/proc/
/selinux/
/sbin/
/sys/
/tmp/
/usr/
/var/log/
/var/spool/
/var/lib/php4/
/var/lib/mysql/

crontab invocation

[root@homer ~]# crontab -l
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=[INSET YOUR EMAIL ADDRESS]
HOME=/root
# field allowed values
# ----- --------------
# minute 0-59
# hour 0-23
# day of month 1-31
# month 1-12 (or names, see below)
# day of week 0-7 (0 or 7 is Sun, or use names)
# M H D M DOW
# Four times a day, when the minutes are 0, run the backup.
0 */6 * * * /root/backup.sh 2>&1 | mail -s "Backup report: `date`" [EMAIL ADDRESS] -- -F [EMAIL ADDRESS]

 

 

Additional information