Ín this article I will explain how to use LUKS to encrypt an external drive. I will also explain how to mount the encrypted volume with some shell scripting.
A word of warning: I am no LUKS and no security expert! Neither am I an expert in shell scripting. Please review everything carefully and double check with other sources such as the Arch wiki Any potential data loss or theft as a result of following this article is your fault alone. I used commands from the arch wiki and ummit.dev
First note that setting up encryption on a partition will erase everything present before, so you might want to backup existing data on the drive.
You may also securely erase the drive before continuing.
First we need to find the external drive for example with:
lsblk -f
Lets say for the article the external drive is /dev/sdc, we will encrypt one partion /dec/sdc1.
Partition the drive
sudo fdisk /dev/sdc # Press "d" to delete all existing partitions # press "n" to create a new partition, use the default values (The whole device will be one large partition) # press "t" to change the type of the partition you just created to "Linux", it was "83" for me
Now we can encrypt the drive. You will be prompted for a passphrase. Choose something appropriately secure and memorize it or store it in your password manager of choice.
sudo cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --hash sha256 --iter-time 10000 --key-size 256 --pbkdf argon2id --use-urandom --verify-passphrase /dev/sdc1
During the encryption setup you might sometimes need the following two commands. I don't know enough about Linux to explain why. Once you completed the initial setup you won't need those anymore
sudo sync sudo partprobe /dev/sdc
We have created an encrypted partition. Normally you can simply mount the partition we created earlier. With LUKS we have one more step. Basically the encrypted partition is a wrapper around your actual partition with the actual data.
First we open the partition. This will prompt us for the password.
sudo cryptsetup open /dev/sdc1/ extdrive # This will create the following link: `/dev/mapper/extdrive`
Running lsblk should show something like this now:
> lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS .... sdc 8:32 0 1,8T 0 disk └─sdc1 8:33 0 1,8T 0 part └─extdrive 253:0 0 1,8T 0 crypt
Now we format the mapped partition like any other partition. For example like this
sudo mkfs.ext4 /dev/mapper/extdrive
Now the initial steps are done.
Depending on your desktop manager you won't even have to do the following manual mounting stuff. For me "Cinnamon" is able to automatically mount this drive like any other external usb device.
To actually use the partition we need to mount it:
sudo mount --mkdir /dev/mapper/extdrive /mnt/exthd # Make sure your preferred users can access the directory sudo chown <youruser>:<yourgroup> /mnt/exthd
You can write and read data like your are used to now. To disconnect and encrypt the device you need to run the following. Always unmount and close the partition and device before unplugging to avoid data corruption.
sudo umount /mnt/exthd sudo cryptsetup close extdrive
And to decrypt/open the device again you need:
sudo cryptsetup open /dev/sdc1 extdrive sudo mount --mkdir /dev/mapper/extdrive /mnt/exthd
The problem with external drives is that they are not always found in the same location, for example /dev/sdc1.
To always mount and decrypt the "right" device I wrote a simple script to mount a device via its serial number.
This script also uses the "secret service" functionality to automatically query the passphrase from your password manager/keyring of choice. For example gnome-keyring or keepassxc.
The script takes three positional parameters, you can also provide no parameters and edit the default values.
You can find the serial number of a device by running lsblk -o name,serial
For example in the following example the serial number would be "1234567890".
> lsblk -o name,serial NAME SERIAL ... sdc 1234567890 └─sdc1 └─extdrive
Here is the complete script:
#!/usr/bin/sh
mountpoint= $1 || '/mnt/exthd'
backupSerial= $2 || "213e8094312"
mapperName= $3 || "extdrive"
# check if exthd is mounted
df -h | awk '{print $6}' | grep -q "$mountpoint"
mountPointPresent=$?
set -e
if [ $mountPointPresent -ne 0 ]; then
echo "external drive not mounted on $mountpoint mounting..."
foundDevice=$(lsblk -o name,serial | awk "{if (\$2 == \"$backupSerial\") {print \$1}}")
if test "$foundDevice"; then
lsblk
echo "Device $foundDevice matches serial $backupSerial, please confirm device (type y)"
read -r confirmation
if [ "$confirmation" != "y" ] && [ "$confirmation" != "Y" ]; then
echo "aborting"
exit 2
fi
echo "Will now decrypt and mount $foundDevice"1
else
echo "No device found matching $backupSerial"
exit 1
fi
# For details on how to store and query the correct passphrase
# check out the documentation of your password management tool of choice
secret-tool lookup service exthd | sudo cryptsetup open "/dev/$foundDevice"1 $mapperName
sudo mount --mkdir "/dev/mapper/$mapperName" $mountpoint
else
echo "$mountpoint Already mounted"
exit 1
fi
What would be nice is if the device got automatically mounted when it is connected. Maybe one can write a udev rule to execute the script? I will update the article once I figure that out. So far I haven't been able to get it to work, but maybe something like this would be necessary:
echo ## KERNEL=="sd[a-z]", ATTRS{vendor}=="TOSHIBA",ATTRS{serial}=="<SERIAL>", RUN+="/usr/local/bin/mountExthd.sh"' > /etc/udev/rules.d/20-mount-encrypted-drive