encrypted backup appliance with raspberry pi and rsnapshot
*** I actually ended up replacing rsnapshot with obnam as detailed in this post. ***
Today, I decided to switch up my backup routine. Before I was using a mix of bash and python scripts to backup different machines, but I wanted to set up a single appliance that could take care of all of my servers and keep backups in a centralized, encrypted location. What I ended up with is a raspberry pi with an encrypted 4TB usb drive.
First, I installed raspbian lite on the raspberry pi, then I changed the root password and removed the pi user.
Next, run updates.
apt install rsnapshot lvm2 cryptsetup
Encrypt the Storage Drive
Next, I set up the encrypted usb drive as a dm-crypt device in LUKS encryption mode.
cryptsetup -v luksFormat /dev/sda
You can also manually specify any options if you don’t like the defaults.
cryptsetup -v --cipher aes-xts-plain64 --key-size 256 --hash sha256 --iter-time 2000 --use-urandom --verify-passphrase lusFormat /dev/sda
Enter your passphrase and your drive is now encrypted.
To be of any use, you will need to mount the drive and create a filesystem.
cryptsetup open --type luks /dev/sda backups
The ‘backups’ in the above command is the name I chose for the device mapper. This will open the encrypted drive as /dev/mapper/backups and you can then create a filesystem.
Create a mount point.
mkdir -p /mnt/backups
Mount the drive.
mount -t ext4 /dev/mapper/backups /mnt/backups
At this point, your drive is encrypted and unlocked and mounted to /mnt/backups. To close the drive, unmount and close it.
cryptsetup close backups
Now this is all good if you just intend to unlock your drive, copy some files, and then lock it back again, but I wanted this to be an appliance. I need the drive available all the time while it is connected to the raspberry pi. To do this, I will need to add a keyfile to the system to unIock the drive when the raspberry pi boots. The problem with this, is that the keyfile is readable by anyone on the system which means that your drive is available to anyone who can access the pi. I only really care about the drive being encrypted when it is removed from the appliance and stored elsewhere so this is fine for my purposes.
Create a folder /etc/keyfiles.
mkdir -p /etc/keyfiles
Create a keyfile.
dd if=/dev/urandom of=/etc/keyfiles/luks_key bs=1024 count=4
Set permissions on the keyfile.
chmod 0400 /etc/keyfiles/luks_key
Now add the key to the drive so that it can be unlocked with your key.
cryptsetup luksAddKey /dev/sda /etc/keyfiles/luks_key
You can dump the luks header and see that your key has been added to slot 2.
crytpsetup luksDump /dev/sda
Now, to have the disk auto unlock and mount at boot, get the disk’s UUID.
Make a new entry in /etc/crypttab using the UUID from output of the previous command.
backup UUID=b432dd1-87a3-439f-80ce-1a2cddef13a /etc/keyfiles/luks_key luks
Update the initial ramdisk.
update-initramfs -u -k all
It should report back:
* backups (started)
Make sure the device is mapped.
Make sure backups is listed.
Make a new entry in /etc/fstab.
/dev/mapper/backups /mnt/backups ext4 defaults 0 2
Make sure it mounts correctly.
Now your encrypted drive will be mounted on boot. Reboot and make sure that /dev/mapper/backups is available and mounted to /mnt/backups.
Set up backup service
Earlier, we installed rsnapshot. rsnapshot is a filesystem snapshot utility based on rsync. This will allow us to backup remote systems over ssh with rsync.
The rsnapshot config file is located at /etc/rsnaphot.conf. Edit this file and set your snapshot_root to the encrypted drive.
Uncomment the external program dependencies.
Those are the basic settings. The rest of the config file is fairly self-explanatory so make any other changes you would like and save the file. You can test your configuration with:
It will tell you exactly what is wrong if there are any errors.
Automate the backups
To have the backups automatically run on a schedule, you will need to set up a systemd service and timer. Create /etc/systemd/system/rsnapshot@.service
Finally, enable and start the service and it should perform an hourly backup of all of your backup targets.
systemctl enable rsnapshot-hourly.timer
systemctl start rsnapshot-hourly.timer
You can extend this by adding daily, weekly, and monthly timers to archive longer periods of time.
To manually run a backup:
# systemctl start rsnapshot@hourly # or rsnapshot@daily, rsnapshot@weekly, ...
The backups drive will contain folders named, daily.0, daily.1 etc. The latest backup will be daily.0 and daily.6 will be a week ago. Each of these folders contain a full backup, so to restore the previous days files, just copy the contents of daily.0 back to its original location. Its as simple as that. You can find more info at rsnapshot.org