Backup on LUKS-encrypted external HDD
One of my strategies to prevent important (electronic-form) information from becoming too ephemeral… #backups #rsync #luks #usb #drive [Source code]
The goal of this text is to share with you a simple strategy to backup your important data to an encrypted external drive. (LUKS, which stands for Linux Unified Key Setup, is the disk encryption framework that we will use to encrypt the external drive.)
Scenario. More specifically, the goal is to create a backup of a set of locations—say, /home/<user>/folder1
, /home/<user>/folder_2
, etc.—where <user>
is your username. The bash
script I will provide also gives you the possibility of quickly restoring that external backup onto your computer—on which more later.
Prerequisites. An external hard drive, of course, and in addition, a machine with a Linux installation that isn’t ancient. As already hinted above, the bash
shell is required, and furthermore, the cryptsetup
package is also a requirement (this is what we’ll actually use to create and manage the LUKS encrypted volume). Finally, the user which will do the backups must have sudo
privileges.
To avoid the perilous path of partioning, I shall assume that your entire external drive is to be formatted as a LUKS container. This, of course, needn’t be so: it is perfectly feasible to create multiple partions in said external drive, and use just one of them as a LUKS container for your backups. But I am afraid that you must look elsewhere for instructions on how to do that.1
Hereinafter, I shall assume that your external drive is /dev/sdb
—modify as required for your own system. The first step, as I said, is to turn your whole drive into a LUKS container. But before that, there is an
IMPORTANT CAVEAT: if your drive has some previous data in it, setting it up as a LUKS container will render any such data inaccessible. But, just to make matters worse, it might not actually delete said pre-existing data. So, on the one hand, please backup any previous data that you want to keep. On the other hand, do not assume that the format process will wipe the drive of its previous contents.2
Setup. LUKS encryption can be done either using a passphrase, or a key file—here we are going for the latter. The key file it self can be anything really—an image, a PDF file, etc.—but here, we are going for a randomly generated hunk of bits (note that this has to be done as root
):
# dd bs=512 count=4 if=/dev/random of=/path/to/keyfile iflag=fullblock
Needless to say, anyone who gets access to this file (keyfile
), can trivially decrypt the LUKS container to be created—so be sure to keep it safe!! It is already owned by root
, but just for good measure, I also make sure that only root
can read it:3
# chmod 400 /path/to/keyfile
Now, to format the drive as a LUKS container, do:
# cryptsetup luksFormat /dev/sdb /path/to/keyfile
Now we have to open the encrypted volume we just created, and format that with an actual file system. Here I will use ext4
, even despite its annoying lost+found
folder.4
# cryptsetup --key-file=/path/to/file open /dev/sdb backupdev
This creates a new (“virtual”) device under /dev/mapper
, more specifically /dev/mapper/backupdev
. To dump an ext4
file system on it:
# mkfs.ext4 /dev/mapper/backupdev
And now mount it:
# mount /dev/mapper/backupdev /mnt
By default, the owner of your new partion will be root
—which will mean that any copying of files therein must also be done as root
. To avoid this, change its owner to you:5
# chown -R <user> /mnt
Moving on, you can choose to store the backup data directly into the root of your drive (i.e., its top folder), but I prefer to create a specific folder, and name it something like <USER>-BACKUP
. Then, all of your backup data will be inside that folder. This leaves you free to, for example, use any remaining space on your drive to store other things. It is done like so:
# mkdir /mnt/<USER>-BACKUP
The setup of the external drive is done! All that is left is to unmount it, close the encrypted container—and then proceed to setup the bash
script. (Note that below, umount
is not a typo—the command really is named like that…)
# umount /mnt
# cryptsetup close backupdev
OK, onto the script! The code is fairly simple (see source code link above)—save it into a file with the .sh
extension (below I will use backup_script.sh
).6 There are variables to set up (they are at the top of the file):
ext_luks_dev
: the UUID of the device. This done because the name of a device (/dev/sdb
,/dev/sdc
, etc.) can vary, depending on, for instance, the USB port onto which it is attached—and hence, it should not be hardcoded. UUIDs, in contrast, are unique. To retrieve it, do (asroot
or not, no matter):lsblk -o +UUID
.ext_luks_key
: the path to thekeyfile
created above.ext_mount_point
: the mount point on which the decrypted LUKS volume (above it was/dev/mapper/backupdev
) should be mounted (above we used/mnt
, and indeed, this can be a fine choice).ext_root_backup_folder
: what I above named<USER>-BACKUP
—but give it any name you want, or no name at all. (But if you give it another name, keep in mind you will have to modify accordingly themkdir
command used above.)loc
: last, but surely not least, the locations to back up. They must be absolute paths. Take the exampleloc=+(...)
lines, modify them to suit your needs—and if needed, add any extra such lines, as required by the number of locations that you want to include in the backup.
Usage. Just run the script:7
$ sh /path/to/backup_script.sh
Without any arguments, as shown above, it creates/syncs a backup. With -r
, it restores the data in the backup to its original location—but without overwriting files that, while present in the backup, have been modified (in the original location) after the backup was done. I.e., restoring a backup preserves files that are newer than the version that exists in the backup.8
In either case, adding the -y
option does a --dry-run
(i.e., a simulation) of the task that would have been done, if the -y
had not been given. (So giving -y
alone simulates a backup; giving -y -r
—the order does not matter—simulates restoring a backup.)
March 8, 2022.
The Arch Wiki might be a good place to start digging for information on partioning drives.↩︎
This is actually a fairly complex issue, that I cannot hope to cover adequately here. An elucidating read on the some of the problems, might be
cryptsetup
’s own FAQ, specifically question 5.19.↩︎There is no need to ever write to this file, so writing permissions make no sense (to give the owner writing permissions, we would use
600
instead of400
; cf.man chmod
). Furtermore,root
permissions are needed to mount the encrypted volume, so making this file readable byroot
only, should cause no problem.↩︎The
ext4
file system uses alost+found
folder, that it creates on the root of the device, to store information that might help to repair the file system, if it becomes corrupted, or whatever. Which is all nice and well, except that, for the life of me, I cannot understand why the designers did chose to store said information… in a hidden folder! Anyway, as this is a backup device, you can probably just delete the folder (rm -rf lost+found
) and move on… (it will be recreated only when and if you run thefsck
file system repair program on the drive). Or just use any other file system…↩︎If you subsequently mount the drive again, the contents will still be owned by you, i.e., this change is permanent. So this
chown
thing needs to be done only once.↩︎I don’t expect to modify this script very much (it at all), so I store it in a static fashion, rather than placing it on github, say.↩︎
This assumes that the
sh
command points to thebash
shell, as is now customary. If this not the case, either run the script replacingsh
with/bin/bash
, or make the script executable ($ chmod u+x /path/to/backup_script.sh
) and then run it like this:
↩︎$ ./path/to/backup_script.sh
This is useful in the following kind of scenarios: say you back up your entire home directory, and then one day—some time after you last updated your backup—you accidentally delete a couple of family vacation photos. No sweat: just run this script with
-r
, and presto: the deleted photos are restored, but any files on which you have worked—and thus modified—after the last backup are left undisturbed.↩︎