Backup on LUKS-encrypted external HDD
One of my strategies to prevent important (electronic-form) information from becoming too ephemeral… [Script] [Config] [Update history]
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: it consists of the script proper, and its configuration file. Save the former into a file with the .sh
extension (below I will use backup_script.sh
), and the latter in file $HOME/.config/ext_luks_bck/config.sh
.6
On the config file, there are the following variables to set up:
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_desc
: the description of the current configuration file. Unused by the script, this is to help the user not get confused, in the scenario where he uses the current script in several computers, and/or has several backup devices. If you use only one computer and one backup drive, you can safely ignore this.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.)locations
: the locations to back up. They must be absolute paths. Take the examplelocations=+(...)
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.excludes
: last, but surely not least, the locations to exclude from the back up. It is optional, but if you need it, take the exampleexcludes=+(...)
lines, and modify them to suit your needs.
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. Got feedback? See the contact page.
* * *
Update history
March 21, 2024. Script can now be used with a user-specified config file $ sh /path/to/backup_script.sh -f /path/to/custom/config/file.sh
. I also added the ability to exclude certain files or folders from being backed up; cf. the new config template.
August 31, 2023. The script now outputs messages to inform the user when the LUKS volume has been successfully mounted/unmounted. Moreover, two new options: -m
mounts the LUKS volume, and nothing else; and -u
unmounts the LUKS volume, and nothing else. Also, the configuration variables have been placed in a separate file, to ease setting them up.