Offsite backups with Raspberry Pi and a friend

Do you have a big Plex video library? Maybe a sizeable MP3 collection that you spent years assembling? Or do you host your private ownCloud server at home? Regardless of what your data is, chances are you've got some files at home that you'd rather not see disappear. Backups are great, but where do you store your backups? At home, in the same place as your original copy? If you suffer an unfortunate house fire, chances are good that your backup will get burned up along with your original. You could back up to a cloud service, but with any significant amount of data to backup there will be some monetary cost. And maybe certain recent revelations have made you a little leery about putting your data in the cloud. Well, do you have a friend with a broadband Internet connection? Why not backup to his house?

In this post, I'm going to run through how to setup a secure remote backup solution using one or more Raspberry Pis (RPi), an external drive, and a friend's broadband Internet connection, using rsync, OpenSSH, and OpenVPN. This configuration will create a mirror-copy backup of your source computer, on whatever schedule you choose to set. The number of RPis needed really depends on the system you're backing up. If you're running a flavor of Linux on your computer, most likely you already have the tools available on that box to run the backup scripts. So you'll only need one Raspberry Pi for the remote side. If you're running a version of Windows on your computer... I'm sorry. But also, you'll need a second Raspberry Pi on your local network to send your backups to the remote end.

The topology will look like this:

 +----------+      +----------+
 |  source  |      |  source  |
 |  volume  |      |  volume  |
 +----------+      +----------+
       |                |
 +----------+     +------------+
 | Linux PC |     | Windows PC |
 +----------+     | CIFS share |
       |          +------------+
       |                |
      +=+        +--------------+
      | |        | Raspberry Pi |
      | |        | Samba client |
      | |        +--------------+
      | |               |
      | |              +=+
  ~~~~| |~~~~~~~~~~~~~~| |~~~~~~
 (    |V|              |V|      )
 (    |P|   Internet   |P|      )
 (    |N|              |N|      )
  ~~~~| |~~~~~~~~~~~~~~| |~~~~~~
      +=+              +=+
       |                | 
+--------------+  +--------------+
| Raspberry Pi |  | Raspberry Pi |
+--------------+  +--------------+
       |                |
 +-----------+     +-----------+
 | Encrypted |     | Encrypted |
 |   backup  |     |   backup  |
 |   volume  |     |   volume  |
 +-----------+     +-----------+

Fig. 1: Backup uses rsync over SSH, tunneled through a VPN.

The backup process uses the rsync program. There are a couple of different ways you could build a solution. You could setup an rsync server on the remote Raspberry Pi and then rsync over VPN. Or you could use SSH as the secure transport for rsync, eliminating the need for an rsync server. For this configuration, we're going to take more of a layered hybrid approach.

We will use OpenVPN to setup an on-demand VPN tunnel between our backup source and target. We'll then run rsync between the VPN endpoints, using SSH as the transport. This has the downside of being a little slower than using an rsync server, and being just slightly slower than using SSH alone without adding the overhead of VPN encryption. However, this solution has three upsides:

  1. We don't have to leave a TCP port open on our home connection to allow SSH traffic through. We could change the port from the standard TCP/22 to an obscure custom port, but it still might be scanned. We will have to open a UDP port for our OpenVPN connection to use, but open UDP ports are significantly harder to detect with network scanning tools than open TCP ports. And generally speaking, malicious hackers usually don't bother looking for open UDP ports in a non-targeted, opportunistic sweep because it's time-consuming and unreliable. This affords us some additional security (albeit, through obscurity).

  2. By using a VPN tunnel as a wrapper, we can restrict SSH access on the remote RPi to a single remote IP: that of the other VPN endpoint. With SSH alone, we would have to assume that the remote public NAT IP could change from time to time, and so we would have to allow SSH access from a wider source scope, if not from any source.

  3. Using a VPN tunnel as a wrapper for the SSH traffic adds an additional layer of security, and a second factor of authentication for the connection.

A few words about data security

