This procedure was tested on Omarchy with UEFI/Limine, a Btrfs root filesystem on LUKS, and a wired Realtek NIC. It uses Dropbear in the initramfs so SSH is available before the encrypted root is mounted.
Replace every value in <ANGLE_BRACKETS> before running a command. Do not
publish a private key, disk passphrase, hostname, IP address, MAC address, or
unredacted command history.
The early boot sequence becomes:
- Firmware and Limine load the kernel and initramfs.
- The initramfs brings up wired networking.
- Dropbear listens on SSH port 22.
- The operator connects as
rootusing a preinstalled public key. - The Dropbear root shell asks for the LUKS passphrase.
- The SSH session closes after unlock and normal userspace boots.
The intended interface is an early-boot unlock shell, not a general-purpose
root shell. That restriction is a property of the installed
mkinitcpio-dropbear/encryptssh hook and its configuration, not a guarantee
provided by Dropbear itself. Verify the generated image and test the behavior
after package updates. The normal SSH service still needs to work separately
after boot.
This exact recipe assumes:
- Omarchy using a busybox-style mkinitcpio configuration with the classic
encrypthook. - A Limine UKI built with
limine-mkinitcpio. - Wired Ethernet available during boot.
- The root LUKS device and ordinary local passphrase unlock already work.
Do not apply this hook rewrite unchanged to a system using a systemd
initramfs and sd-encrypt; that needs a different configuration.
This exposes a privileged SSH service before the encrypted root filesystem is mounted. Normal userspace firewall rules are not active yet, so the host firewall does not protect the early Dropbear listener. Use this only on a trusted, access-controlled management network, or enforce an upstream ACL that allows TCP port 22 only from the intended management client. Do not expose the early service to the Internet, a guest network, or an unrestricted LAN.
LUKS protects the encrypted volume at rest; it does not authenticate the firmware, bootloader, EFI system partition, UKI, or initramfs. An attacker who can modify the boot artifacts could replace the unlock helper and capture the passphrase during the next boot. This procedure does not protect against that physical-access or evil-maid threat. A correctly configured verified boot chain can reduce that risk, but configuring one is outside this guide's scope.
Have a monitor/keyboard or another out-of-band console available for the first test. A failed initramfs can otherwise leave the machine inaccessible.
Open a root shell:
sudo -iVerify that this is the writable top-level system, not an Omarchy snapshot overlay:
cat /proc/cmdline
findmnt -no SOURCE,FSTYPE,OPTIONS /
findmnt -no SOURCE,FSTYPE,OPTIONS /bootThe root output should show the normal Btrfs @ subvolume, for example:
/dev/mapper/root[/@] btrfs ... subvol=/@
If / is overlay, or the command line contains
rootflags=subvol=/@/.snapshots/<number>/snapshot, reboot and select the
normal top-level Omarchy entry before making changes. Do not build from the
snapshot overlay.
Create an Omarchy snapshot before changing the initramfs:
omarchy-snapshot createIf this says that the root is not a Btrfs subvolume, stop and return to the
normal top-level system. A snapshot is a rollback aid, not a complete backup
of important data or the LUKS header. Omarchy snapshots restore the root
filesystem, not /home; if /boot is a separate EFI partition, it is not
rolled back by the Btrfs snapshot either. That is why the next step backs up
the boot files separately.
Back up the current UKI and configuration:
install -d -m 700 /boot/remote-unlock-backup
install -o root -g root -m 600 \
/boot/EFI/Linux/omarchy_linux.efi \
/boot/remote-unlock-backup/omarchy_linux.efi
if [ -e /boot/limine.conf ]; then
cp -a /boot/limine.conf /boot/remote-unlock-backup/limine.conf
fi
cp -a /etc/default/limine /etc/default/limine.before-remote-unlock
if [ -e /etc/mkinitcpio.conf.d/zz-remote-unlock.conf ]; then
cp -a /etc/mkinitcpio.conf.d/zz-remote-unlock.conf \
/etc/mkinitcpio.conf.d/zz-remote-unlock.conf.before
fiOn Omarchy, use its package wrapper:
omarchy pkg add \
dropbear \
mkinitcpio-dropbear \
mkinitcpio-netconf \
mkinitcpio-utils \
mkinitcpio-nfs-utilsVerify the packages:
pacman -Q \
dropbear \
mkinitcpio-dropbear \
mkinitcpio-netconf \
mkinitcpio-utils \
mkinitcpio-nfs-utilsDo this first on the client machine. Use a dedicated key so it can be revoked without changing normal SSH access:
ssh-keygen -t rsa -b 4096 -f ~/.ssh/initramfs_unlock \
-C 'initramfs-unlock'Transfer only ~/.ssh/initramfs_unlock.pub to the server. Never transfer or
publish ~/.ssh/initramfs_unlock.
On the server, paste the public key as exactly one physical line:
install -d -m 700 /etc/dropbear
vi /etc/dropbear/root_key
chmod 600 /etc/dropbear/root_keyVerify the key without printing it into the gist or log:
ssh-keygen -lf /etc/dropbear/root_key -E sha256
grep -c . /etc/dropbear/root_key
stat -c '%a %s bytes %n' /etc/dropbear/root_keyThe mode should be 600, and the nonblank-line count should be 1. Compare
the fingerprint with the client-side public key:
ssh-keygen -lf ~/.ssh/initramfs_unlock.pub -E sha256The name used by normal userspace is not necessarily the name available in
the initramfs. Predictable names such as enp3s0 are often assigned only
after udev runs; the initramfs may initially call the device eth0.
Inspect the running system:
lspci -k | grep -A3 -i ethernet
ip -br link
dmesg --ctime | grep -Ei 'renamed from|ethernet|r8169|link'Record two values:
<NIC_MODULE>: the kernel driver, such asr8169.<INITRAMFS_IFACE>: the name before the udev rename, such aseth0.
For example, the relevant evidence may look like:
r8169 ... eth0: RTL8168g/8111g
r8169 ... enp3s0: renamed from eth0
In that case, use r8169 as <NIC_MODULE> and eth0 as
<INITRAMFS_IFACE>. Do not use enp3s0 in the early ip= parameter merely
because that is what ip link shows after normal boot.
This guide assumes the existing configuration has the classic encrypt
hook. Check before editing:
grep -RInE 'HOOKS=.*(encrypt|sd-encrypt)' \
/etc/mkinitcpio.conf /etc/mkinitcpio.conf.d 2>/dev/nullCreate a late drop-in. Replace r8169 below with your actual
<NIC_MODULE>:
vi /etc/mkinitcpio.conf.d/zz-remote-unlock.confUse this content:
MODULES+=(r8169)
_remote_hooks=()
for _remote_hook in "${HOOKS[@]}"; do
case "$_remote_hook" in
encrypt) _remote_hooks+=(netconf dropbear encryptssh) ;;
netconf|dropbear|encryptssh) ;;
*) _remote_hooks+=("$_remote_hook") ;;
esac
done
HOOKS=("${_remote_hooks[@]}")
unset _remote_hooks _remote_hookThe zz- prefix makes this override run after the normal Omarchy mkinitcpio
drop-ins. The build should show these hooks in this order:
netconf -> dropbear -> encryptssh
Check the drop-in syntax:
bash -n /etc/mkinitcpio.conf.d/zz-remote-unlock.confFind the LUKS partition and a stable device identifier. This recipe uses the
partition's PARTUUID. PARTUUID identifies the partition, while UUID for
a crypto_LUKS partition identifies the LUKS container; do not substitute one
for the other without changing the cryptdevice= prefix:
lsblk -o NAME,TYPE,FSTYPE,UUID,PARTUUID,MOUNTPOINTS
blkid -s PARTUUID -o value /dev/<LUKS_PARTITION>The static ip= form is:
ip=<INITRAMFS_HOST_IP>::<GATEWAY_IP>:<NETMASK>::<INITRAMFS_IFACE>:none
For example, if the address assigned to the machine being unlocked is
192.0.2.50, the gateway is
192.0.2.1, the netmask is 255.255.255.0, and the early interface is
eth0, the parameter is:
ip=192.0.2.50::192.0.2.1:255.255.255.0::eth0:none
The 192.0.2.0/24 values above are documentation-only examples. Replace
them with values from the target network and ensure the address is reserved
or otherwise cannot conflict.
Edit the existing Limine defaults rather than creating a second conflicting
ip= parameter:
vi /etc/default/limineInspect the existing KERNEL_CMDLINE[default] assignment first. Preserve its
existing cryptdevice, root, rootflags, resume, graphics, and other
required arguments. Replace any old ip=... token with the new static value;
do not add a second conflicting ip= token or duplicate the root arguments.
A complete minimal Omarchy-style command-line assignment, for a system that does not already have one, looks like this:
ESP_PATH="/boot"
KERNEL_CMDLINE[default]+="cryptdevice=PARTUUID=<LUKS_PARTUUID>:root root=/dev/mapper/root rootflags=subvol=@ rw ip=<INITRAMFS_HOST_IP>::<GATEWAY_IP>:<NETMASK>::<INITRAMFS_IFACE>:none rootfstype=btrfs"Replace all angle-bracket placeholders before saving. Treat that assignment as a shape, not as a line to paste over an existing Omarchy configuration. Most installations already have additional generated or locally required arguments; retain them.
The explicit static form removes DHCP and interface autodetection from the
pre-boot path. If DHCP is required instead, specify the early interface
explicitly rather than using bare ip=dhcp:
ip=:::::<INITRAMFS_IFACE>:dhcp netconf_timeout=30
Check the Limine defaults and rebuild:
bash -n /etc/default/limine
limine-mkinitcpioTreat a build error as a stop condition. The build must finish with messages
equivalent to Unified kernel image generation successful and Updated: /boot/limine.conf.
Verify that the generated boot entry contains the intended early interface:
grep -n 'ip=' /boot/limine.confVerify that the UKI contains the driver, hooks, key, and unlock shell:
lsinitcpio -l /boot/EFI/Linux/omarchy_linux.efi | \
grep -E 'r8169|hooks/(netconf|dropbear|encryptssh)|root_key|authorized_keys|cryptsetup_shell|usr/bin/dropbear'The output should include equivalents of:
.../r8169.ko.zst
hooks/netconf
hooks/dropbear
hooks/encryptssh
etc/dropbear/root_key
root/.ssh/authorized_keys
usr/bin/cryptsetup_shell
usr/bin/dropbear
Do not reboot until these checks pass and a physical recovery path is ready.
On the client, open a separate terminal before rebooting. Use the dedicated private key and an isolated known-hosts file because the initramfs Dropbear host key may differ from the normal OpenSSH host key:
ssh -i ~/.ssh/initramfs_unlock \
-o IdentitiesOnly=yes \
-o UserKnownHostsFile=/tmp/initramfs-unlock-known_hosts \
-o StrictHostKeyChecking=accept-new \
root@<INITRAMFS_HOST_IP>The early Dropbear service listens on port 22 by default. The login user is
root; the key is not installed for the normal user account.
After reboot, the connection should reach a prompt similar to:
Enter passphrase for /dev/<LUKS_PARTITION>:
Enter the LUKS passphrase. The input is not echoed. After a successful unlock, the initramfs SSH session normally closes and the machine continues booting. Reconnect using the normal account and hostname after userspace is ready.
On the tested Omarchy package set, the session may close with:
cryptsetup: no process found
This is noisy cleanup after a successful unlock, not an unlock failure. Treat
it as harmless only when the normal SSH service returns and checks confirm that
the expected /dev/mapper/root mapper and root filesystem are present. If
normal boot does not complete, investigate the failure instead of assuming
this message is benign.
If the passphrase is rejected, the same early SSH session may present the prompt again. If SSH times out, do not keep rebooting blindly; use the troubleshooting section below.
The UKI and encryption hook are running; early networking or Dropbear startup failed. Boot locally by entering the passphrase, then inspect:
dmesg --ctime | grep -Ei 'renamed from|ethernet|<NIC_MODULE>|link'The most common cause is using the normal userspace name (enp3s0) instead
of the original initramfs name (eth0). Also confirm that the driver was
forced into the image with MODULES+=(<NIC_MODULE>).
Compare fingerprints and permissions:
ssh-keygen -lf /etc/dropbear/root_key -E sha256
chmod 600 /etc/dropbear/root_keyRebuild the UKI after any key change. Do not paste the private key into the server or into a gist.
Select the normal top-level Omarchy Limine entry. Snapshot entries use a
temporary overlay and are not the writable top-level @ system. Verify with:
findmnt -no SOURCE,FSTYPE,OPTIONS /Only create snapshots or edit persistent initramfs configuration when the
output shows the normal writable @ subvolume.
Run this only from the writable top-level system, using the backup filenames created earlier. This restores both the root-side configuration and the separately backed-up boot artifacts:
mv /etc/mkinitcpio.conf.d/zz-remote-unlock.conf \
/etc/mkinitcpio.conf.d/zz-remote-unlock.conf.disabled
cp -a /etc/default/limine.before-remote-unlock /etc/default/limine
cp -a /boot/remote-unlock-backup/omarchy_linux.efi \
/boot/EFI/Linux/omarchy_linux.efi
if [ -e /boot/remote-unlock-backup/limine.conf ]; then
cp -a /boot/remote-unlock-backup/limine.conf /boot/limine.conf
fi
limine-mkinitcpioThe installed packages may remain present. Disabling the drop-in and restoring the Limine command line removes the remote-unlock hooks from any future generated image; the backup copy restores the last known-good image immediately. Verify the rebuilt image before rebooting.
The isolated UserKnownHostsFile keeps the initramfs host key separate from
the normal userspace SSH key, but StrictHostKeyChecking=accept-new is
trust-on-first-use. It does not protect the first connection from a
man-in-the-middle attack.
For a security-sensitive deployment, obtain the expected early host-key fingerprint through a trusted local console, a trusted build/recovery process, or another authenticated channel. Store that key in the isolated known-hosts file before remote unlock and use strict checking:
ssh -i ~/.ssh/initramfs_unlock \
-o IdentitiesOnly=yes \
-o UserKnownHostsFile=/tmp/initramfs-unlock-known_hosts \
-o StrictHostKeyChecking=yes \
root@<INITRAMFS_HOST_IP>Treat an unexpected early host-key change as a stop condition until it has
been explained. Rebuilding the initramfs may legitimately change the key,
depending on how the installed package provisions it; verify and repin it
through the trusted channel after such a change. Do not use ssh-keyscan over
an unauthenticated network as proof that a fingerprint is genuine.
A snapshot and a copied UKI are useful rollback material, but neither is by itself a guaranteed boot path. Before operating the machine headlessly, verify at least one recovery method:
- a physical or out-of-band console with a known local unlock procedure;
- a known-good, selectable Limine fallback entry; or
- bootable recovery media that can unlock the LUKS volume, mount the Btrfs root and EFI partition, and restore the saved configuration.
A backup file on the same disk is not sufficient if the EFI partition, disk, or boot configuration is damaged. A snapshot also does not roll back a separate EFI partition or guarantee that the machine can boot far enough to restore it.
- Use a dedicated client key and protect its private half normally.
- The public key is copied into the initramfs and may be present on the EFI partition; it is not a secret.
- Never write the LUKS passphrase into the key file, command line, shell history, gist, or logs.
- Restrict early SSH reachability to a trusted, access-controlled management network. The initramfs service has fewer controls than a full OpenSSH installation, and normal userspace firewall rules do not protect it.
- Use an isolated
UserKnownHostsFilefor the early service so its host key does not conflict with the normal host key. For stronger protection, use the optional strict host-key pinning procedure above. - A Btrfs snapshot is not a complete backup and does not protect against disk failure or accidental deletion of unrelated data.