My laptop is set up as btrfs on a LUKS-encrypted partition. I bought a new M.2 drive, installed it on the extra slot… then wasted most of a day trying to make it work. Here’s a synopsis of why and what I did to resolve the problems. Hope it helps.

Setup

Lenovo Thinkpad P15v with two M.2 slots (only one in use). I bought it in November 2022, installed Gentoo on it, with this layout:

NAME        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
nvme0n1     259:1    0 953.9G  0 disk
.....
├─nvme0n1p4 259:12   0     1G  0 part  /boot
├─nvme0n1p5 259:13   0   900M  0 part  /sysrescue
└─nvme0n1p6 259:14   0 887.7G  0 part
  └─root    254:1    0 887.7G  0 crypt /home
                                       /snapshots
                                       /.swap
                                       /

That is: nvme0..p6 is LUKS, decrypted at boot time, with a btrfs filesystem on top of that.

I bought and installed a new M.2 drive, partitioned it similarly (with an identical-size p6), ran luksFormat on it, then came to a screeching halt because:

Problem

There’s no way to tell genkernel that it needs to unlock more than one LUKS device bz694778. That means you can’t do btrfs RAID on LUKS, because the RAID will come up with only one volume.

Also, I want to enter my LUKS passphrase once, not once for each partition.

Solution

The solution requires two parts:

  1. Patches to genkernel
  2. Learning keyctl

1. Patching genkernel

David Sardari maintains a set of patches for genkernel that allow unlocking multiple root and swap devices. Read the docs, install patches 00 and 01, re-emerge genkernel.

(Life is volatile. It’s possible that David’s patches will not apply to the version of genkernel you’re installing. Fixing that is left as an exercise for the reader).

Now edit /etc/default/grub, pluralizing crypt_root and adding your new partition:

-GRUB_CMDLINE_LINUX="crypt_root=/dev/nvme0n1p6 root=LABEL=t ..."
+GRUB_CMDLINE_LINUX="crypt_roots=/dev/nvme0n1p6 crypt_roots=/dev/nvme1n1p6 root=LABEL=t ..."

2. Learning keyctl

This requires genkernel 4.3.2 or greater.

Edit /etc/genkernel.conf, find the KEYCTL= line, and set it to "yes".

Make up a name for your new keyctl token (replace “potrzebie” below) and run the following magic commands:

# cryptsetup token add --key-description potrzebie /dev/nvme0n1p6
# cryptsetup token add --key-description potrzebie /dev/nvme1n1p6

Edit /etc/default/grub again and add one more entry to the cmdline:

-GRUB_CMDLINE_LINUX="...root=LABEL=t ..."
+GRUB_CMDLINE_LINUX="...root=LABEL=t keyctl_keydesc=potrzebie ..."

That’s it. You can now run genkernel ramdisk and whatever scripts you use for updating /boot/grub/grub.cfg, and reboot. On boot, the password prompt will be different:

- Enter passphrase for /dev/nvme0n1p6:
+ Please type the key 'potrzebie' for the user keyring then press Ctrl-D twice:

(DO NOT press Enter! Just type your passphrase, then ^D twice)

If all has gone well, that’s the last prompt you get. When you log in as root, run ls -l /dev/mapper and you’ll see the new disk as root_1.

If you mistype, just Ctrl-Alt-Del to reboot. There’s no retry mechanism.

See genkernel(8) (search for “keyctl”) and cryptsetup(8) (search for “token.*add”) for further info.

Enabling btrfs RAID

Once you’re super-comfy with the boot process, and you’re certain that all LUKS partitions will be unlocked safely before btrfs is activated, add the new partition as a RAID volume:

# btrfs device add /dev/nvme1n1p6 /
# btrfs balance start -dconvert=raid1 -mconvert=raid1 /

Moving further

Get rid of swapfile-on-btrfs. I was doing that solely because of the multiple-passphrase-prompts issue. Now I can use an actual encrypted swap partition. (Be sure to do the cryptsetup-token thing on it).