This solution was designed to be as secure as possible. With any security measure, there is some trade-off in convenience. Here are the caveats with this configuration:

  • The backup volume is secured using LUKS partition-level encryption, and the passphrase is not stored on the remote RPi. This prevents the remote volume from being automatically mounted, but it also prevents someone from pulling your SD card and compromising your encryption key. However, this means that if the remote RPi is rebooted or the drive disconnected, you will need to SSH to the device and manually enter your encryption passphrase to re-mount the disk. This is a minor inconvenience that provides a high degree on on-disk data security.

  • In the configuration I'll provide, the remote RPi is not accessible via SSH from the remote LAN, or even from the local console if someone were to connect a keyboard and monitor. The only way to access a terminal on the remote RPi is to establish a VPN tunnel to it and SSH from your local VPN endpoint. For this reason, remote support of your device will be limited to rebooting it with a power cycle. But, this measure also prevents unauthorized users from logging into your system and viewing the mounted backup volume and its decrypted contents.

So with your remote backup target, no sensitive information is stored on the Raspberry Pi's unencrypted SD card. Your backup volume is encrypted and the passphrase is not stored anywhere on the remote RPi. Any tampering with the remote backup target (i.e. rebooting, disconnecting the disk, etc.) will simply result in an unmounting of the backup volume. The data on the volume can only be read when the backup volume has been mounted and the encryption passphrase entered, and there is no way for an unauthorized user even with physical access to view the disk in its mounted state.

In the worst case scenario where the backup target and disk are stolen, the most you are out is the cost of the Raspberry Pi and external backup disk. Your data is safe (assuming you used a strong encryption passphrase that is not easily guessed).

A few words about network security

The data on your remote backup volume is secure. Now let's assume that your friend has been so kind as to host your backup solution, and he thinks it's a great idea. He asks you to reciprocate and host his backup on your network. Seems only fair, right? Sure, just keep one thing in mind. By hosting his remote backup RPi on your network, you are giving him access to your internal LAN. Your friend could (theoretically) fire up the VPN tunnel to his remote RPi, SSH into it, and then gain access to your local network. Now, hopefully if you trust this person enough to host your backup volume, you trust them enough not to compromise your network.

But still...

My advice would be to host your friend's remote backup RPi in a DMZ on your network. A DMZ with access control that restricts the RPi from connecting to your local LAN, and possibly even to the Internet in general (the remote RPi only needs incoming connections). If you don't have a firewall with multiple interfaces that supports defining a DMZ network, my suggestion would be to work out some other creative method for segregating your friend's Raspberry Pi from the rest of your LAN. Good fences make good neighbors, and the same goes for firewall rules.

The basics

To start with, you'll need one or two Raspberry Pi computers, and an SD card (micro SD for the RPi2) and micro USB power supply for each RPi. You'll also need an external USB hard drive big enough to contain a backup of your source data, and you probably want to put each RPi in a case of some kind. For my remote RPi, I put it in a JBtek case and velcro'd the RPi to the side of my external drive. This allowed me to keep the USB cable really short and minimize cable clutter. For the SD card, you don't need anything huge. I typically use 8GB SD cards for RPi storage, unless larger cards are available at a lower price. SD card prices are strange, sometimes a 32GB card is less than a 8GB card.

You should image your SD card(s) with the latest version of Raspbian, and this tutorial assumes you're using the built-in ethernet port, and you're configuring each RPi with a static IP address or using a DHCP reservation to assign a fixed IP address.

I'm not going to go into great depth regarding installing Raspbian and doing the initial setup. You can find useful information about installation here. You'll need to use the raspi-config tool to enable the SSH server (under Advanced Options/SSH) on your remote RPi.

If you're running Linux on the source computer, you'll have to determine what account you want to use for running your backup. If you want to perform a full system backup, you'll likely want to run the backup as root so that it can read every file in /. If you only want to backup a specific partition or directory, then you may be able to use a standard user account that has read access to the files being backed up. On Debian-based distributions (including Ubuntu) the root account has no default password and is unable to login. You'll need to set a strong password for root.

If you're running Windows on the source computer, you'll need to setup a network share or shares for the files you want to backup. You should create a designated local, non-admin account on your computer that has read-only access to the share(s) and underlying filesystems. Set a strong password for this account.

