TechEarl

Unlock LUKS Remotely Over SSH With Dropbear

Set up LUKS remote unlock over SSH with Dropbear in the initramfs, so an encrypted root server can finish booting after a reboot without a console or KVM.

Ishan Karunaratne⏱️ 12 min readUpdated
Share thisCopied
LUKS remote unlock over SSH with Dropbear: put an SSH server in the initramfs so you can type the disk passphrase remotely and finish booting an encrypted root server.

If your root filesystem is LUKS-encrypted, a remote server cannot finish booting on its own: it sits at the initramfs prompt waiting for someone to type the passphrase. The fix is to put a tiny SSH server (Dropbear) into the initramfs so you can SSH in early in boot and type the passphrase remotely. On Debian and Ubuntu that is one package:

bash
sudo apt install dropbear-initramfs

Add your public key to /etc/dropbear/initramfs/authorized_keys, rebuild the initramfs, and on the next reboot you SSH into the half-booted box, run one command to unlock the disk, and the boot continues. No console, no KVM, no IPMI Java applet. This is the whole job, and below is every step plus the parts that bite people.

If you have not encrypted the disk yet, do that first: encrypt a disk with LUKS and cryptsetup. This article assumes the LUKS volume already exists and is unlocked at boot from a console today.

Why the initramfs needs its own SSH server

The reason a normal sshd does not help here: at the point boot stalls, the root filesystem is still encrypted and not mounted. Your real OpenSSH server, its config, and its host keys all live on that locked disk. Nothing on root is reachable yet.

The initramfs is the small, unencrypted image the bootloader loads into RAM before root exists. It is the one place early enough in boot to run code while the disk is still locked. So the trick is to bake a minimal SSH server (Dropbear, chosen because it is tiny) plus a network stack into that initramfs. You SSH to that, unlock the disk from inside it, and the normal boot, including your real sshd, takes over.

Dropbear is a small SSH server and client written for embedded and memory-constrained environments. That is exactly the initramfs use case: a few hundred KB, no dependency on the encrypted root.

Install and add your key (Debian, Ubuntu)

Install the package, then drop your public key in:

bash
sudo apt install dropbear-initramfs

On current Debian (12 "bookworm" and later) and Ubuntu, the package is dropbear-initramfs, split out from the older monolithic dropbear package. The authorized-keys file lives at:

bash
sudo tee -a /etc/dropbear/initramfs/authorized_keys < ~/.ssh/id_ed25519.pub

This is a separate authorized_keys from your normal user account's. It only governs the early-boot Dropbear, and the only thing you can do once connected is unlock the disk, so keep it to the keys that genuinely need to reboot the box.

If you do not have a keypair yet, create an SSH key first. Use a plain Ed25519 key here; Dropbear has supported it for years. One caveat worth knowing: a FIDO2 hardware key (sk-ssh-ed25519) is not a good fit for the initramfs, because the busybox Dropbear has no ssh-sk middleware to negotiate the security-key challenge. Keep the hardware key for your normal account and use a standard Ed25519 key for early-boot unlock.

Rebuild the initramfs

Nothing you changed takes effect until you regenerate the initramfs image, because the key and the Dropbear binary get copied into it at build time:

bash
sudo update-initramfs -u

-u updates the initramfs for the current kernel. The build hook pulls in Dropbear, your authorized_keys, and the network bits. Confirm the key actually made it in before you trust it with a reboot:

bash
sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'dropbear|authorized_keys'

You want to see both the Dropbear binary and authorized_keys listed. If authorized_keys is missing, the file was empty or in the wrong path, and you will lock yourself out. On a remote box this is the one mistake with no recovery short of console access, so never reboot until that grep returns both lines. If you can, do the very first reboot with a console or KVM still attached as a safety net.

Give the initramfs an IP address

The early environment has no DHCP client and no network config from your normal setup, so you have to tell it how to bring up networking. This is the step people forget, and the symptom is an SSH connection that just times out at boot.

You configure it with the kernel ip= boot parameter. The simplest reliable form is static:

bash
ip=192.0.2.10::192.0.2.1:255.255.255.0:myhost:eth0:off

