u/True3301

Building a Trusted Alpine Ramdisk Linux Desktop on Heads

The Catalyst

Every serious systems project starts with friction. For me, it began during a period of high adversity—dealing with persistent digital harassment, compromised hardware, and an institutional grind at university that saw three years of my research systematically junked while an administration pushed to force me out through sheer attrition.

I didn't have a job, but I had time. I decided to channel that asset into tearing down the illusions of modern computing and learning cybersecurity from the silicon up. I stopped asking how to "secure" an off-the-shelf operating system and started asking a much harder question: How do you build a machine you can actually trust when you assume everything around you is hostile?

That meant looking past software patches and examining the entire trust chain—hardware, firmware, boot processes, and authentication—with zero tolerance for components I couldn't verify.

The Hardware War of Attrition

Getting Heads firmware running on a machine was the first major battle. It started with years of false starts—buying hardware without supported targets, followed by the slow, frustrating hardware degradation of my ThinkPad A275. I eventually pivoted to the X230, a machine with a mature Heads target, but the physical flashing process was its own gauntlet.

Early attempts with a cheap SOIC-8 clip were an unmitigated disaster: completely unreliable contact, wasted cycles, and endless frustration that forced me to shelve the project multiple times. Eventually, I stopped cutting corners. I ordered a Pomona clip, wired up a Raspberry Pi configured with pico-serprog, and tried again. This time, it took. After years of dead ends, I finally had a hardware-rooted boot process.

That was only the entrance fee. I had initially planned to install a conventional Linux distribution, but Heads is fiercely uncompromising. It expects a rigid, specific partition layout and cryptographic structure. Standard installers simply refused to cooperate.

So, I threw out the standard playbook and started testing what would actually survive under Heads.

Forging a Sub-OS from Scratch

Standard Alpine installations wouldn't work out of the box because of the strict partitioning demands. That friction forced a breakthrough: instead of fighting an installer, why not build the system from the ground up?

I booted into the Alpine LiveCD, brought the network online, and ignored any traditional installation routine. I plugged in a USB stick, mounted it, and started writing and running raw make commands.

How did I know that would even work? Honestly, it was pure instinct forged by breaking enough systems to understand their internal mechanics. I used the live environment as a clean, volatile base. I had used Ubuntu and Mint heavily in the past, but I had never built a Linux distribution from scratch. Fortunately, Alpine makes this remarkably straightforward.

Alpine's package manager, apk, excels at targeting external directories. I could treat the entire block device as a deployment target and manipulate it directly using apk --root /mnt. Stripped down to its core, a basic Alpine system is deceptively simple: alpine-base, alpine-baselayout, alpine-baselayout-data, and alpine-keys. From there, it was just a matter of layering on firmware for my X230 target alongside openrc and busybox, hand-crafting a full desktop that existed entirely on my terms.

Running Entirely in RAM

While experimenting with the boot parameters, I stumbled across a unique GRUB flag: copytoram. I'm not one to ignore a flag like that. I stopped and thought: Hold on a second... I can make this live entirely in RAM?

It felt like an incredible, overlooked superpower for a secure desktop. I decided right then that the OS was going to run completely in memory. To pull that off, I had to upgrade my RAM from a measly 4GB to 16GB, which instantly became a core constraint of the build. Operating straight from memory delivered a massive performance leap—roughly a 21 times speed increase over standard SATA storage.

From there, it was a long slog of bringing up devices, hammering configuration files into place under /etc, and sorting out network capabilities. Using AI as a force multiplier, I opted for the most battle-proven packages available. Most of it fell into place, except for two major walls: dynamically fetching UUIDs and the absolute pain of getting initramfs to work correctly with LUKS encryption. Once that cryptographic boot wall was breached, the system was alive.

The Hardware Root of Trust and Authentication

I don't trust smartphones or always-on network devices that map their surroundings. I needed absolute physical control. After researching options, I bypassed YubiKeys and chose a Nitrokey. It provides several independent subsystems, including GPG and FIDO, allowing the same physical token to serve multiple authentication roles.

I use the term "pseudo-biometric" loosely—it’s not a replacement for a body, but it is a replacement for the surveillance devices most people carry in their pockets.

One crucial detail when using Nitrokey hardware with Heads is understanding that Heads takes ownership of the GPG subsystem without automatically controlling the rest. In practice, you have to treat the device as multiple independent functions sharing a single piece of silicon.

That said, I have zero patience for some of the cryptographic choices baked into parts of Heads. Their reliance on ECDSA with NIST P-256 is an unnecessary hazard. ECDSA signature security hinges entirely on the per-signature nonce; if that nonce is weak or reused, the private key is instantly compromised. I would much prefer Ed25519 for its deterministic nonce generation, but the ecosystem offers little flexibility to move toward more robust constructions. I work with what I have, but with open eyes.

TTY to Wayland: Constructing the Userspace

My root account acts as a glorified TTY control center equipped with htop, bandwhich, lnav, atop, kernel monitoring via Alt+Fn bindings in /etc/inittab, and a pristine, ANSI-native Neovim setup.

Stepping from that raw environment into a graphical desktop for my primary user multiplied the system's complexity tenfold. You never escape a desktop session without encountering thousands of subtle graphical errors and log spam that can only be silenced with 2>/dev/null. The entire graphical stack rests on a fragile foundation of dbus and seatd.

To tie authentication into the desktop, I configured Linux-PAM to log me in automatically upon the physical presence of the Nitrokey. From there, I launch the Wayland compositor with dbus-run-session labwc. You might think reaching that point means the hard work is done, but it just drops you into a stark black screen to build upon from scratch. To make it usable, I brought in foot—the lightest terminal emulator I could find—layered on waybar for a clean, minimalist toolbar, and used wofi as an application launcher.

Daily Drivers and Current Frontiers

My workflow is minimal: a browser and an IDE. Alpine gives me LibreWolf, which I consider vastly superior to stock Firefox. For development, options on musl are sparse; I'm used to Zed, but Alpine's repo is limited. Fortunately, VSCodium recently landed in the /edge/testing repository, giving me a proper IDE.

Right now, I'm wrestling with the realities of running a RAM-resident OS. Heavy compilation can chew through memory fast. I've had to carve out an 8GB tmpfs specifically for development, but building projects heavy on Rust will still push it to its limits. My next step is dialing in compiler flags to optimize memory usage and establishing a dedicated carve-out on the encrypted block device for heavy persistent storage, keeping the core OS lightning-fast and entirely volatile.

reddit.com
u/True3301 — 5 days ago