--- title: "Launching SSH during early boot with mkinitfs" blurb: "Replacing the early init with our own script to launch SSH, killing it in early userspace, and allowing remote disk decryption in the mean time" author: "7222e800" slug: "alpine-ssh-early-initfs-disk-decryption" id: 1768406136 # Timestamps are in ISO8601 UTC (`date -u +%Y-%m-%dT%H:%M:%SZ`) created: "2026-01-14T15:53:57Z" updated: "2026-01-14T15:53:57Z" published: false ---
**Warning**
This post talks about operations that may lead the reader's system unbootable, including modifying its initramfs. Do not follow along if the reader is not prepared to fix its own systems from potentially infuriating bugs.

Maybe avoid following along on the friday before the reader's vacation.

For a while, this one's been meaning to setup an early-boot SSH environment for Alpine Linux on systems that are using a [System Disk](https://wiki.alpinelinux.org/wiki/System_Disk_Mode) installation mode. In [Data Disk](https://wiki.alpinelinux.org/wiki/Data_Disk_Mode) mode, it can be handled in `boot` or `sysinit`. This can even be nicely netbooted via a netbooted apkovl - article on that eventually. (for now, if you're interested in that, here's a good starting point: [alpine/mkinitfs#cc4954b/initramfs-init.in](https://gitlab.alpinelinux.org/alpine/mkinitfs/-/blob/cc4954bc73cf55833b48624232b9c42ca3abc390/initramfs-init.in#L647)) On System Disk installations, with tooling like [dracut](https://wiki.gentoo.org/wiki/Dracut), this would also be trivial. Unfortunately, this one's a masochist and like staying close to the intended upstream Alpine installation > **Note**
> Alpine does have > [a package](https://pkgs.alpinelinux.org/package/v3.23/community/x86_64/dracut) > for dracut, and the reader may want to look into using it instead. ## mkinitfs and it's challenges Alpine's [mkinitfs](https://gitlab.alpinelinux.org/alpine/mkinitfs/) allows us to do things like including files or kernel modules in the image, via their [features.d](https://gitlab.alpinelinux.org/alpine/mkinitfs/-/tree/master/features.d). This is nice and all, but on it's own, we can only really give the kernel a module, or a file we manually call by spamming enter through the encryption password prompts and running via the 'Emergency Shell'. ### approach 1: patching The easiest solution this one thought of was to just directly modify `/usr/share/mkinitfs/initramfs-init` and be happy, then deal with it when upstream modifies things. This is, however, very not "set, make a blog post, and forget". So we skipped that idea. ### approach 2: fork the upstream The second, and nicest to upstream solution it thought of was modify [initramfs-init.in](https://gitlab.alpinelinux.org/alpine/mkinitfs/-/blob/cc4954bc73cf55833b48624232b9c42ca3abc390/initramfs-init.in) \- which gets built into `/init` in the initfs. This would've worked very well, but would require maintaining one's own `/init`, for which the distro provides few guarantees that the rest of the tooling will forever accomodate an old version forked off. #### upstreaming It also thought about upstreaming this, for which this would've been the only viable approach. However, with this, comes the challenge of cleaning up the sshd during early openrc, cleanly, without any use-case edge-cases. > **For Alpine Maintainers**
> If beings involved in the mkinitfs project want something like this, this > one's willing to, with some guidance on avoiding user edge-cases, contribute > this. ### approach 3: third approach's the charm The third approach was wrapping [nlplug-findfs](https://gitlab.alpinelinux.org/alpine/mkinitfs/-/blob/cc4954bc73cf55833b48624232b9c42ca3abc390/nlplug-findfs.1.in), replacing the system-wide binary, regenerating the initramfs, and then spawning SSH from there and directly interacting via libssh. Whilst this would be sensible in theory, this has a high maintenance burden if nlplug-findfs is modified substantially (or, worse, entirely removed). This is heavily in no guarantees provided land. So this one opted against it. ### approach 4: a kernel module A kernel module could start a userspace process early, which would not involve touching any of the existing tooling's code (and just needs one file added). But also, no. ## starting ssh before `initramfs-init.in` > "it's like LogoFAIL for your initfs" - somebeing, probably After roughly a few moments too many than this one'd prefer ot have thought about this, it came to the idea of [TODO: FINISH POST]