Encrypted remote backups with SSHFS and LUKS

back

I’d like to keep all my backups encrypted. For local backups it’s easy with LUKS, but for remote backups this is problematic as LUKS only works on the local system and I’d have to trust the remote host which is unacceptable.

There are many backup tools available for remote backups but they are quite complicated and sometimes use dubious cryptography or implementations. I prefer simple backup solutions. The following setup uses SSHFS combined with LUKS for encrypted remote backups.

(An alternative to SSHFS is NBD (network block device) over VPN, e.g. with NBD and OpenVPN.)

All commands must be run as root, see below for possible issues when running with sudo.

Note

This setup requires a stable internet connection. If the hosts is disconnected during the backup then everything will hang and you’ll have to kill the sshfs process and then unmount the backup directory manually.

Setup

Mount the target directory from the remote host with SSHFS and create a sparse file for the backup (it can be resized later at any time).

sshfs backup-host:/path/to/backup/directory /mnt/backup-host
truncate -s 50G /mnt/backup-host/backup-file.luks

Now encrypt it as usual with LUKS by using cryptsetup, add any options you like, e.g. key files.

cryptsetup luksFormat backup-file.luks

Then we need to create a filesystem on the encrypted partition.

cryptsetup luksOpen /mnt/backup-host/backup-file.luks backup-partition
mkfs.ext4 -m0 /dev/mapper/backup-partition

That concludes the setup.

Backup

Mount the remote backup (here using a key file).

sshfs backup-host:/path/to/backup/directory /mnt/backup-host
cryptsetup luksOpen /mnt/backup-host/backup-file.luks backup-partition --key-file /root/luks/backup.key
mount /dev/mapper/backup-partition /mnt/remote-backup

lsblk should now look sometimes like this.

...
loop0                     7:0    0   100G  0 loop
└─backup-partition      254:4    0   100G  0 crypt /mnt/remote-backup

Now perform the backup as usual like any other “local” backup, for example with rsync.

After everything is done unmount the file system:

umount /mnt/remote-backup
cryptsetup luksClose backup-partition
fusermount -u /mnt/backup-host

Resize

To increase the backup image use truncate and resize2fs.

truncate -s 200G /mnt/backup-host/backup-file.luks

Decrypt and mount the partition as described above. Then resize it.

resize2fs /dev/mapper/backup-partition

TRIM/Discard

One remaining issue with this setup is that the sparse file on the remote host doesn’t shrink when files are deleted. SSHFS doesn’t support TRIM (limitation of the SFTP protocol) but nbd-server supports it.

The following setup explains how to use TRIM over LUKS and NBD.

Install NBD:

apt-get install nbd-server nbd-client

nbd-server's configuration isn’t straight-forward (e.g. you can’t specify the trim option globally), so here’s a mininaml configuration file:

[generic]
// ...
[default] // can be any name
exportname=/path/to/your/file
trim = true

Then run the NBD server on the remote host:

nbd-server -C /path/to/config

And connect from the local host:

nbd-client -N default -n $host $port /dev/nbd0

Then mount it as usual, however note the --allow-discards option which is required for TRIM:

cryptsetup luksOpen --allow-discards /dev/nbd0 backup-partition
mount /dev/mapper/backup-partition /mnt/remote-backup

Now you can finally TRIM deleted space:

fstrim -v /mnt/remote-backup

You don’t have to use NBD all the time and can use SSHFS for regular backups and only run TRIM once in a while; all files deleted in the meantime will be TRIMed.

Possible issues

If you’re starting sshfs as non-root user then running cryptsetup will fail as FUSE prevents root from entering the mounted file system (this is designed to prevent attacks which confuse or hang root processes). Either run sshfs as root or mount with sshfs -o allow_root (this requires enabling user_allow_other in /etc/fuse.conf which might have security implications).

back

Last updated 2017-03-27 02:24:07 CEST