This is an n+1 th guide on setting up a Raspberry Pi to boot on an encrypted external disk, to complement n other guides, including:
- https://rr-developer.github.io/LUKS-on-Raspberry-Pi/
- https://askubuntu.com/a/1296450
- https://github.com/ViRb3/pi-encrypted-boot-ssh
Enabling boot on USB
Either use the official Raspberry Pi Imager utility or do
# echo "program_usb_boot_mode=1" >> /boot/config.txt
on an existing installation, and reboot.
Installing cryptsetup on the disk image
Get a disk image of Raspberry Pi OS on https://www.raspberrypi.com/software/operating-systems. The Lite version will also work fine.
Restore it on the destination disk, and boot the Pi.
Install cryptsetup, which is not present in the original image:
# apt install cryptsetup cryptsetup-initramfs
# shutdown -h now
Encrypting the volume
In the previous step, the root partition got expanded to the size of the disk by the installer. We have to undo that to avoid spending a day encrypting a large mostly empty partition.
This is most easily done with gparted and its very good support for encrypted volumes.
Once the partition is resized, encrypt it, replacing sdb2 by the name of the root partition you just resized:
# lsblk -f # Note the partition name and its UUID
# cryptsetup-reencrypt --new --reduce-device-size=16M --type=luks2 \
-c xchacha12,aes-adiantum-plain64 -s 256 -h sha512 --use-urandom /dev/sdb2
This should take roughly 30 minutes.
After that, you can expand again the now-encrypted partition with gparted.
Configuring crypttab and fstab
With the partition mounted, set /etc/crypttab to
rootfs UUID=XXX none
replacing XXX by the UUID of the encrypted root partition (with FSTYPE equal to crypto_LU).
Change the /etc/fstab line about the rootfs partition to
/dev/mapper/rootfs / ext4 defaults,noatime 0 0
On the boot partition, add the following to the kernel parameters in cmdline.txt:
cryptdevice=UUID=XXX:rootfs
replacing again XXX by the partition UUID above.
Unattended decrypt with key on an external device (optional)
The following step is optional; it allows reading the decryption key from an external medium (USB key, SD card) rather than using an interactive prompt.
Mount your external medium, label the partition, generate a key, and add it to the encrypted partition
# sudo e2label /dev/sdc2 sd # Label the device
# dd if=/dev/urandom of=/mnt/sd/key bs=4096 count=1
# cryptsetup luksAddKey /dev/sb2 /mnt/sd/key
replacing sdc2 by the partition name of your external medium.
To your cmdline.txt, add
cryptkey=/dev/disk/by-label/sd:ext4:/key
At boot, the partition will automatically be mounted to read the key. If this fails, decrypting the root partition will fallback to a prompt.
Boot and update initramfs
Finally, boot again the Pi with the disk attached.
On this first boot, decrypting the volume will fail and an initramfs prompt will be open (possibly after a minute or so of retries). Open the volume manually:
# lsblk # Note partition name
# cryptsetup luksOpen /dev/sba2 rootfs
# exit
This should allow booting normally, after which you can execute
# update-initramfs -u
The next reboot should then work properly, with or without password prompt depending on whether you followed the optional step.