Documenting my Arch Linux encryption setup, for when I inevitably have to set it up again :P
I’ve gotten into the habit of doing a full clean-install of my system roughly every year or so. For the last three years, that choice has always been Arch, and I don’t see myself switching to anything else soon.
Each time, I find myself having to remember the exact process of setting up my device the way I want it. I guess this blog entry can serve as notes for my future self. I’ve decided to make them public regardless, in case anyone else finds them useful .
I want a LUKS-encrypted, clean root partition. Additionally, I want to mount another LUKS-encrypted partition using the same password as the root partition. On boot, both partitions must be unlocked by entering the password only once.
I use systemd-boot. Being the noob that I am, I will rely on archinstall
for most of the installation.
In short, our setup will look something like this:
× — nvme
| |— /boot Partition FAT32
| \— / Partition LUKS(BTRFS)
|
\ — hdd
\— /media Partition LUKS(BTRFS)
I use the Arch Linux ISO and “burn” it onto a USB stick with the help of Balena Etcher (AUR / GitHub), then boot into it.
After changing the keyboard locale to German (loadkeys de
), I start up archinstall
.
I use best-effort partitioning for my NVME. This should create something like:
│ Name | Type | Filesystem | Path | Start | End | Size | Flags
----------------------------------------------------------------------------------------
| primary | fat32 | /dev/nvme0n1p1 | 2048 | 2099200 | 1 GB | Boot, ESP
| primary | crypto_LUKS | /dev/nvme0n1p2 | 2099200 | 3907027120 | 1 TB |
1 GB for the boot partition, and the rest for the LUKS-encrypted partition.
My HDD is already encrypted and contains data, so I don’t touch it during this process.
After the partitions are set up, find the Disk encryption entry below. Here, I use LUKS and set an encryption password—the same one I use for the HDD.
From here, select whatever you need in archinstall. For me, that’s a KDE Desktop Profile, Pipewire for the audio server, firefox
and neovim
as additional packages, and multilib
as an additional repo. Also, don’t forget to configure the network, as archinstall
no longer sets it up by default. Make sure to select the correct keyboard locale under Locales, especially if your decryption password contains special characters and you are not using the US keyboard layout.
Once archinstall
has done its magic, it’s time to add the additional hard drive.
To do this, I add the HDD’s LUKS partition to /etc/crypttab
and reference the mapped, decrypted BTRFS partition in /etc/fstab
.
The entry in /etc/crypttab
is… basic:
media UUID=${LUKS_UUID}
Here, ${LUKS_UUID}
is the UUID of the crypto_LUKS
partition, which you can find by running lsblk -f
. Make sure it is the UUID of the crypto_LUKS
partition, not the decrypted partition.
Once you enter the password (twice) during boot, you’ll have /dev/mapper/root
and /dev/mapper/media
, corresponding to the respective decrypted partitions.
To get the HDD to mount on boot, add it to /etc/fstab
.
You can retrieve the UUID of the decrypted partition by mounting it. Create the mount point (e.g. mkdir /media
), then run luksOpen $device $name
(e.g., luksOpen /dev/sda1 media
). After entering the password, it should appear at /dev/mapper/$name
.
Running lsblk -f
again should reveal the UUID.
In my case, /etc/fstab
contains the following entry for the additional partition:
# encrypted HDD
UUID=${BTRFS_UUID} /media btrfs defaults 0 0
${BTRFS_UUID}
is the UUID of the media
partition, which is the “child” of the crypto_LUKS
partition.
For reference, here’s the lsblk -f
output:
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 crypto_LUKS 1 ${LUKS_UUID}
│ └─media btrfs ${BTRFS_UUID} 2T 18% /media
... # etc
The default decryption time for LUKS-encrypted partitions configured with archinstall
tends to be on the longer side—around 6 to 10 seconds. Personally, I don’t want to wait that long.
If you’re okay with a slight compromise in security (quicker brute-forcing), you can replace the key set by archinstall
with a less “expensive” one.
I usually aim for a decryption time of around ~1 second.
Using the cryptsetup
utility, you can pass your desired duration (“iteration-time”) using the -i
or --iter-time
parameter in milliseconds.
First, run a benchmark to determine how many iterations are needed to achieve your desired decryption time (e.g., 1000 ms):
cryptsetup benchmark -i 1000
Then, examine the keyslots for your LUKS device:
cryptsetup luksDump $device
# $device is the LUKS partition (where FSTYPE is crypto_LUKS)
# In my case, /dev/nvme0n1p2
LUKS allows multiple keys, and any of these can be used to decrypt the partition. Under the hood, all keys decrypt to a “Master Key” used for the actual decryption. To shorten decryption time, you can add a new key in a separate keyslot and then delete the initial one.
archinstall
typically uses keyslot 0. So, when you run luksDump
, the output should look something like:
...
Keyslots:
# v--------------- Keyslot 0
0: luks2
Key: 512 bits
...
Add a new key into slot 1 (or any unoccupied slot) using:
# vvvvvvv-- tries for decryption time around 1000 ms
cryptsetup -i 1000 --key-slot 1 luksAddKey $device
Afterward, run luksDump
again, and you should see:
...
Keyslots:
# v--------------- Keyslot 0
0: luks2
Key: 512 bits
...
# v--------------- The newly added key
1: luks2
Key: 512 bits
...
Finally, remove the first key by running:
cryptsetup luksKillSlot $device 0
Afterward, luksDump
should display:
...
Keyslots:
# v--------------- The newly added key
1: luks2
Key: 512 bits
...
And that’s it! Decryption should now be faster.
sd-encrypt
Instead of encrypt
By default, even if you select systemd
as your boot system, archinstall
will use the encrypt
hook to decrypt your partition on startup.
This hook works fine if you’re only decrypting the root partition. However, it doesn’t handle additional decryption entries from /etc/crypttab
. I believe that sd-encrypt
manages decrypting non-root partitions.The result is that you have to enter your password twice: once for the root partition and once for the media partition.
The solution is to use the sd-encrypt
hook for decrypting the root partition. sd-encrypt
caches the password and reuses it to decrypt the media partition automatically.
To replace encrypt
with sd-encrypt
, modify the hook in the /etc/mkinitcpio.conf
file. Also, don’t forget to add the systemd hook. If you’re using a non-US keyboard layout, add sd-vconsole
before sd-encrypt
aswell.
In my case, the changes to the HOOKS
list look like this:
- HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
+ HOOKS=(base systemd udev autodetect microcode modconf kms keyboard keymap consolefont block sd-vconsole sd-encrypt filesystems fsck)
After making these changes, run mkinitcpio -P
. Do not forget to run this, or the following changes will result in an unbootable system!
If you see an error like add_systemd_unit: command not found
, you forgot to add the systemd
hook!
Finally, modify the systemd boot entry.
You should have a config file under /boot/loader/entries/YYYY-MM-DD_HH-mm-ss_linux.conf
.
In this file, replace the options
line as follows:
# Created by: archinstall
# Created on: 2024-10-04_22-40-41
title Arch Linux, btw (linux)
linux /vmlinuz-linux
initrd /initramfs-linux.img
# Replace cryptdevice=... with rd.luks.name=... and use DEVICE_ID instead of PARTUUID
+ options rd.luks.name=${DEVICE_ID}=root root=/dev/mapper/root zswap.enabled=0 rootflags=subvol=@ rw rootfstype=btrfs
- options cryptdevice=PARTUUID=${PREVIOUS_PART_ID}:root root=/dev/mapper/root zswap.enabled=0 rootflags=subvol=@ rw rootfstype=btrfs
${DEVICE_ID}
refers to the crypto_LUKS
device.
For reference, lsblk -f
should show something like this:
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
...
nvme0n1
├─nvme0n1p1 vfat FAT32 0000-0000 852.7M 17% /boot
└─nvme0n1p2 crypto_LUKS 2 11111111-1111-1111-1111-111111111111 <------- use this as DEVICE_ID
└─root btrfs 22222222-2222-2222-2222-222222222222 1.7T 4% /var/log
/home
/var/cache/pacman/pkg
/.snapshots
/
And that’s basically it!
You should now reboot. After entering your password, both partitions should be decrypted, and decryption should be considerably faster .