The fields, in order, are: client IP, NFS/boot-server IP (left blank here, which is why you see the doubled ::), gateway, netmask, hostname, interface, and autoconf (off for static, dhcp to ask a DHCP server). Add it to GRUB_CMDLINE_LINUX in /etc/default/grub:

bash
GRUB_CMDLINE_LINUX="ip=192.0.2.10::192.0.2.1:255.255.255.0:myhost:eth0:off"

Then regenerate GRUB and the initramfs:

bash
sudo update-grub && sudo update-initramfs -u

Two real-world snags. First, the interface name: the initramfs may not run the same predictable-naming rules as your booted system, so a NIC that is enp1s0 once booted can be eth0 in early boot. If SSH times out, the wrong interface name is the first suspect. Second, dhcp works but it makes boot depend on a DHCP lease being granted in a narrow window; for a server you reboot rarely, a static ip= is more predictable.

Unlock the disk on the next reboot

Reboot, then SSH to the box. Dropbear listens on port 22 by default (you can change it, see below), and it logs in as root even though your normal login may not:

bash
ssh root@192.0.2.10

You land in a minimal busybox shell. The right command depends on your distro's initramfs scripts. On a current cryptsetup-initramfs setup, run:

bash
cryptroot-unlock

It prompts for the LUKS passphrase, unlocks the mapped device, and boot continues. Your SSH session to the initramfs drops as the real system comes up, which is expected, not an error. A few seconds later you can SSH in normally to your actual user account.

Older guides tell you to echo the passphrase into a named pipe like /lib/cryptsetup/passfifo. That still works on some setups, but cryptroot-unlock is the supported wrapper and the one to reach for first.

Lock it down: separate port, no shell

Two hardening steps I always apply. Run Dropbear on a non-standard port so it does not collide with your real sshd in host-key caches and SSH config, and restrict the early key so a connection can only unlock, never drop to a shell.

Set Dropbear's options in /etc/dropbear/initramfs/dropbear.conf (older packages used /etc/dropbear-initramfs/config with a DROPBEAR_OPTIONS= line; check which your version ships):

bash
DROPBEAR_OPTIONS="-p 2222 -s -j -k -I 60"

-p 2222 moves it off 22. -s disables password logins (key-only, which is the point). -j and -k disable local and remote port forwarding. -I 60 idle-times-out the session after 60 seconds, so a forgotten connection does not sit open.

You can also force a single command per key by prefixing the line in authorized_keys:

bash
command="/bin/cryptroot-unlock" ssh-ed25519 AAAA... you@example.com

Now that key can do nothing but unlock the disk. Even if it leaks, it cannot get a busybox shell on your initramfs. (Dropbear also accepts -c cryptroot-unlock in DROPBEAR_OPTIONS to force that command for every login regardless of key; the per-key command= form is more explicit, so I prefer it.)

This is the early-boot half of the picture. The real OpenSSH server that takes over once root is mounted needs its own hardening, key-only auth in particular: see disable password authentication in sshd for that pass.

When this is and is not the right tool

ScenarioUse Dropbear remote unlock?
Remote VPS or dedicated box with LUKS root, no out-of-band consoleYes. This is the canonical use case.
Box you reboot rarely and only ever from a physical consoleOptional. The console is already enough.
You want fully unattended reboots, no human typing a passphraseNo, this still needs a human. Use a TPM-bound key or Clevis/Tang network-bound unlock instead.
Encrypted /home or a data volume, but root is plaintextNo. If root is unencrypted, the normal sshd boots fine; unlock the data volume after login.

The honest caveat: this is convenience, not extra security. The disk is exactly as encrypted as before. Worth weighing: an unattended TPM or Tang unlock removes the human but also removes the "someone must know the passphrase" property, so it is a different threat model, not strictly better. For a server I reboot a handful of times a year, typing a passphrase over SSH is the right trade.

A note on systemd-based initramfs

