Building a Trusted Alpine Linux Desktop on Heads #2187
Replies: 1 comment
|
@harryjwright thanks for opening this discussion, this sharing. Not sure how I can help here though. Only facts I can correct are that recent merge of #2130 temporarily improved framebuffer compatibility from coreboot to efifb (heads) to kexec final iso with simpledrm (sysfb) and simplefb and even vesafb by describing the framebuffer properly for final framebuffer OS support. So most recent OSes should work by default where they didn't before. As for booting into ram, kicksecure and tails already work on that level and is considered resolved. This is a great experiment you are doing, and I would be interested to see a repo with this work incrementing. On my side, but with limited resource, it's been a while I'm interested into creating an overlay that could be initially downloaded (we have recent android and Linux phone tethering support, where phone defines networking path if user wants VPN enforcement or anonymity) to download that overlayfs under /boot) If/when Heads reuses u-root for initramfs, we could also easily boot and cache network based minimal OS in ram, and measuring and sealing secrets based on this overlay initramfs, the user would verify and trust. Not sure where you want to go from here, but we are limited into what can fit in the SPI flash, so this project of yours would need persistence somewhere, unless it's network booted or cached on disk; this cannot completely fit in SPI, unless current CBFS size limitation (16mb)is improved on recent platforms, and the spi flash chip is >16mb to fit this:but yet again this is not realistic for fully blown OSes, unless downloaded and cached for reuse. Note that discussions, as opposed to issues, don't get notifications nor as much eyes. Thanks! |
Uh oh!
There was an error while loading. Please reload this page.
Building a Trusted Alpine 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
makecommands.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 usingapk --root /mnt. Stripped down to its core, a basic Alpine system is deceptively simple:alpine-base,alpine-baselayout,alpine-baselayout-data, andalpine-keys. From there, it was just a matter of layering on firmware for my X230 target alongsideopenrcandbusybox, 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 gettinginitramfsto 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 viaAlt+Fnbindings 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 ofdbusandseatd.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 infoot—the lightest terminal emulator I could find—layered onwaybarfor a clean, minimalist toolbar, and usedwofias 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/testingrepository, 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.
All reactions