Unlocking an encrypted disk from the couch
A full-disk-encrypted desktop can't come back from a remote reboot on its own: it stops at a password prompt nobody can reach. Putting a tiny SSH server in the initramfs fixes that. What it costs, and how I checked the boot image before trusting it.

Part three of a series on wiring my machines together. Previously: from the couch to a shell in fifteen seconds. Next: screenshots, clipboards and a GUI across machines.
The desktop’s disk is encrypted with LUKS, as it should be. The catch is what that means for a machine you want to manage remotely: after any reboot — a kernel update, a driver update, a crash — it sits at a password prompt before anything else starts. No network, no SSH, nothing. Someone has to be at the keyboard.
For a machine I now mostly reach from the couch, that cancels out everything from part two. Every update ended with a walk.
The trick: SSH before the disk is open
Linux boots in two stages. The kernel first unpacks an initramfs — a small, unencrypted filesystem in the boot image — which does whatever it takes to reach the real root filesystem, including asking for the LUKS password. Only then does the actual system start.
So the fix is to put a network stack and an SSH server in the initramfs. dropbear is a small SSH server meant for exactly this. On Arch, three mkinitcpio hooks do the work:
netconfbrings the network up inside the initramfs.dropbearstarts the SSH server.encryptsshreplaces the stockencrypthook. It shows the same password prompt on screen as before, and lets an SSH login answer it.
That last part matters. Typing the password at the desk still works exactly as it did. Remote unlock is an extra path, not a replacement.
Fitting it into a distro that owns the config
Omarchy writes its own mkinitcpio config through drop-in files, and it already sets the hook list. I didn’t want to edit its files, because the next Omarchy update would either overwrite my change or conflict with it.
mkinitcpio config files are bash that gets sourced in order, so the last drop-in can rewrite the hook list instead of replacing it:
# /etc/mkinitcpio.conf.d/zz-remote-unlock.conf
_hooks=()
for _h in "${HOOKS[@]}"; do
if [[ $_h == encrypt ]]; then
_hooks+=(netconf dropbear encryptssh)
else
_hooks+=("$_h")
fi
done
HOOKS=("${_hooks[@]}")
unset _hooks _h
MODULES+=(r8169 realtek)
Whatever Omarchy decides the hook list should be, this swaps one entry and leaves the rest alone. The zz- prefix makes it sort last. The MODULES line pulls the network driver into the image; without it, netconf has no NIC to bring up.
No names before the disk is open
The initramfs has no mDNS, so grimmauld.local doesn’t resolve while it’s waiting for a password. The laptop has to find it by IP.
I gave the desktop a DHCP reservation on the router and told the kernel to use the same address statically during early boot:
ip=192.168.1.144::192.168.1.1:255.255.255.0:grimmauld:eth0:none
Note the eth0: inside the initramfs the NIC has its kernel name, not the enp42s0 systemd gives it later. The address is dropped before handover, and NetworkManager takes over as usual.
The address has to match the reservation exactly. If they drift apart, sooner or later something else on the network gets that IP, and the unlock prompt either becomes unreachable or, worse, you end up talking to the wrong machine.
Two host keys, one IP
dropbear has its own host key, separate from the real system’s OpenSSH key. To SSH they’re two different servers at one address, so the second one you connect to looks like a man-in-the-middle attack and SSH refuses.
The wrong fix is turning off host key checking for that address. The right fix is telling SSH they’re two hosts:
Host grimmauld-unlock
HostName 192.168.1.144
User root
HostKeyAlias grimmauld-initramfs
RequestTTY yes
ControlMaster no
ControlPath none
HostKeyAlias stores and checks the initramfs key under its own name, so both keys are pinned and either one changing still raises the alarm. Multiplexing is off for this host because the server disappears the moment the disk unlocks, and a shared master connection would be left pointing at nothing.
On the server side, dropbear only accepts the laptop’s key, and logging in as root gets you no shell: you get the password prompt and nothing else. The SSH key lets you ask to unlock the disk. You still need the disk password.
Check the image, not the config
I don’t fully trust a boot change until I’ve seen it in the thing that boots. Omarchy builds a unified kernel image — kernel, initramfs and command line in a single EFI file — so the setup script pulls the pieces back out of the built file and checks them:
objcopy -O binary --only-section=.initrd "$uki" "$work/initrd"
objcopy -O binary --only-section=.cmdline "$uki" "$work/cmdline"
tr '\0 ' '\n\n' < "$work/cmdline" | grep -a '^ip='
for f in usr/bin/dropbear usr/bin/cryptsetup_shell \
root/.ssh/authorized_keys hooks/encryptssh hooks/netconf; do
lsinitcpio "$work/initrd" | grep -q "^$f\$" \
&& echo "ok $f" || echo "MISSING $f"
done
The first version of this check was wrong. It looked for binaries under bin/ when the image puts them under usr/bin/, and it split the command line on spaces when the section is NUL-padded. So it reported missing pieces in a perfectly good image. I’d rather have a check that’s loudly wrong in a way I can fix than a reboot that’s quietly wrong in a way I can’t see from the couch.
Then I rebooted from the laptop, watched work notice dropbear’s banner on port 22, typed the password, and watched it wait for OpenSSH and drop me into my session.
What this costs
I do security for a living, so here’s the honest version.
The initramfs is unencrypted. That’s the point of it, and it means dropbear’s host key sits on the boot partition in the clear. Someone with physical access could copy it and impersonate the unlock prompt to capture the disk password. That’s the evil-maid attack, and full-disk encryption on its own doesn’t stop it either: anyone who can tamper with the boot partition can swap in a keylogging prompt. Remote unlock doesn’t create the problem, but it does add one more way in. For a desktop in my house, I’ll take that.
The password crosses the network. It goes over SSH to a pinned host key, on the LAN only. That’s the same exposure as typing sudo over SSH, which I already do.
There’s one more thing listening at boot. While the prompt is up, a root login is reachable on the LAN with a single authorized key, and all it can do is ask for a password. I’m comfortable with that surface.
What it’s worth: kernel and driver updates no longer have to wait until I’m at the desk. That turns out to matter more for security than it sounds. The updates I put off are the ones that need a reboot, and now they don’t need me in the room.
Next: moving screenshots, files and an entire desktop GUI between machines without setting anything up each time.