Boot Naked Linux

abnercoimbre1 pts0 comments

Boot Naked Linux · ... and another thing ...

... and another thing ...

Boot Naked Linux

2026-05-19

linux

Starting up a Linux kernel to host one single process rather than a full on operating system ... and doing it in less than a second!

When I was a kid, computers weren’t coddled and<br>left running 24/7, when you were done with them you switched them off, and<br>when you wanted them again you just switched them on and within a second or<br>so they’d be loading whatever was in their disk drive.

There was a brief moment in the early 2000s where the newly introduced<br>SSDs made booting quick but as always the tech industry has taken up the<br>slack until even a 16 core monster with a fast SSD still takes a minute<br>to get its feet under it.

So I wanted to try an alternative.<br>Keep the Linux kernel but strip away everything else I could.<br>Here goes … well not quite here goes nothing, but here goes a lot less.

UPDATE: As per long tradition, while trying to fix a couple of details<br>I found “Building a tiny Linux from scratch”<br>which does most of what I do here but in Rust and a year ago,<br>so that’s worth a look too.

Hello, World!

The first thing a Linux system does is run an “init” program of one sort<br>or another which loads all the other processes and configurations and stuff.<br>There’s nothing too special about this program, it’s just a regular<br>executable or script, and there have been a few different approaches taken<br>over the years in any case.

So we can write a new one in C … here’s init.c:

#include<br>#include<br>#include

int main(int argc, char **argv) {<br>fprintf(stderr, "Hello from init.c!");<br>reboot(RB_POWER_OFF);

All it does is print a message, and then reboot the computer.

If our init process exits the kernel panics, so instead of busy waiting1<br>or sleeping forever or whatever, we use reboot(RB_POWER_OFF) to shut the<br>virtual machine down in an orderly manner.

Making initrd

Modern Linux supports<br>quite a complex multi-stage process.<br>There’s a lot of<br>resources<br>out there, and a lot of them are 20 years out of date, and<br>there have been changes<br>but here’s a summary of how I think it works right now,<br>as of 2026 and Linux 6.8 or thereabouts:

A boot loader runs with a kernel and a dummy filesystem called ‘initrd’.

The kernel attempt to unpack the ‘initrd’ file into an ‘initramfs’, a<br>root filesystem in RAM which allows initialization tools to run.

it looks for a file called /init (or whatever is specified in the<br>rdinit= kernel parameter)

if it exists, it runs it and that process takes over initialization.

Otherwise, it falls back to:

mount the root partition specified by the root= kernel parameter

mount the devtmpfs filesystem at /dev

run /init (or whatever is specified in the init= kernel<br>parameter) from that.

Otherwise, or if the init process exits, it kernel panics.

Most modern distros use the first branch: quite a large initrd filesystem is<br>provided so that modules and firmware can get loaded before attempting to<br>boot the real filesystem.<br>The initrd file which my PC boots from is 73MB and according to lsintramfs<br>it contains 2163 files!

There’s a few examples of how to<br>construct a filesystem with a<br>replacement for init<br>but I wanted to go even simpler and replace the entire initrd.

If we compile our example code statically, eg: containing all the libraries it<br>needs, we can make our own initrd with only one file in it:

gcc -static init.c -o init

echo 'init' | cpio -o --format=newc | gzip -c > initrd

about cpio

cpio is a very weird and ancient program with a command line<br>which makes tar look user-friendly.<br>But let’s not worry about the details for now.

I will note that, later, if you get a kernel message:

Initramfs unpacking failed: no cpio magic

… it means that either the cpio format or the compression or something<br>similar isn’t compatible with your kernel. The kernel will attempt to<br>continue, but a later error message like:

check access for rdinit=/init failed: -2, ignoring

… means that either the initramfs didn’t happen or your binary is<br>in the wrong place (-2 is -ENOENT which means file not found).<br>You might also get a message about incompatible architectures.<br>This message happens pretty early in the boot process, which attempts to<br>continue anyway, so you’ll have to look back carefully.<br>Whereas if you see:

Trying to unpack rootfs image as initramfs...

… and then nothing else, that’s a good sign. It never logs that it was<br>successful until much later when it should hopefully say:

Run /init as init process

Incidentally, if you’re looking to pack many files into a cpio archive,<br>you want something along the lines of:

(cd $SOURCE_DIR; find . | cpio -o -H newc) | gzip -c > $OUTPUT_FILE

The whole thing about piping in a list of files probably seems<br>perverse but cpio is older than tar, older than shell filename<br>globbing so perhaps we can forgive it

Virtualized

Getting this going on real hardware would involve an irritating<br>amount of USB key swapping,<br>so I’m using QEMU to make a virtual...

init kernel linux initrd cpio process

Related Articles