This describes my setup for using DigitalOcean Volumes (disk images attached to my VPS) for off-site backups and keeping them encrypted-at-rest when I'm not actively writing or reading to the disk image.
Basically it consists of:
- A DigitalOcean virtual private server.
- An extra Volume attached to the VPS (100GB or so), this presents itself as a block storage device in Linux.
- LUKS encrypted partition on the Volume.
- A few shell scripts to mount, rsync, and unmount the volume.
These steps are only done in the beginning to initially format and set up the encrypted disk partition.
Install cryptsetup: sudo apt install cryptsetup
or
sudo dnf install cryptsetup-luks
for Debian or Fedora.
Create a partition table and a partition on the disk you're using (i.e. so that /dev/sda is the hard disk and /dev/sda1 is the first partition on it). Filesystem on the partition doesn't matter because it's going to be overwritten anyway.
Format the partition for LUKS encryption:
cryptsetup -y -v luksFormat /dev/sda1
Open the LUKS volume and give it a mapper name ("backup" in this example):
cryptsetup luksOpen /dev/sda1 backup
This creates the device node /dev/mapper/backup
which represents the
decrypted partition, so you can create a filesystem on it and mount it:
# Create an ext4 filesystem in the LUKS volume.
mkfs.ext4 /dev/mapper/backup
# Mount it.
mkdir -p /mnt/backup
mount /dev/mapper/backup /mnt/backup
To unmount and close the encrypted volume for data security at rest:
# Unmount
umount /mnt/backup
# Lock the encrypted partition.
cryptsetup luksClose backup
To manually decrypt and mount, and unmount and lock again, the commands would be as follows:
# Decrypt and mount
cryptsetup luksOpen /dev/sda1 backup
mount /dev/mapper/backup /mnt/backup
# Unmount and lock
umount /mnt/backup
cryptsetup luksClose backup
Putting it all together, I wrote a few shell scripts to automate the backup process as much as possible.
From my client device I just run a shell script, enter my LUKS disk encryption password, and it rsync's over and locks the disk when done.
/root/luks-mount.sh to decrypt and mount the filesystem:
#!/bin/bash
if [[ -f "/mnt/backup/mounted.txt" ]]; then
echo LUKS disk is already mounted.
exit 0
fi
cryptsetup luksOpen /dev/sda1 backup
mount /dev/mapper/backup /mnt/backup
df -H
NOTE: I created an empty file "mounted.txt" in the filesystem to easily check whether the disk is mounted or not. The above shell script checks its existence before attempting to unlock the disk.
/root/luks-umount.sh to lock the disk back down:
#!/bin/bash
if [[ ! -f "/mnt/backup/mounted.txt" ]]; then
echo LUKS disk is already unmounted.
exit 0
fi
umount /mnt/backup
cryptsetup luksClose backup
This is the one I actually run when I need to sync my backups to my remote server.
Note: set up SSH key based authentication to make it easier. When you run the backup script you're only prompted to enter the LUKS disk password and the rest of the script is automatic.
#!/bin/bash
# Exit on first error.
set -e
# Mount the remote LUKS volume.
echo Mounting remote crypto-backup LUKS volume on example.com...
ssh -t [email protected] './luks-mount.sh'
# Rsync your stuff over.
echo Copying backups over...
rsync -av /mnt/Midnight/Images/Organized/ example.com:/mnt/crypto-backup/Photos/
# Lock the disk when finished for encryption at rest.
echo Unmounting remote LUKS volume
ssh -t [email protected] './luks-umount.sh'