Encrypting an external device with LUKS
13 April 2026
I, like many other folks out there, use a small USB drive to store personal documents and other files. It works as a useful backup in case my system fails or gets stolen. However, since I am always traveling this has always made me nervous, because it is too easy to lose a drive the size of a coin.
As I only ever plug it into a Linux machine (I
already keep it formatted as ext4), it
seems sensible to encrypt it with LUKS. Also, it is
annoying to write a new password all the time, so —
since my threat model considers my laptop to be safe and
only accessible by me — let’s also setup the device to
auto decrypt whenever plugged on it.
Important: Throughout this post, we
will use the dummy /dev/sdX to refer to the
device descriptor. Make sure to check right name for
your setup. Also, guarantee that the device is
unmounted, specially if you use an automount daemon like
udiskie.
Wipe It Out
First of all let’s substitute everything This step is optional, but useful if you are already storing something in the device.
Make sure the device is unmount and let’s shred it.
sudo shred -v -n 1 /dev/sdXYou can also use dd to write from
/dev/urandom if you prefer. Check the Arch
Wiki for possible methods of wiping a disk.
Encrypt Drive
If you didn’t follow the previous step, do keep in mind that this one is not optional and it will delete everything in the drive. Backup accordingly.
We are using the Linux kernel’s support for full-disk
encryption via dm-crypt. We users interact
with it using the cryptsetup command. Let’s
use it to format the whole drive using LUKS2 headers1.
sudo cryptsetup luksFormat /dev/sdX --type luks2 --label driveYou will be prompted for a password when running this
command. For now, this is the only way to access the
data in this device. Make sure to remember it. Also, the
label drive can be anything you want.
Now let’s open the drive and assign a name to it.
sudo cryptsetup open --type luks2 /dev/sdX drive-nameIt will prompt you for the password and map the
decrypted device to
/dev/mapper/drive-name.
I am going to format it with as ext4
because it is fast, stable, and the encryption scheme
already only works on Linux. But VFAT or almost any
other should work well enough.
sudo mkfs.ext4 /dev/mapper/drive-nameNow your drive is ready to use! You can close and remove it if you want.
sudo cryptsetup close drive-nameWhenever you want to use it, you will have to first “open” the drive (decrypt) and only then mount its partition. Notice that the mapped name can be anything you want.
sudo cryptsetup open --type luks2 /dev/sdX usb
sudo mkdir -p /media/usb
sudo mount /dev/mapper/usb /media/usbAuto-Opening and Mounting
This whole opening and closing, mounting and unmounting dance can get tiresome pretty quickly. If you trust a machine, you can let it decrypt your USB drive automatically.
Keyfile
Till now, our device only opens with a password.
Let’s allow it to also be opened using a
keyfile. This can be any file you want:
random bytes, a giant riddle written in a txt, your
dog’s picture, etc. For the sake of simplicity and
entropy, we are going with 4kB of
randomness. For good measure, also only allow your user
to see and edit the file.
dd if=/dev/urandom of=/path/to/keyfile bs=1024 count=4
chown "$USER":"$USER" /path/to/keyfile
chmod 600 /path/to/keyfileRemember that /path/to/keyfile must be
somewhere safe, or it defeats the whole purpose. If you
have an encrypted home folder, you can keep it as a
dotfile in there, for example.
Allow the keyfile to open your device.
sudo cryptsetup luksAddKey /dev/sdX /path/to/keyfileYou can verify that it worked by checking that there are two keyslots in the output of (one for the password, and another for the keyfile)
sudo cryptsetup luksDump /dev/sdXNow you can open without a password!
sudo cryptsetup open --type luks2 --key-file /path/to/keyfile /dev/sdb usbAutomount with
udiskie
If you have an automount setup, it is necessary to instruct it on where to find the keyfile.
I will show it for udiskie because that is what I use and because I don’t want to mount the drive at boot, but at user level2 I imagine it is similar for any other setup though.
Start by checking the device’s UUID,
lsblk -ndo UUID /dev/sdXAnd proceed to create or edit
$HOME/.config/udiskie/config.yml to link
this UUID to the keyfile. You must write a section like
this:
device_config:
- id_uuid: <DEVICE UUID>
keyfile: /path/to/keyfileKeep in mind that the keyfile must be readable by the
user running udiskie.
Conclusion
After spending some time searching for encryption solutions, I ended up with this one, which leaves most of the magic to the Linux kernel itself.
Below is a small proof-of-concept script automating the whole process. Make sure to edit it when adapting to your workflow.
See full script
#!/bin/sh
# Use this script by passing the device name
# and an optional keyfile name.
# usb-encrypt "/dev/sdX" "/path/to/keyfile"
DEVICE=$1
KEYFILE=$2
NAME=$(uuidgen)
# Wipe the drive
sudo shred -v -n 1 "$DEVICE"
# Encrypt and format
sudo cryptsetup luksFormat --type luks2 --label drive "$DEVICE"
sudo cryptsetup open --type luks2 "$DEVICE" "$NAME"
sudo mkfs.ext4 "/dev/mapper/$NAME"
# Create and assign keyfile
if [ -n "$KEYFILE" ] ; then
dd if=/dev/urandom of="$KEYFILE" bs=1024 count=4
sudo cryptsetup luksAddKey "$DEVICE" "$KEYFILE"
chown "$USER":"$USER" "$KEYFILE"
chmod 600 "$KEYFILE"
# Configure udiskie if the executable exists
if command -v udiskie >/dev/null 2>&1 ; then
UUID="$(lsblk -dno UUID "$DEVICE")"
cat >> "${XDG_CONFIG_HOME:-$HOME/.config}/udiskie/config.yml" <<EOF
device_config:
- id_uuid: $UUID
keyfile: $KEYFILE
EOF
fi
fi
sudo cryptsetup close "$NAME"