How to install and unlock your encrypted Debian root with a keyfile
Introduction
A common method for securing the root partition of a system is through encryption using a passphrase. While effective, this approach requires manual input every time the machine starts, which poses a challenge for headless machines that lack a keyboard or screen.
To address this, we can store the keyfile on a USB key, allowing the system to automatically access the encryption key during boot. Alternatively, the keyfile can be stored on the network, providing a convenient solution for multiple machines, but we will see that one day, maybe.
In this blog post we will install Debian 13 using debootstrap without setting up a passphrase. Although we could run the installer, which supports LUKS encryption with a passphrase, and add the keyfile later, where would be the fun?
Debian Installation
First, grab (a tea and) a live version of Debian, install it on a usb key (it's 2025, who still burns Linux distributions to CDs?), boot on it, and open a terminal.
We need to install a few packages:
sudo apt update
sudo apt install debootstrap arch-install-scripts
Let's assume you have the following setup:
sda
is the disk where we are going to install the system (with its partitions being efi, boot and root, in that order);sdb
is the live usb key;sdc
is the usb key where we will install the keyfile.
NAME SIZE RO TYPE UUID
sda 1T 0 disk
├─sda1 1G 0 part 00a1
├─sda2 1G 0 part 00a2
└─sda3 958G 0 part 00a3
sdb 7.6G 0 disk
├─sdb1 3.5G 0 part
└─sdb2 3.2M 0 part
sdc 8G 0 disk
├─sdc1 8G 0 part 00c1
We will start with creating a 64B keyfile. You can adjust the command to your liking, e.g., if you want a larger key, or if you want it to contain text, an image, etc.:
mkdir /tmp/usbkey
sudo mount /dev/sdc1 /tmp/usbkey
dd if=/dev/urandom of=/tmp/usbkey/luks-keyfile bs=1 count=64
We can now create our new filesystem:
sudo mkfs.vfat -F32 /dev/sda1
sudo mkfs.ext4 /dev/sda2
sudo cryptsetup luksFormat /dev/sda3 --key-file /tmp/usbkey/luks-keyfile
sudo cryptsetup open /dev/sda3 cryptroot --key-file /tmp/usbkey/luks-keyfile
sudo mkfs.ext4 /dev/mapper/cryptroot
sudo umount /tmp/usbkey
And mount it:
sudo mount /dev/mapper/cryptroot /mnt
sudo mkdir /mnt/boot
sudo mount /dev/sda2 /mnt/boot
sudo mkdir /mnt/boot/efi
sudo mount /dev/sda1 /mnt/boot/efi
And install a basic Debian system:
sudo debootstrap stable /mnt http://deb.debian.org/debian
Let's also generate a few files (if the usb key with the keyfile is still plugged in, you might want to remove it from /mnt/etc/fstab
):
sudo bash -c 'genfstab -U /mnt > /mnt/etc/fstab'
chroot
to the new system
To enter our new system:
sudo arch-chroot /mnt
arch-chroot
is provided by the arch-install-scripts
package installed earlier. It is a quicker and more convenient way to mount the required file systems needed in the chroot and then chroot.
New installation setup
Install a few necessary tools:
apt update
apt install neovim grub-efi openssh-server cryptsetup-initramfs \
linux-image-amd64 linux-headers-amd64 initramfs-tools efibootmgr locales
Configure a few necessary things:
# root password
passwd
# hostname
echo my-encrypted-host > /etc/hostname
sed -i 's/debian/my-encrypted-host/' /etc/hosts
# setting the time & locales
dpkg-reconfigure tzdata
dpkg-reconfigure locales
# setting up the network
cat << EOF > /etc/systemd/network/<interface-name>.network
[Match]
Name=<interface-name>
[Network]
DHCP=yes
EOF
You might also want to allow password authentication for root via ssh, just at the beginning for debug purposes:
nvim /etc/ssh/sshd_config
...
PermitRootLogin yes
...
We can now enable the services:
systemctl enable sshd
systemctl enable systemd-networkd
Encrypted root configuration
Add a new entry in /etc/crypttab
:
cryptroot /dev/sda3 /dev/disk/by-uuid/00c1:/luks-keyfile luks,discard,keyscript=/lib/cryptsetup/scripts/passdev
Also add a few modules in /etc/initramfs-tools/modules
ext4 # this is because our root partition uses ext4
nls_cp437
nls_ascii
Update Initramfs:
update-initramfs -u -k all
Install the bootloader:
grub-install --target=x86_64-efi --efi-directory=/boot/efi
update-grub
Et voilà! You can now exit the chroot, unmount the different disks, and reboot.
Note: please properly close the cryptroot mapping after unmounting /mnt
:
sudo cryptsetup close /dev/mapper/cryptroot