Some recent systems build a systemd-driven initramfs rather than the classic busybox one. The plumbing differs (the unlock prompt is handled by systemd-cryptsetup and you may need the dropbear systemd hook rather than the script hook), but the shape is identical: SSH server in the initramfs, connect early, unlock, boot continues. The Arch Wiki section linked at the foot of this page documents the systemd-hook variant if your distro uses it; the Debian/Ubuntu dropbear-initramfs package handles the script-based case described above for you.

Because at the moment boot stalls, the root filesystem is still encrypted and unmounted. Your real OpenSSH server, its config, and its host keys all live on that locked disk, so none of it is running yet.

Dropbear solves this by living inside the initramfs, the small unencrypted image loaded into RAM before root exists. That is the only place early enough to accept a connection while the disk is still locked. See encrypting a disk with LUKS and cryptsetup for how the encrypted root is set up in the first place.

Almost always one of two things. Either the initramfs brought up no network (you forgot the kernel ip= parameter, or it is set for dhcp and no lease was granted), or the interface name in ip= is wrong. Early boot may name a NIC eth0 even though your booted system calls it enp1s0.

Confirm the key and binary are actually in the image with lsinitramfs /boot/initrd.img-$(uname -r) | grep dropbear before blaming the network.

On a current cryptsetup-initramfs setup, run cryptroot-unlock. It prompts for the LUKS passphrase, unlocks the device, and boot continues. Your SSH session then drops as the real system takes over, which is expected.

Older setups used an echo into a named pipe such as /lib/cryptsetup/passfifo; that may still work, but cryptroot-unlock is the supported wrapper.

Keep them separate. Run Dropbear on a different port (for example -p 2222) so the two do not share an entry in your client's known_hosts, which otherwise produces a host-key-mismatch warning every time you reboot. Dropbear keeps its own host keys in the initramfs config, distinct from your OpenSSH host keys on the encrypted root.

Yes. cryptroot-unlock reports a failed attempt and returns you to the prompt, so you can run it again or re-enter the passphrase without rebooting. The disk stays locked until a correct passphrase is given; a wrong one does not consume a one-shot or wipe anything.

If the SSH session itself drops mid-unlock (idle timeout from the -I option, or a flaky link), just reconnect and run cryptroot-unlock again. Nothing is lost because boot has not progressed past the unlock step.

They solve different problems. Dropbear keeps a human in the loop: you SSH in and type the passphrase, so the secret never lives on the machine or the network. Clevis with a Tang server, or a TPM-bound key, unlocks the disk automatically with no human, which is what you want for fully unattended reboots.

The trade is the threat model: automatic unlock means anyone who can boot the box on its own network (or with its TPM intact) gets a decrypted disk. For a server I reboot a few times a year, the Dropbear approach is the one I reach for; for a fleet that reboots constantly, network-bound unlock wins.

No. The disk is exactly as encrypted as before, and the passphrase is still required. Dropbear only moves where you type that passphrase from a physical console to an early-boot SSH session. The key for the initramfs lives in a separate authorized_keys, and you can pin it to command="/bin/cryptroot-unlock" so it can do nothing but unlock.

See also

Sources

Authoritative references this article was fact-checked against.

TagsLUKSDropbearSSHinitramfscryptsetupFull Disk EncryptionLinuxSecurity

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts

Download an entire YouTube playlist or channel free with yt-dlp: use a download archive for incremental re-runs, organize files with output templates, grab item ranges, and rate-limit big channels.

Download a YouTube Playlist or Entire Channel with yt-dlp

Download a whole YouTube playlist or entire channel free with yt-dlp: point it at a playlist or @handle, use a download archive so re-runs skip what you already have, organize files with output templates, and rate-limit to dodge the bot wall.

Wire ElasticPress to WP_Query so WordPress queries hit Elasticsearch instead of MySQL. Install, indexable post types, ep_integrate, wp-cli index, faceted aggregations, and when ES actually beats MySQL FULLTEXT.

How to Use ElasticPress with WP_Query

Wire ElasticPress to WP_Query so WordPress queries hit Elasticsearch instead of MySQL. Covers installation, indexable post types, ep_integrate, the wp-cli index command, faceted search with aggregations, and when ES actually beats MySQL FULLTEXT.