Dirt-cheap client-encrypted online backups with Raspberry Pi

Mike Solomon

To be useful to me, backups must be:

  • Stored in a reliable and offsite location
  • Readable only by me (client-side encryption)
  • Cheap
  • Automatic

We can achieve all of these goals with a combination of tools:

I have been using this setup for about a year, and it costs me about $2 a month for about 100 GB of backups.

The Raspberry Pi is very useful because it uses very little power and can backup my Network Attached Storage (NAS) automatically over the network.

Aside: backing up a computer

You should strongly consider using Backblaze1. It’s cheap, has no storage limit, and lets you use your own encryption key. It’s going to be the simplest and most reliable bet if you only need to backup the computers you use frequently, instead of your NAS.

Backing up your NAS, or multiple computers

There are five basic steps we need to get backups running:

  1. Set up the storage service: Google Nearline
  2. Set up the connection to the files to be backed up: sshfs
  3. Set up encryption software: GPG
  4. Configure the backup software: Duplicity
  5. Run the backups on a schedule: cron

Set up Google Nearline

Go to the Google Developer’s Console, and sign up as necessary. You may need to enter billing information. Create a new project on that page, perhaps called duplicity-backups.

Click on the duplicity-backups project and click the hamburger menu (three lines) button in the upper left corner and select “Storage” under “Storage.” Press “Create bucket” and choose a name (perhaps “photos”) and select “Nearline” for “Storage class.”

The last piece needed is access credentials for this storage bucket. Press Settings on the left, then click Interoperability. Create a new key, then copy down the Access Key and Secret shown. We will use these later.

Mounting via SSH

You will need to access the files you wish to backup (likely located on your NAS) over the network. I will assume that they are reachable via SSH. If they are not, you will need to mount them on the filesystem in a similar way (perhaps with NFS).

Run sudo apt-get install sshfs to make mounting drives over SSH possible.

It will be easier to connect to your NAS via SSH if you use passwordless authentication with a public/private key pair. Run ssh-copy-id nasuser@mynashost to copy it, substituting in your actual NAS information.

Run mkdir ~/nas to create a place to mount your NAS directories.

Add lines like this to /etc/fstab so your Raspberry Pi can treat the remote host as a drive:

root@mycroft:/my-nas/Photos /home/pi/nas/Photos fuse.sshfs      user,delay_connect,noauto,_netdev,uid=1000,gid=1000,idmap=user,allow_other,reconnect 0 0
root@mycroft:/my-nas/write /home/pi/nas/write fuse.sshfs      user,delay_connect,noauto,_netdev,uid=1000,gid=1000,idmap=user,allow_other,reconnect 0 0

And test it with sudo mount /home/pi/nas/Photos, verifying that the files appear in that directory as expected.

I recommend that your create a second partition directory on your NAS (separate from that which you wish to back up) to store Duplicity’s local cache and log files. Otherwise, you are likely to quickly fill your Raspberry Pi’s local storage. This directory is called “write” in my examples. Run touch /home/pi/nas/write/.useThisWriteDir after it is mounted to use with the script below.

Set up GPG and your encryption keys

GPG is supported by Duplicity for encryption, and provides a high level of security.

Run sudo apt-get install gnupg. Then run gpg --gen-key and follow the prompts, choosing the defaults. Be sure to choose a long (ideally random) passphrase and to write it down (preferably in a password manager). You won’t be able to read your backups without the generated keys, so be sure to back that up as well.

We will need the fingerprint of the newly-generated key to tell Duplicity to use it. Run gpg --fingerprint to see it. gpg --fingerprint | grep pub | grep -P "(?<=/)\\w{8} " should highlight the 8-character fingerprint you require.

Set up Duplicity and the backup script on your Raspberry Pi

These instructions assume you use Raspbian. They should be adaptable for use on other Linux (or Linux-like) systems.

Install duplicity by running sudo apt-get install duplicity.

A simple backup script is needed to store credentials and run the backup. I store it along with the files I wish to backup (Photos), but you could do something more secure instead.

# stored in Photos, the directory I wish to back up

export SRC=/home/pi/nas/Photos
export DEST=gs://<your Google Cloud Storage bucket name>/Photos

export FTP_PASSWORD="<password>"
export GS_ACCESS_KEY_ID="<your Google access key>
export GS_SECRET_ACCESS_KEY="<your Google secret>"

export KEY="<your GPG key fingerprint (8 characters)>"
export PASSPHRASE="<your GPG passphrase>"

# Locking is handled by cron. This has helped it restart after problems.
killall duplicity
find /home/pi/nas/write/.cache/duplicity/ | grep lockfile.lock | xargs rm

# make sure we're using the right write dir.
# remote mounting issues can otherwise cause problems
if [ ! -f /home/pi/nas/write/.useThisWriteDir ]; then
  echo "write directory does not appear to be mounted"

duplicity \
  --sign-key $KEY \
  --encrypt-key $KEY \
  --log-file /home/pi/nas/write/duplicity.log \
  --archive-dir /home/pi/nas/write/.cache/duplicity/ \
  "$SRC" "$DEST" 2>&1 >> /home/pi/nas/write/duplicity-foreground.log

Run the backup script on a small test directory to make sure it’s all set up properly.

Scheduling backups with cron

The last step is to run this backup automatically. Cron can do this for us, and is built-in.

We will use a simple perl script to keep things from running multiple times. Download it to /home/pi and make it executable with chmod u+x /home/pi/solo.pl.

Run crontab -e and add these lines:

# m h  dom mon dow   command
* * * * * grep -qs '/home/pi/nas/write' /proc/mounts || /home/pi/solo.pl -port=3386 mount /home/pi/nas/write
* * * * * ls /home/pi/nas/write || /home/pi/solo.pl -port=3386 sudo umount -f -l /home/pi/nas/write
* * * * * grep -qs '/home/pi/nas/Photos' /proc/mounts || /home/pi/solo.pl -port=3385 mount /home/pi/nas/Photos
* * * * * ls /home/pi/nas/Photos || /home/pi/solo.pl -port=3385 sudo umount -f -l /home/pi/nas/Photos
* * * * * grep -qs '/home/pi/Drive' /proc/mounts || /home/pi/solo.pl -port=3384 mount /home/pi/Drive
* * * * * /home/pi/solo.pl -port=3383 sh /home/pi/nas/Photos/backup.sh > /dev/null 2>&1

# optional: automatic reboots and software updates to keep things well-oiled
0 5 * * * ssh mynasuser@mynas 'reboot'
0 5 */2 * * sudo /sbin/shutdown -r +1
0 6 * * * sudo rpi-update
0 7 * * * sudo apt-get update -y && sudo apt-get upgrade -y
0 10 * * * sudo apt-get autoremove -y && sudo apt-get autoclean -y && sudo apt-get clean -y

This will start a new backup as soon as the last completes. This works well for my use case, adjust as necessary.

Be sure to test your backups to ensure you can restore in a disaster! duplicity verify may help you here.

Future improvements

This could be improved with emails about failed backups, or when backups haven’t run for some time. The overall process could also be simpler. Ideas? Let me know in the comments and I can update the article with them!

  1. I have no affiliation with Backblaze.