Mon 21 December 2015
By DrWhoZee
my new root server host offers—as part of the base package—a 100
GB backup package. access to that space is via SMBFS/CIFS, WebDAV, or
FTP. as we don’t really want to have our data lying around in the
clear, i needed a solution to encrypt the data before storing it
on the backup server. also, i really wanted to use rsnapshot to do
the job.
after a bit of mucking around, this is what i came up with (all as root obviously).
set up an encrypted backup image
mount the backup server via smbfs/cifs at /mnt/backup-server
.
create a sparse disk image:
# truncate -s 90G /mnt/backup-server/backup.image
make it available as a loopback device:
# losetup /dev/loop0 /mnt/backup-server/backup.image
set up /dev/loop0
as a LUKS partition:
# cryptsetup luksFormat /dev/loop0
open the LUKS partition and make it available as /dev/mapper/backupfs
:
# cryptsetup luksOpen /dev/loop0 backupfs
create an ext4 filesystem on the opened LUKS partition:
# mkfs -t ext4 /dev/mapper/backupfs
and mount it as /backups
:
# mkdir /backups
# mount /dev/mapper/backupfs /backups
set up rsnapshot
and run it.
once rsnapshot has done its job, umount the backup image, release the
loopback device, unmount the backup server.
automating it
to automate the whole setup:
to mount the backup server and the contained LUKS image, the mount-backup
script
#!/bin/bash
BACKUPLUKS=/mnt/backup-server/backup-90G.luks
DMTAG=backupfs
BACKUPS=/backups
LUKSKEYFILE=/etc/backup/luks.txt
# setup: utilities
logger=/usr/bin/logger
mount=/bin/mount
losetup=/sbin/losetup
grep=/bin/grep
cryptsetup=/sbin/cryptsetup
# action
$mount /mnt/backup-server
if [ ! -e "$BACKUPLUKS" ]; then
$logger --priority user.err "failed to mount backup server, did not find $BACKUPLUKS --- aborting."
exit 1
fi
if $losetup -a | $grep -q "$BACKUPLUKS" ; then
$logger --priority user.err "oops: $BACKUPLUKS still in use --- aborting."
exit 2
fi
$losetup /dev/loop0 "$BACKUPLUKS"
$cryptsetup --key-file $LUKSKEYFILE luksOpen /dev/loop0 "$DMTAG"
$mount /dev/mapper/"$DMTAG" "$BACKUPS"
along with it’s companion to umount the whole stack, the umount-backup
script
#!/bin/bash
BACKUPLUKS=/mnt/backup-server/backup-90G.luks
DMTAG=backupfs
BACKUPS=/backups
# setup: utilities
logger=/usr/bin/logger
mount=/bin/mount
umount=/bin/umount
losetup=/sbin/losetup
grep=/bin/grep
cryptsetup=/sbin/cryptsetup
sync=/bin/sync
# action
$sync
$umount "$BACKUPS"
$cryptsetup luksClose "$DMTAG"
$losetup -d /dev/loop0
$umount /mnt/backup-server
finally, a wrapper around rsnapshot to mount the backup image, run
rsnapshot, capture stats, and unmount the backup image, the
rsnapshot-local
script
#!/bin/bash
REPORT=/tmp/$$-report
RECIPIENT=you@your.email.address.here
TIMESTAMP=$(date --rfc-3339=seconds)
SUBJECT="rsnapshot $@ at $TIMESTAMP"
rm -f $REPORT
echo "rsnapshot $@ report from $TIMESTAMP" > $REPORT
echo "" >> $REPORT
echo "Mounting secure backup & running rsnapshot:" >> $REPORT
if /usr/local/sbin/mount-backup; then
/usr/bin/rsnapshot "$@" | while read line; do
echo " $line" >> $REPORT
done
fi
echo "" >> $REPORT
echo "Backup server space used:" >> $REPORT
df -H /mnt/backup-server | while read line; do
echo " $line" >> $REPORT
done
echo "" >> $REPORT
echo "Backup image size:" >> $REPORT
ls -lsh /mnt/backup-server | while read line; do
echo " $line" >> $REPORT
done
echo "" >> $REPORT
echo "rsnapshot disk usage:" >> $REPORT
/usr/bin/rsnapshot du | while read line; do
echo " $line" >> $REPORT
done
echo "" >> $REPORT
/usr/bin/mail -s "$SUBJECT" "$RECIPIENT" < $REPORT
rm -f $REPORT
/bin/sync
/usr/local/sbin/umount-backup