Headless Linux Disk Encryption

Using disk encryption is generally seen as a best practice to prevent data from falling into the wrong hands should the system be stolen. In Linux, this is typically implemented using LUKS disk encryption, which requires a password to be entered on boot. This presents a problem when dealing with servers which don’t have a keyboard and screen attached.

There are a few ways to address this problem.

Store Encryption Keys in TPM to Transparently Decrypt the Drive

This approach has a few of drawbacks. Firstly, whilst this would ensure the disk would be unreadable if removed from the host system, it would still boot without user interaction. An attacker with access to ports such as PCIe or Thunderbolt may be able to use DMA to extract credentials from the systems RAM and login as normal.

In addition, as the system will boot without user interaction any network accessible services hosted on the system may be attacked. If the attacker has time, previously undisclosed vulnerabilities in these services may become available.

Lastly, configuring this scenario is a pain to do in Linux!

Use LUKS Full Disk Encryption but Store the Encryption Key on External Media

The downside of this is you would need to be physically present to plug the device in. Depending on the location of the system this may not be feasible. This could be done by programming the key into a YubiKey, or storing the key on USB media.

Configure SSH Access in Initramfs to Provide the Encryption Key

This is the option we will be looking at.

This example is using Ubuntu 22.04. Install the server, and set a disk encryption key during install:

Once the operating system is up and running, Install dropbear initramfs on the server. This will provide an SSH server that can be used during the boot process.

sudo apt-get install dropbear-initramfs

Generate an SSH key on your local machine, and copy the public key to the server.

ssh-keygen -t rsa -f ubuntuserver_ssh_key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ubuntuserver_ssh_key
Your public key has been saved in ubuntuserver_ssh_key.pub
The key fingerprint is:
SHA256:0mRUBJclKvf1Jtj13TFm+iiTVwnxzlEFRPC8jmUe8tc user@fedora
The key's randomart image is:
+---[RSA 3072]----+
|        o+=oo=+.+|
|       . o.. oo .|
|      . =   ..+B |
|       * . + oBoB|
|      . S o +.B=+|
|       .    .@+..|
|           +.o+.E|
|            +  . |
|                 |
+----[SHA256]-----+
~/SSH_KEYS  ls
ubuntuserver_ssh_key  ubuntuserver_ssh_key.pub
scp ubuntuserver_ssh_key.pub 192.168.1.129:/etc/dropbear/initramfs/authorized_keys

Next, login to the server and set the key permissions;

chmod 600 /etc/dropbear/initramfs/authorized_keys

Modify /etc/initramfs-tools/initramfs.conf to include a line with the systems IP address it will use during boot;

IP=192.168.1.129::192.168.1.254:255.255.255.0:ubuntuserver

Finally, run update-initramfs to save the configuration.

update-initramfs -u
update-initramfs: Generating /boot/initrd.img-5.15.0-58-generic

Now, when you reboot the system the local console will still prompt for a boot password, but you should be able to SSH to the system and run the cryptroot-unlock command.

In Conclusion

The /boot partition will remain unencrypted. An attacker with physical access to the system may be able to alter the initramfs image to record the encryption key as it’s entered. However, it’s worth noting this this risk would be present entering the password locally.