Skip to main content

Remote Unlock of Encrypted ZFS Root

Install prerequisites

sudo apt install dropbear-initramfs initramfs-tools dropbear

Configure network and Dropbear in initramfs

sudo vim /etc/initramfs-tools/initramfs.conf

Append the following

#format [host ip]::[gateway ip]:[netmask]:[hostname]:[device]:[autoconf]
#([hostname] can be omitted)
IP=172.30.0.203::172.30.0.1:255.255.0.0::enp0s25:off

To avoid issues with mis-matching host keys with the post startup SSH server causing your SSH client to complain, we will setup the initramfs dropbear instance to use a different port.

sudo vim /etc/dropbear/initramfs/dropbear.conf
DROPBEAR_OPTIONS="-s -I 30 -p 4748"

Dropbear authorized keys

sudo vim /etc/dropbear/initramfs/authorized_keys
no-port-forwarding,no-agent-forwarding,no-x11-forwarding,command="/scripts/unlock-zfs-root" ssh-rsa AA...ub initramfs

Initramfs Unlock script

This script is executed instead of a shell when a user logs in to the dedicated dropbear (SSH) service. It simply prompts the user for the password, kills the existing "zfs load-key" instance that initramfs started (that is waiting for a password to be entered on the console), then exits, disconnecting the user.

sudo vim /usr/share/initramfs-tools/scripts/unlock-zfs-root
# Source the ZFS functions
. /scripts/zfs

root=$(ps | grep -v grep | grep 'zfs load-key' | awk '{print $NF}')
load_key_pid=$(ps | grep -v grep | grep 'zfs load-key' | awk '{print $1}')

if [ ! "x${root}" = "x" ] && [ ! "x${load_key_pid}" = "x" ]; then
decrypt_fs $root
kill $load_key_pid
exit 1
else
echo "Unable to find the \"zfs load-key\" process."
exit 1
fi
sudo chmod +x /usr/share/initramfs-tools/scripts/unlock-zfs-root

Initramfs Hook

sudo vim /etc/initramfs-tools/hooks/unlock-zfs-root.sh
#!/bin/sh

PREREQ="dropbear"

prereqs() {
echo "$PREREQ"
}

case "$1" in
prereqs)
prereqs
exit 0
;;
esac
sudo chmod +x /etc/initramfs-tools/hooks/unlock-zfs-root.sh
sudo update-initramfs -c -k all