Simple RSYNC/SSH/ZFS Backup


Hi there,

It has been a while, busy building clouds and stuff. In the Christmas spirit of sharing, today I wanted to share this bash script for ZFS backups, it will basically snapshot the ZFS share, RSYNC new files over and the delete the old ZFS snaps.

Simple, yes, but somehow a wheel that keeps being reinvented over and over again, so here’s my version of it. Hope it helps someone save some time.

For this script, the backup server is one of our own TerraNas servers (basically, Ubuntu 14 with Native ZFS and NFS/4) the client is a Ubuntu14 LTS server, the SSH keys have been imported to the client so we can SSH across without passwords and such.

On the ZFS/NFS server side, we disable ID mapping to have usernames cross the wire instead of ID’s

echo N > /sys/module/nfs/parameters/nfs4_disable_idmapping

share the ZFS drive with:

zfs set sharenfs=rw=@192.168.33.0/24,insecure,no_root_squash pool1/backup

Where 192.168.33.0/24 is your subnet or host of course.

Then we share it our with zfs share -a and service nfs-kernel-server restart.

We do have one export to the localhost in the /etc/exports file, because NFS will complain if this file is empty, but the rest of the exports come from ZFS

On the client we have this little script:

Make note of the additions of MOUNT and UMOUNT to the sudoers file, to enable a user to mount NFS shares.
# User home ZFS Backup Script 2.0
#
# Needs SSH token access to ZFS Server and NFS Mount Points
# ZFS/NFS exports on ZFS server under zfs/backup/*
# add Cmnd_Alias MOUNT=/bin/mount,/bin/umount to the ALIAS section in /etc/sudoers using visudo
# add ALL ALL=NOPASSWD: MOUNT to the END of the /etc/sudoers using visudo
#

# Vars
#
NOW=$(date +"%m-%d-%Y")
BACKUPSOURCE=/home/$USER
BACKUPDEST=$BACKUPSOURCE/zfs/$HOSTNAME
ZFSSERVER=192.168.33.10
ZFSPOOL=pool1/backup
ZFSMOUNT=zfs/$ZFSPOOL
RETENTION=5

# Create or mount the ZFS folder
#
echo ZFS Backup from $BACKUPSOURCE to $BACKUPDEST started..
if ! [ -d $BACKUPSOURCE/zfs ]; then mkdir $BACKUPSOURCE/zfs; fi
if ! mountpoint -q $BACKUPSOURCE/zfs; then if ! (sudo mount $ZFSSERVER:$ZFSMOUNT $BACKUPSOURCE/zfs); then echo "Mount of $BACKUPSOURCE/ZFS failed"; exit 1; fi;fi

# Add attempt to backup list and syslog
#
echo $NOW,$HOME/zfs/$HOSTNAME-$USER-$NOW.log >> $HOME/zfs/backup-$HOSTNAME-$USER-dates.lst
logger BACKUP-START-$NOW,$HOME/zfs/$HOSTNAME-$USER-$NOW.log

# Create ZFS folder or snapshot
#
if [ -d $BACKUPDEST ]; then
ssh root@$ZFSSERVER 'zfs snapshot '$ZFSPOOL'/'$HOSTNAME'@'$USER-$NOW
else
ssh root@$ZFSSERVER 'zfs create '$ZFSPOOL'/'$HOSTNAME
fi

# Remove the older snaps (see RETENTION varaible)
#
FS=$ZFSPOOL/$HOSTNAME
ssh root@$ZFSSERVER 'zfs list -rt snap -H -S creation -o name |grep '$USER' |tail -n '$RETENTION' |xargs -n 1 zfs destroy -r'
# Do the Magic
#
rsync -av -P $BACKUPSOURCE $BACKUPDEST --stats --human-readable --delete-before --log-file=$HOME/zfs/$HOSTNAME-$USER-$NOW.log --exclude-from=$BACKUPSOURCE/exclude.lst

# Clean it up
#
sudo umount $BACKUPSOURCE/zfs
logger BACKUP-END

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s