Encrypted disk on RPi 4 Model B

Note: This guide is for RPi 4 Model B, Raspberry Pi OS (Raspbian) and external disk drive (no SD card used, except for /boot). Kernel used is v7l+.

I like to encrypt all the devices I own, except for servers which can be troublesome to decrypt it... Anyway, here is a memory guide on how I configured encryption on an external disk for a RPi 4 B and boot on it.

Install required packages

# apt install busybox cryptsetup initramfs-tools lvm2

Prepare configuration

# cat <<EOF > /etc/kernel/postinst.d/mkinitramfs
#!/bin/sh -e
version=\$1
if ! (echo "\$version" | grep -q "v7l+"); then exit 0; fi
mkinitramfs -o /boot/initramfs.gz "\$1"
EOF
chmod +x /etc/kernel/postinst.d/mkinitramfs

Encrypt the disk and copy filesystem

On a freshly written SD card Raspberry Pi image.

# cryptsetup luksFormat /dev/sda
# cryptsetup open /dev/sda crypted
# pvcreate /dev/mapper/crypted
# vgcreate /dev/mapper/crypted vg0
# lvcreate -nrootfs -L30G vg0
# lvcreate -nhome -L100G vg0
# mount /dev/vg0/home /mnt/
# rsync -avh --progress /home/ /mnt/
# mount /dev/vg0/rootfs /mnt
# rsync -avh --progress --exclude="{/proc/**, /sys/**, /dev/**, /tmp/**, /home/** , /mnt}" / /mnt/

Note: I don't delete sources files on the SD card, as it can be useful to boot on the SD card later, for a rescue mode.

Configure fstab and crypttab

/dev/mapper/vg0-rootfs  /               ext4    defaults,noatime  0       1
/dev/mapper/vg0-home  /home               ext4    defaults,noatime  0       1
crypted	/dev/sda	none	luks

Prepare an initramfs image

The RPi bootloader directly access the kernel image on the SD card, partition /boot and don't need an initramfs like traditional machines. But, as we want to decrypt and mount LVM volumes we need an image which contains the required tools.

# mkinitramfs -o /boot/initramfs.gz

Check that the image has cryptsetup and LVM tools:

# lsinitramfs /boot/initramfs.gz | grep -e cryptsetup -e lvm

Note: It may fail to detect root device, in this case at next reboot you will have to manually luksOpen and vgchange -ay in busybox to be able to boot correctly. After that “manual” boot, you can redo mkinitramfs and it should works.

Final steps with RPi bootloader

initramfs initramfs.gz followkernel
root=/dev/mapper/vg0-rootfs cryptdevice=/dev/sda:crypted

Also, remove quiet or splash to see the boot process and to be able to have a prompt asking for your LUKS password.

And you're done!

Main source: robpol86.com website.