On the remote RPi (and local RPi if you're running Windows), you will only use the root account. You should set a strong password for the root account, login as root and delete the default pi account, so that root is the only account on the system with login/shell access on the remote RPi.

If you need to set a static IP on your RPi, edit /etc/network/interfaces, remove the line that reads iface eth0 inet dhcp, and add a configuration such as:

iface eth0 inet static

Then issue the command service networking restart to pick up the new config.

For the initial setup and the seed copy, you'll have both endpoints (computer and RPi, or RPi and RPi) connected to the same LAN. So you'll either need two DHCP reservations during setup, or to configure both with static IPs. If the DHCP server on your network (and your friend's network) supports reservations, I'd recommend just using a DHCP reservation for the remote side and leaving the RPi set for DHCP. I also recommend against using WiFi for network connectivity, as wireless will be an additional wildcard for troubleshooting and will certainly provide poorer network performance than the 100Mbps wired interface. Network speed is going to play a particular role in making your seed copy.

Required packages

The first thing you'll need to do once you have imaged and base configured your RPi(s) is to install the necessary packages on both the source and target computers. You will need the openvpn, easy-rsa, and rsync packages. On Raspbian, easy-rsa is bundled with openvpn, but they are separate packages on other distros. You can install these packages on Raspbian with the command:

apt-get update
apt-get install openvpn rsync


Your local source computer (or local RPi) will need to make a VPN connection to the public IP address of your friend's Internet connection, where it will be NAT'd to the remote RPi. With most residential broadband providers, this IP is subject to change. You have two options:

  1. Use an entry in your source computer's /etc/hosts file to resolve a remote server name to public IP address, and update that entry manually should your friend's public IP address change, or

  2. Use a dynamic DNS (DDNS) provider to have a public DNS name that always points to the current IP of your friend's broadband connection.

If your friend's public IP doesn't change often (if at all), then option #1 is probably fine. If the public IP tends to change fairly often, you'll probably want to opt for option #2. Raspbian includes the ddclient package (apt-get install ddclient), which will provide a dynamic DNS client on your remote RPi. You'll need to sign up with the DDNS service of your choice, and configure the /etc/ddclient.conf accordingly.

Setting up SSH

You will be authenticating SSH sessions from the source computer to the target computer using keys rather than passwords. So you'll need to generate an SSH key. Run the following command on the source computer (or local RPi, if your source is a Windows computer):

ssh-keygen -t rsa -b 4096

Assuming you're generating the key as root set the default install location to /root/.ssh/backup. Do not set a passphrase on this key. After the key is generated, you will need to copy the /root/.ssh/backup.pub public key to /root/.ssh/authorized_keys on the remote RPi. You can do this using the ssh-copy-id command:

ssh-copy-id root@<remote RPi IP>

You'll be prompted for the root password on the remote RPi. After the key is copied, you should be able to SSH without being prompted for a password. If not, check the permissions on /root/.ssh and /root/.ssh/authorized_keys on the remote RPi. They should not be group- or world-writable. On the local side, the /root/.ssh/backup RSA key should only be accessible by the root user:

chmod 600 /root/.ssh/backup

Also check /etc/ssh/sshd_config on the remote RPi to ensure that PermitRootLogin yes, RSAAuthentication yes, and PubkeyAuthentication yes are set. If any of these need to be changed, restart SSH afterward.

On the source computer or local RPi, edit the ~/.ssh/config file for root (or whichever user will run the backup scripts), and enter the following:

Host backup
    User root
    Port 22
    IdentityFile /root/.ssh/backup

For right now, continue connecting to the RPi by using the command:

ssh root@<LAN IP address>

Later in this tutorial, once we get the OpenVPN tunnel setup, you'll be able to connect using the simpler command:

ssh root@backup

OpenVPN configuration

On the source computer or local RPi, you'll need to first setup an entry in your /etc/hosts file. This entry should have either the DDNS name that you have registered, or a real (or fake) fully-qualified domain name (FQDN) for the remote RPi. The IP address for this entry should be the local LAN IP that is currently assigned to the remote RPi. When the RPi is deployed, you'll change this entry to your friend's public IP. The VPN client connection will use the hostname you set in /etc/hosts. The entry should be in the format:   remote.backup.net

Even if you're going to use DDNS for the remote RPi, for the initial setup and seed copy - since the remote RPi will be on the local network and not at the IP address DDNS will report - you'll need to setup this /etc/hosts entry. Once the seed copy is complete and you send the remote RPi offsite, you'll just remove that entry from /etc/hosts and the name will resolve normally via DNS to the public IP address.

Under Raspbian, when the openvpn package is installed it is enabled and started up. On the remote RPi we want the OpenVPN service to start automatically, so that is fine. On the source computer or local RPi, we only want the VPN tunnel to connect when it's needed. So if your local VPN endpoint is an RPi or other Debian-based system, be sure to prevent OpenVPN from starting automatically:

update-rc.d openvpn disable

Now you'll need to create some certificates to encrypt and authenticate your VPN connection. This can be a somewhat involved process, and I'm going to just run through the highlights. If you'd like more info on OpenVPN and creating certificates, check out this tutorial. You'll only need to go through this cert generation process on the remote RPi side. Once you're done, you'll just copy a few of the certificate files to the source computer or local RPi for the client side of the connection.

First, you're going to create a directory to build the keys and copy the easy-rsa starter files into it. You're also going to create a symlink for the openssl config file, in case your openssl version isn't detected properly:

mkdir -p /etc/openvpn/easy-rsa/keys
cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa
ln -s /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf

Move into the easy-rsa directory:

cd /etc/openvpn/easy-rsa

You'll need to edit the vars file and modify two parameters:

export EASY_RSA="/etc/openvpn/easy-rsa"
export KEY_SIZE=2048

Save the changes, and then do the following:

source ./vars

Now you'll build your certificate authority (CA) cert. You'll be prompted to provide some certificate details. It really doesn't matter what you enter for country, province, city, organization, organizational unit, or email. The only two fields that matter are the certificate name (which you should call 'server') and the canonical name (CN), which should be the fully-qualified name you've given to your remote RPi.


You'll repeat the process to build the server certificate:

./build-key-server server

Next you'll create your Diffie-Hellman (DH) key exchange file. This can take a while. You might want to type this and then go make a sandwich:


Now create a client certificate for your source computer or local RPi:

./build-key client

And then finally, we're going to create a TLS-auth key for an additional layer of security, and then copy the necessary keys to the /etc/openvpn directory:

cd keys
openvpn --genkey --secret ta.key
cp dh2048.pem ca.crt server.crt server.key ta.key /etc/openvpn

You'll need to copy the ca.crt, client.crt, client.key, and ta.key files to the /etc/openvpn directory on your source computer or local RPi, as well.

A WORD OF WARNING: Don't leave your ca.key file on your remote RPi. It's not needed there. My advice is to backup all of your OpenVPN keys, and then rm -rf /etc/openvpn/easy-rsa rather than leaving it laying around. At the very least, backup the ca.key file and delete it from the remote RPi.

Now with keys and certs in place, you just need to create some configuration files. On the remote RPi, create /etc/openvpn/openvpn.conf:

port 21999 #just a high, random port
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
ifconfig-pool-persist ipp.txt
keepalive 10 120
tls-auth ta.key 0
max-clients 1
user nobody
group nogroup
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 4
mute 20

Now restart the openvpn service on the remote RPi:

service restart openvpn

Ensure that the OpenVPN service started and is running on port 21999:

netstat -an | more
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
udp        0      0 *               LISTEN

Now configure the client side on the source computer or local RPi. On Raspbian or another non-systemd distro, you'll edit the /etc/openvpn/openvpn.conf file. For a systemd-based distro, edit the /etc/openvpn/backup.conf file:

dev tun
proto udp
remote remote.backup.net 21999 # use the name you put in /etc/hosts
resolv-retry infinite
user nobody
group nogroup # this may be nobody, check your /etc/group
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
verb 3
mute 20

On Raspbian or another non-systemd distro, start the OpenVPN client with the command:

service openvpn start

For a systemd-based distro, start the openvpn@backup service:

systemctl start openvpn@backup

Within a few moments, the tunnel should establish. Verify by using the ifconfig command. You should see a tun0 interface:

tun0: flags=4305<up,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet  netmask  destination
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 12165  bytes 15687148 (14.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7096  bytes 773505 (755.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Verify connectivity by pinging

[root@home /]# ping -c 4
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=29.3 ms
64 bytes from icmp_seq=2 ttl=64 time=33.5 ms
64 bytes from icmp_seq=3 ttl=64 time=35.6 ms
64 bytes from icmp_seq=4 ttl=64 time=33.1 ms

--- ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 29.368/32.928/35.669/2.273 ms

At this point, you should now be able to SSH from the source computer (or local RPi) to the remote RPi, using the command:

ssh root@backup

Encrypting the backup volume

Now we need to setup the encrypted backup volume. In the examples that follow, I'm working with the assumption that your external USB disk is connected to the remote RPi. The disk will likely be /dev/sda and the partition should be /dev/sda1. If you need to re-partition your backup disk, use either the fdisk or parted commands to do so. If your source computer is running Linux, you could connect your USB disk to that computer and then partition your disk and create the encrypted volume using a GUI disk utility (such as the GNOME Disks tool), if you prefer. I'm going to assume you're connecting the disk to the remote RPi and creating the volume from the CLI. To create the encrypted volume on /dev/sda1, you'll use the cryptsetup command. This tool isn't installed by default on Raspbian, so the first thing you'll need to do is install the cryptsetup package:

apt-get install cryptsetup

Then you can create the encrypted volume:

cryptsetup --verify-passphrase --cipher aes-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda1

Now you'll need to get the UUID of the volume you just encrypted. Do the following:

ls -al /dev/disk/by-uuid

What you're looking for is a line in the output like this:

lrwxrwxrwx 1 root root  10 Jan  1  1970 d5201310-4c76-49ab-a36d-46446f4415da -> ../../sda1

Select and copy that UUID. You'll need it in a second. The last thing to do here is to create a mount point where we'll mount the backup volume:

mkdir /mnt/backup

Windows mounts

If the computer you're backing up is running Windows and you've got an RPi for the local VPN endpoint, you'll need to mount the share(s) that you've created on the Windows computer, on the local RPi so it can read them. First, you'll need to create a credentials file, containing the Windows user credentials needed to access the share. Put these credentials in /root/.smbcreds and make sure the file is owned by root, with 0600 permissions. The contents of the file should be:

username=<your Windows username>
password=<your Windows password>
domain=<domain or workgroup>

Create a mount location for your Windows share(s):

mkdir -p /mnt/windows/share1

Then create an entry in /etc/fstab to mount the share:

//<Windows IP address>/<share name> /mnt/windows/share1 cifs auto,ro,credentials=/root/.smbcreds 0 0

You should now be able to mount the Windows share and view the files there:

mount /mnt/windows/share1

The scripts

You could do all of these tasks manually, but since a) they are repetitive, and b) you're going to want to automate them, we'll setup some scripts to make things easier. The first thing you'll need is a script to mount your backup volume, since we won't be mounting it automatically with /etc/fstab. On your remote RPi, create a bash script with the following contents and name it something obvious like mount-backup.sh. Move it to the /usr/sbin directory, make root the owner, and make sure only root can execute it (chmod 700):

cryptsetup luksOpen UUID=d5201310-4c76-49ab-a36d-46446f4415da backup # use your UUID here
mount /dev/mapper/backup /mnt/backup

Now you should be able to mount your encrypted volume by typing mount-backup.sh and entering your passphrase. Go ahead and do so now, you'll need the volume online for the seed backup later.

On the source computer or local RPi, you should create three scripts.

  1. A script to bring up the VPN tunnel.
  2. A script to bring down the VPN tunnel.
  3. A script to backup from the source to the remote target.

The first two are going to be distribution-specific. Generally, it's going to be something like:

service openvpn start

Or something like this, for systemd-based distributions:

systemctl start openvpn@backup

Whichever command you used to bring up the VPN tunnel earlier in this tutorial, is the one you'll put in these scripts. Make two scripts:


/usr/bin/systemctl start openvpn@backup

And /usr/sbin/stop-vpn.sh

/usr/bin/systemctl stop openvpn@backup

Again set each script to be owned by root, with permissions of 0700. Test your scripts to ensure the VPN tunnel goes up and down. Now let's create the actual backup script. This script will bring up the VPN tunnel, wait 60 seconds for it to initialize, and then run a full system backup with rsync, tunneled over SSH. Call this script /usr/sbin/remote-backup.sh, and once again make sure it is owned by root with 0700 permissions:

echo "Starting VPN..."
echo "Waiting..."
sleep 60
cd /
echo "Beginning rsync backup..."
rsync -avz -e "ssh" --exclude /sys --exclude /tmp --exclude /run --exclude /proc --delete / root@backup:/mnt/backup
echo "Shutting down VPN..."

If you are backing up a mounted Windows share, your rsync line might be much simpler:

rsync -avz -e "ssh" --delete /mnt/windows/share1 root@backup:/mnt/backup/share1

This will perform a mirror backup of the live system to the backup volume. Note the use of the --delete option. This instructs rsync that if you delete a file on the source side, the file should also be deleted from the remote side. You can choose to omit --delete from the line, and files that are deleted locally will remain on the backup. However, keep in mind that unless you remove the files manually, the disk space usage on your backup volume will continue to grow larger than the source as new files are sync'd, and deleted files are never deleted. I wouldn't recommend using this system as a versioned backup, but rather as just a weekly remote snapshot. If you want to do a versioned backup, I would recommend using rsnapshot and an external USB disk locally connected to the source system.

Seeding the backup

Now it's time to create your seed copy. You'll do this with both the local source and the remote target connected to the same LAN. After this seed copy is complete, only changes made to the source will be sync'd to the remote end. To start your seed, just run your backup script manually:


And... wait. This first copy will take quite a while if you've got a lot of data. Remember, the RPi's only have 100Mbps network interfaces. And if you're syncing a Windows share, the RPi has to read the files from the share and then send them to the remote RPi using the same interface. So the bandwidth is effectively reduced by half. Just have patience. If you have hundreds of gigabytes (or terabytes) of data, this seed copy may take several days.

Scheduling the backup

Once you have your backup script set, you'll want to add a cron job to run the backup weekly as root (or whatever user you've designated for backups). You can do that either by adding a file to /etc/cron.d containing:

0  1  * * 6  root /usr/sbin/remote-backup.sh

Or you can edit root's crontab using the command crontab -e and add:

0  1  * * 6  /usr/sbin/remote-backup.sh

Each of these examples runs a weekly job every Saturday at 1:00am. If you have an MTA setup on the source system and an alias configured for root, cron will email you the transcript of the session. If you don't have a mailer setup, you may want to add the following to the end of the cron line, to log the session:

> /root/last-backup.log

If you want to suppress all output, add the following instead:

> /dev/null 2>&1

But of course, then you won't know if your backups are actually running or not.

Securing the remote RPi

Now that everything is tested and the seed is created, let's secure the remote RPi before we send it to your friend's house. For starters, we want to prevent any unauthorized users from making an SSH connection to the RPi. Since the only valid SSH connection will come from the other end of the VPN tunnel, edit the /etc/ssh/sshd_config file and change PermitRootLogin yes to PermitRootLogin no. Then add the following to the bottom of the file:

Match Address
  PermitRootLogin yes

This will only allow root SSH access from (the source end of the VPN tunnel). And since no other accounts have shell/login access, that effectively disables remote login except over the tunnel. Restart SSH for the change to take effect.

service ssh restart

To disable local root login on the RPi's console, we simply need to remove all entries from the /etc/securetty file (thus rendering no terminal secure, and therefore root cannot login). The easiest way to do this is to backup the existing file and replace it with a blank file.

mv /etc/securetty /etc/securetty.sav
touch /etc/securetty

Once this is done, test access. Make sure you can not SSH to the remote RPi, except from the source computer or local RPi, and only when the VPN tunnel is up. Plug a keyboard and monitor into the remote RPi, and make sure you cannot login as root or any other user.

After all the testing is complete, run your remote-backup.sh script on your source computer or local RPi, just to ensure that everything still works properly. If you've recently done your seed copy, the sync should not take much time at all.

Deploying the remote RPi

Now it's time to send your remote RPi and backup disk to your friend's house. On your end, the only thing left to do is to edit or remove the /etc/hosts file entry you made previously to facilitate your seed copy on the local LAN. Either change the entry to your friend's public IP address, or remove it and use DDNS to resolve the name to IP.

At your friend's house, your RPi and hard drive should be put in a safe place, and connected to a surge protector (good) or a UPS (better). If you elected to use a DHCP reservation, your friend just needs to set that up in his DHCP server or router. Make note of the RPi's MAC address (ifconfig) before you send it out. If you're using a static IP, remember to change that on your remote RPi before you send it out the door. The only other thing required is for your friend to setup a NAT or port forward from his public IP to your RPi, on UDP port 21999.

Once the RPi is connected and online, login to your source computer or local RPi and use your start-vpn.sh script to bring up the VPN tunnel. It may take 20-30 seconds to establish, so be patient. Once the tunnel is up, you should be able to ping Then ssh root@backup to connect to your remote RPi, and run your mount-backup.sh script. Enter your passphrase, and make sure you can read the partition at /mnt/backup. If so, logout of the remote RPi, and use your stop-vpn.sh script to bring the tunnel down.

Then you just have to wait until Saturday at 1:00am (or until whenever you scheduled your backup to run), and check your log or email to make sure the backup completes properly. If so, you now have a weekly snapshot of your computer, backed up securely offsite. Congratulations!

Wrap up

This has been a complicated setup, and an insanely long post. Chances are good that I missed something somewhere along the way. If you find mistakes or omissions, if something is unclear or you think you may have a better way of doing it, shoot me an email. I'd love to hear from you.