remote-unlocking full system encryption with arch linux

======================================================================

I recently needed to set up a server with full system encryption and was faced with the conundrum: if I need to reboot, the keys are either (a) on the server, and thus not actually secure, or (b) need to be entered at boot, which typically means (I thought) that one needs to actually enter a password. However! I searched around a bit and saw that people used the dropbear ssh server in their initramfs images to log in remotely and thereby allow for a genuinely headless full-disk encrypted system. Unfortunately, almost all of the resources I could find on this was for Debian-based systems, and I had a hell of a time getting it to work on Arch.

So, to spare others the pain I went through getting this to work, here is sanine's guide to remote-unlocking encrypted Arch systems.

1. set up arch with full system encryption

----------------------------------------------------------------------

The Arch wiki has fairly complete guides on how to do this! I used the installation guide and encrypting an entire system guide to get my initial installs set up.

A note on the bootloader steps, because this was not made clear to me the first time I did it: the kernel parameters are passed as command-line parameters. If you're using GRUB, for instance, they should be put in the GRUB_CMDLINE_LINUX variable, not as config variables in their own right.

2. install the needed packages

----------------------------------------------------------------------

This should be a pretty easy step. On your lovely fresh install, just do

pacman -S mkinitcpio-netconf mkinitcpio-dropbear

The netconf hook will set up networking for us; the dropbear hook sets up an ssh server for us.

3. write a completely new initcpio hook

----------------------------------------------------------------------

Yeah, sorry, this is where it got weird for me and I spent several days just reading the man pages convinced I had done something wrong. Nope! As it is now, if we set up the hooks, the dropbear server would run just fine but wouldn't actually accept any logins because there's no /etc/passwd file in the initramfs image for it to check if a user is valid. Luckily, it's pretty easy to create a hook that adds one for us. Create the file /usr/lib/initcpio/install/rootpasswd and write in it

#!/bin/bash

build ()
{
    echo "root::0:0::/root:/bin/sh" > /tmp/rootpasswd
    add_file /tmp/rootpasswd /etc/passwd
}

You can change the user if you want to, though you'll have to go modify the dropbear install file so that it sets up the root_key in the correct folder.

4. hack the encrypt hook

----------------------------------------------------------------------

(If you're using the sd-encrypt hook: I have no idea how applicable any of this section will be to you. Try it and let me know!)

Okay, now it's possible to log in to the ssh server so what's the problem? Well, the default encrypt hook only checks if the target volume is present at the beginning. If you unlock it halfway through, when it's already prompted you for a password (say, for instance, by sshing in and decrypting it) it will just break. So we need to write another new hook. We still need the encrypt hook's install file though, so do

cd /usr/lib/initcpio/install
cp encrypt remote-encrypt

In your favorite text editor, enter the following into /usr/lib/initcpio/hooks/remote-encrypt:

#!/bin/sh

run_hook ()
{
    echo "waiting for ${root} to be available..."
    while ! [ -e "${root}" ]; do
        sleep 2;
    done
}

Okay, now you're finished writing hooks. Time to bring everything together.

5. bring everything together

----------------------------------------------------------------------

Edit your /etc/mkinitcpio.conf HOOKS line so that it looks a little like this:

HOOKS=(base udev rootpasswd keyboard keymap consolefont
autodetect modconf block netconf dropbear remote-encrypt
lvm2 filesystems fsck)

Remember that the order of your hooks is important! When you're done, run mkinitcpio -P to regenerate your initramfs images.

Now, edit your chosen bootloader to add the kernel parameter ip=dhcp so that the netconf hook will work correctly. (If you're using GRUB, don't forget to regenerate your grub.cfg.)

Last but not least, make sure the ssh keys you want to use for unlocking are stored like an authorized_keys file in /etc/dropbear/root_key.

6. unlock remotely

----------------------------------------------------------------------

If all went well, you should now be able to reboot and ssh into your machine before disk decryption. Decryption will be different based on how you set up your machine, but if you did LVM on LUKS like me, you can do

cryptsetup open [cryptdevice] [target] && exit

The "&& exit" isn't critical, but it does lead to some weird effects because for some reason you won't get booted out when dropbear is supposed to die? And this triggered some ugly segfault error messages when I actually did exit after the machine fully booted. Oh well.