Off-site backups using tarsnap

I finally decided to invest in an off-site backup solution for the home machines. While everything is backed up in a mutual fashion internally, should my house be nuked, there would be no data left anywhere. I considered rsync.net and tarsnap, eventually settling for tarsnap on the basis of supporting someone (Colin Percival) who had contributed to FreeBSD.

The signup and setup process for tarsnap is well documented; there's nothing I need to add to that. However, the backup setup is worth documenting, even if it only serves to remind me what I did.

Backups to tarsnap are taken from one machine, crimson, which acts as the main backup and fallback server. It runs FreeBSD, natch.

crimson is normally dormant, so I have to wake it up from the always-on server, topaz, then start the backup cron job on crimson a few minutes later. This will be performed in the early morning to minimise impact to the ADSL bandwidth for my users (aka family).

The crontab on topaz looks like this:

  SHELL=/bin/sh
  PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
  HOME=/home/mark

  # bring up crimson to run tarsnap on Monday morning, 0002
  02 00 * * 1 /home/mark/bin/wake crimson

wake is a front-end to wol. And on crimson, the crontab looks like:

  SHELL=/bin/sh
  PATH=/sbin:/bin:/usr/sbin:/usr/bin
  HOME=/root

  # run tarsnap on Monday morning, 0007
  07 00 * * 1 sh /root/bin/tarsnap.sh -s

The tarsnap.sh script is as follows:

  #!/bin/sh
  #
  # NAME
  #   tarsnap.sh - Backups to tarsnap (for crimson only)
  #
  # SYNOPSIS
  #   sh tarsnap.sh [-a args] [-s]
  #
  #   Switches:
  #      -a  args  provides additional arguments to tarsnap for this run 
  #      -s        shutdown machine at script completion
  #
  # DESCRIPTION 
  #   This script is designed to be run by cron.  It automates the
  #   backup of key directories on the crimson server.  Backup
  #   directories to process are defined in the archives variable, see
  #   below.
  #
  # MPW 2014-01-03
  
  export PATH=$PATH:/usr/local/bin
  
  SCRIPT=${0##*/}
  TODAY=`date +%Y-%m-%d`
  shutdown="no"
  tsargs=""
  
  # Define archive names, backup targets and associated tarsnap arguments
  archives='mark=--exclude:public_html/*:--exclude:www-src/*:/home/mark 
    heather=/rep/backups/heather 
    repcvs=/rep/backups/topaz:/rep/backups/amber 
    windows=/tank1/backups/gold/windows'
  
  # process switches
  while [ $# -gt 0 ]; do
     case $1 in
         -a)
             tsargs=$2
             shift
             ;;
         -s)
             shutdown="yes"
             ;;
         *)
             echo $SCRIPT: unknown argument: $1
             exit 1
             ;;
     esac;
     shift
  done
  
  set -f # prevent globbing of tarsnap args
  for arch in $archives
  do
      archname=${arch%=*}
      archargs=`echo ${arch#*=}|sed -e 's/:/ /g'`
      echo Creating archive: ${archname}-${TODAY}, args: ${tsargs} ${archargs}
      tarsnap -c -f ${archname}-${TODAY} ${tsargs} ${archargs}
  done
  
  if [ $shutdown = "yes" ]; then
      shutdown -p +1
  fi