<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TinyComputers.io (Posts about uefi)</title><link>https://tinycomputers.io/</link><description></description><atom:link href="https://tinycomputers.io/categories/uefi.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 A.C. Jokela 
&lt;!-- div style="width: 100%" --&gt;
&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;&lt;img alt="" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/80x15.png" /&gt; Creative Commons Attribution-ShareAlike&lt;/a&gt;&amp;nbsp;|&amp;nbsp;
&lt;!-- /div --&gt;
</copyright><lastBuildDate>Thu, 18 Jun 2026 20:58:10 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>The OS That Couldn't See the Network: Native OpenBSD/arm64 Builds on AWS Graviton Metal</title><link>https://tinycomputers.io/posts/the-os-that-couldnt-see-the-network-native-openbsd-arm64-on-aws-graviton.html?utm_source=feed&amp;utm_medium=rss&amp;utm_campaign=rss</link><dc:creator>A.C. Jokela</dc:creator><description>&lt;div class="audio-widget"&gt;
&lt;div class="audio-widget-header"&gt;
&lt;span class="audio-widget-icon"&gt;🎧&lt;/span&gt;
&lt;span class="audio-widget-label"&gt;Listen to this article&lt;/span&gt;
&lt;/div&gt;
&lt;audio controls preload="metadata"&gt;
&lt;source src="https://tinycomputers.io/the-os-that-couldnt-see-the-network-native-openbsd-arm64-on-aws-graviton_tts.mp3" type="audio/mpeg"&gt;
&lt;/source&gt;&lt;/audio&gt;
&lt;div class="audio-widget-footer"&gt;31 min · AI-generated narration&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;The OS That Couldn't See the Network: Native OpenBSD/arm64 Builds on AWS Graviton Metal&lt;/h2&gt;
&lt;p&gt;I have a Rust project — a ballistics engine — that ships binaries for an embarrassing number of platforms. Linux on x86 and ARM, Windows, FreeBSD, NetBSD, and, because someone always asks and because I like the discipline of it, OpenBSD. Most of those targets are easy: a build matrix, a cross-compiler, a Docker image with the right musl toolchain, and the artifacts fall out the other end. The BSDs are where the matrix stops being polite.&lt;/p&gt;
&lt;p&gt;For FreeBSD and NetBSD on arm64 I already had a clean answer: spin up a real Graviton instance, build natively, collect the binary, terminate the instance. A build costs a few cents and finishes in minutes, because the hardware is real ARM and there's no emulation tax. I'd written a little orchestrator for exactly this — launch, build, tear down — and it worked beautifully for two of the three BSDs.&lt;/p&gt;
&lt;p&gt;OpenBSD was the one that wouldn't fall in line. And the reason is so clean, so completely a consequence of what OpenBSD &lt;em&gt;is&lt;/em&gt;, that it took me a while to stop treating it as a bug to be worked around and start treating it as a fact to be designed around.&lt;/p&gt;
&lt;p&gt;This is the story of building native OpenBSD/arm64 binaries on a cloud that OpenBSD, in the most literal sense, cannot see.&lt;/p&gt;
&lt;h3&gt;Why native, and why that's suddenly hard&lt;/h3&gt;
&lt;p&gt;The honest first question is whether native builds matter at all. Couldn't I cross-compile OpenBSD/arm64 binaries from Linux and skip the whole circus?&lt;/p&gt;
&lt;p&gt;For a trivial program, maybe. For anything real, no. Cross-compiling to OpenBSD means reproducing its libc, its linker behavior, its system call conventions, and its packaging quirks in a toolchain that lives somewhere else — and then trusting that the binary you produced behaves the way a binary built &lt;em&gt;on&lt;/em&gt; OpenBSD would. The entire value of shipping an OpenBSD artifact is the claim "this was built and linked on the platform it runs on." A cross-compiled binary that mostly works is worse than no binary at all, because it fails in ways your users discover and you can't reproduce.&lt;/p&gt;
&lt;p&gt;So: native. Build it on OpenBSD/arm64, on real ARM silicon, the way the platform's own users would.&lt;/p&gt;
&lt;p&gt;The old way to get there was emulation — QEMU on an x86 host, software-emulating an ARM CPU. It works, and it's miserably slow: with no hardware virtualization to lean on, every guest instruction gets translated, and a four-minute build stretches to twenty-five. I did not want to go back.&lt;/p&gt;
&lt;p&gt;The new way was supposed to be the Graviton instance: real ARM cores, native speed, terminate when done. It works for FreeBSD. It works for NetBSD. And then you try it with OpenBSD and walk straight into the wall.&lt;/p&gt;
&lt;h3&gt;The wall: OpenBSD has no driver for AWS's network card&lt;/h3&gt;
&lt;p&gt;Here is the entire problem, and it is almost funny once you see it.&lt;/p&gt;
&lt;p&gt;Modern EC2 instances present their network to the guest through the &lt;strong&gt;Elastic Network Adapter&lt;/strong&gt; — &lt;code&gt;ena&lt;/code&gt;, a custom Amazon device with a custom driver. Every cloud-friendly OS ships that driver: Linux has it, FreeBSD has it, NetBSD's community AMIs have it. It is the thing that lets an instance have a network at all.&lt;/p&gt;
&lt;p&gt;OpenBSD's arm64 kernel does not have an &lt;code&gt;ena&lt;/code&gt; driver.&lt;/p&gt;
&lt;p&gt;This isn't an oversight, and it isn't a slight. OpenBSD is a small, fiercely curated tree. Drivers get in because someone runs the hardware, writes clean code, and maintains it — and effectively nobody runs OpenBSD as a first-class EC2 guest, so the driver for Amazon's proprietary NIC simply isn't there. The project doesn't chase cloud hardware the way a commercial OS does, and that restraint is a feature, not a failing. But it has a consequence: an OpenBSD/arm64 instance on EC2 boots, comes up, and finds &lt;strong&gt;no network interface it understands.&lt;/strong&gt; The NIC is right there on the PCI bus, and the kernel has nothing to bind to it.&lt;/p&gt;
&lt;p&gt;An EC2 instance you cannot reach over the network is not an instance. It's a billable void. There's no SSH, no console you can usefully drive, no way to hand it a build and get a binary back. The OS runs perfectly; it just can't talk to the one piece of hardware that makes a cloud instance a thing you can use.&lt;/p&gt;
&lt;p&gt;I sat with that for a bit. You can't add the driver from outside. You can't give OpenBSD a NIC it understands by configuring the instance differently, because AWS only offers &lt;code&gt;ena&lt;/code&gt;. The platform and the OS disagree about reality at the level of the network card, and neither one is going to move.&lt;/p&gt;
&lt;p&gt;So I stopped trying to make them agree.&lt;/p&gt;
&lt;h3&gt;Stop asking OpenBSD to talk to AWS&lt;/h3&gt;
&lt;p&gt;The move, once it arrived, was obvious in the way these things always are in retrospect: &lt;strong&gt;don't let OpenBSD touch the cloud's hardware at all.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Put a Linux host on the metal. Linux has the &lt;code&gt;ena&lt;/code&gt; driver; it brings the network up without complaint. Then run OpenBSD as a &lt;strong&gt;virtual machine inside that Linux host&lt;/strong&gt;, under QEMU with KVM acceleration — and hand the guest the kind of hardware OpenBSD &lt;em&gt;does&lt;/em&gt; understand: virtio. OpenBSD has had solid virtio drivers for years. It sees a &lt;code&gt;virtio&lt;/code&gt; network card and a &lt;code&gt;virtio&lt;/code&gt; disk and is perfectly happy, never knowing or caring that the physical NIC underneath is an Amazon device it couldn't have spoken to directly.&lt;/p&gt;
&lt;p&gt;The Linux host owns the &lt;code&gt;ena&lt;/code&gt; and the public IP. The OpenBSD guest lives behind it on a private virtual network, reachable through a port forward. The two layers each get hardware they recognize, and the impedance mismatch — the missing driver — simply stops mattering, because the only thing that ever talks to the &lt;code&gt;ena&lt;/code&gt; is Linux.&lt;/p&gt;
&lt;p&gt;It's the same shape as a hundred other infrastructure problems: when two layers can't agree, you don't force them, you put a translator between them. Here the translator is an entire hypervisor, and the thing being translated is the basic question of what a network card is.&lt;/p&gt;
&lt;p&gt;This also quietly solves the speed problem that made x86 emulation unbearable. Because the host is itself ARM, KVM can run the ARM guest at near-native speed — no instruction translation, just virtualization. OpenBSD/arm64 on an ARM host under KVM boots in seconds and builds at real-hardware pace. The thing that was slow about the old emulation approach was never "virtualization"; it was &lt;em&gt;cross-architecture&lt;/em&gt; emulation. Match the architectures and the tax disappears.&lt;/p&gt;
&lt;h3&gt;Why it has to be bare metal&lt;/h3&gt;
&lt;p&gt;There's a catch, and it's the reason this costs more than a few cents.&lt;/p&gt;
&lt;p&gt;KVM needs hardware virtualization extensions, and on AWS those are only exposed to the guest OS on &lt;strong&gt;bare-metal instances&lt;/strong&gt;. On an ordinary virtualized Graviton instance, the Nitro hypervisor already owns the CPU's virtualization layer; your kernel can't open &lt;code&gt;/dev/kvm&lt;/code&gt; because something else is already standing where KVM would stand. Try to accelerate QEMU on a normal instance and it silently falls back to the slow software path — right back to the emulation tax I was trying to escape.&lt;/p&gt;
&lt;p&gt;So the host has to be &lt;code&gt;.metal&lt;/code&gt;. The cheapest bare-metal Graviton AWS sells is &lt;code&gt;a1.metal&lt;/code&gt; — first-generation Graviton, sixteen Cortex-A72 cores, and, crucially, a real &lt;code&gt;/dev/kvm&lt;/code&gt; exposed to the host kernel. It's about forty-one cents an hour on demand. That's more than the few-cents-per-build the native FreeBSD path costs, but a build spins the instance up, runs, and terminates in fifteen or twenty minutes, so a release still costs well under a dollar.&lt;/p&gt;
&lt;p&gt;I picked Ubuntu for the Linux host — its QEMU and UEFI firmware packages are exactly what the recipe wants — pointed it at the right ARM AMI, and gave it a roomy root volume. The host comes up, &lt;code&gt;apt&lt;/code&gt; installs QEMU and the AAVMF UEFI firmware, and now I have an ARM machine with KVM, ready to boot an OpenBSD guest. That part was easy.&lt;/p&gt;
&lt;p&gt;The part that ate an afternoon was getting OpenBSD to actually &lt;em&gt;attach its own disks.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Two device-tree gotchas that ate an afternoon&lt;/h3&gt;
&lt;p&gt;QEMU's generic ARM machine type, &lt;code&gt;virt&lt;/code&gt;, gives you a clean, modern, device-tree-described board. You hand it virtio devices and it wires them up. I did the obvious thing — a virtio block device for the installer image, a virtio block device for the target disk, a virtio network device — booted, and watched the OpenBSD installer come up, reach the disk-selection step, and announce:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;Available disks are: none.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No disks. Also, quietly, no network interface. Both virtio devices were &lt;em&gt;there&lt;/em&gt; — UEFI had even booted the installer kernel off one of them — and yet the running OpenBSD kernel saw neither.&lt;/p&gt;
&lt;p&gt;The cause is a transport mismatch that's easy to miss. On the &lt;code&gt;virt&lt;/code&gt; machine, &lt;code&gt;virtio-blk-device&lt;/code&gt; and &lt;code&gt;virtio-net-device&lt;/code&gt; use the &lt;strong&gt;virtio-MMIO&lt;/strong&gt; transport — devices described in the device tree, sitting at fixed memory addresses. UEFI can boot from those. OpenBSD's arm64 kernel, it turns out, does not attach them. What it &lt;em&gt;does&lt;/em&gt; attach is &lt;strong&gt;virtio-PCI&lt;/strong&gt; — the same virtio devices presented as PCI devices on the PCIe controller the kernel already probes. Swap &lt;code&gt;virtio-blk-device&lt;/code&gt; for &lt;code&gt;virtio-blk-pci&lt;/code&gt; and &lt;code&gt;virtio-net-device&lt;/code&gt; for &lt;code&gt;virtio-net-pci&lt;/code&gt;, and suddenly the disks appear as &lt;code&gt;sd0&lt;/code&gt; and &lt;code&gt;sd1&lt;/code&gt; and the NIC as &lt;code&gt;vio0&lt;/code&gt;. One word per device, and the installer can see the world.&lt;/p&gt;
&lt;p&gt;That fixed the disks. The very next boot hung.&lt;/p&gt;
&lt;p&gt;Not crashed — &lt;em&gt;hung.&lt;/em&gt; The kernel probed all the devices, printed them, and then stopped cold, right before mounting its root filesystem. The host's load average sat at zero: the guest CPU wasn't spinning, it was blocked, waiting for something that was never going to come. The something was an interrupt.&lt;/p&gt;
&lt;p&gt;virtio-PCI devices default to MSI-X — message-signaled interrupts, delivered on ARM through the GIC's Interrupt Translation Service. On this first-generation Graviton host, under KVM, that MSI path doesn't deliver. The guest arms its interrupts, waits for the first one, and waits forever. The fix is to tell QEMU to give each virtio device zero MSI-X vectors, forcing it back to plain old pin-based (INTx) interrupts, which ride the GIC's distributor directly and work fine:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;-device virtio-blk-pci,drive=hd0,bootindex=1,vectors=0
-device virtio-net-pci,netdev=net0,vectors=0
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;vectors=0&lt;/code&gt; on every virtio device, the device line in the boot log changes from &lt;code&gt;msix&lt;/code&gt; to a plain &lt;code&gt;irq&lt;/code&gt;, the kernel gets its interrupt, mounts root, and reaches the installer prompt. Two one-line changes — the PCI transport and the disabled MSI-X — separated by an afternoon of staring at a boot that stopped in exactly the same place every time.&lt;/p&gt;
&lt;p&gt;Neither of these is in the friendly "run OpenBSD under QEMU" recipes you'll find, because those recipes assume a host where MSI-X works and where someone already knew to use the PCI transport. The combination of &lt;em&gt;this&lt;/em&gt; OS on &lt;em&gt;this&lt;/em&gt; generation of silicon under &lt;em&gt;this&lt;/em&gt; hypervisor is niche enough that you find the edges yourself.&lt;/p&gt;
&lt;h3&gt;Installing an OS through a serial straw&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;virt&lt;/code&gt; machine has no graphics — no VGA, no framebuffer worth the name. OpenBSD's installer comes up on the serial console, which QEMU helpfully wires to standard out. That's fine for a human at a keyboard. It's less fine when you're trying to make the whole thing repeatable, because the OpenBSD installer is a long, interactive conversation: hostname, network, disk, sets, passwords, two dozen prompts.&lt;/p&gt;
&lt;p&gt;OpenBSD has an answer for this — &lt;code&gt;autoinstall&lt;/code&gt;, where a response file answers every prompt and the install runs unattended. I tried it first, serving the response file over HTTP from the Linux host. It failed in an instructive way: QEMU's built-in user-mode network doesn't advertise an autoinstall server in its DHCP lease, and when the installer falls back to asking &lt;em&gt;where&lt;/em&gt; the response file is, it tries to fetch it before the guest's network is actually up. The fetch fails, autoinstall aborts, and you're dropped to a shell. The unattended path assumes a network environment QEMU's toy DHCP doesn't provide.&lt;/p&gt;
&lt;p&gt;So the install came down to driving the interactive program by hand — except I didn't drive it. I let Claude drive, programmatically: QEMU running inside a &lt;code&gt;tmux&lt;/code&gt; session, the agent feeding the serial console one answer at a time and reading the screen back between each step. It's a strange way to install an operating system — an AI typing into a virtual serial port through a terminal multiplexer over SSH — and it fumbled in telling ways. It stuffed answers ahead of the prompts and desynced, at one point confidently typing &lt;code&gt;vio0&lt;/code&gt; into the &lt;em&gt;DNS domain name&lt;/em&gt; field because it had guessed the question order and the installer disagreed; a mismatched password pair followed, and I watched it back out and resynchronize. Once it was reading each prompt instead of predicting it, the rest was deterministic, and it pulled the install sets straight off the installer image so the guest never needed working DNS at all. Whole-disk GPT, auto layout, sets from the local media, and a few minutes later: &lt;code&gt;CONGRATULATIONS! Your OpenBSD install has been successfully completed!&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Drop the installer image, reboot from the disk alone, and the installed system comes up on its own — generates its host keys, starts &lt;code&gt;sshd&lt;/code&gt;, reaches a login prompt. &lt;code&gt;uname&lt;/code&gt; confirms it: OpenBSD 7.9, arm64, on a "QEMU KVM Virtual Machine." A real, persistent OpenBSD/arm64 system, running on a cloud that can't host it directly.&lt;/p&gt;
&lt;h3&gt;Making it ephemeral: the golden image and the one-button build&lt;/h3&gt;
&lt;p&gt;A hand-installed VM is a proof of concept, not a build server. The point was always to make this &lt;em&gt;disappear into a command&lt;/em&gt; — spin the whole stack up, build, collect the artifact, spin it down, and pay pennies.&lt;/p&gt;
&lt;p&gt;So I did the slow part exactly once. I took that freshly installed guest, added the toolchain a build needs — git, the Rust compiler — and a build key whose public half lives in the image's &lt;code&gt;authorized_keys&lt;/code&gt;. Then I shut it down cleanly and compressed the disk: a 20 GB virtual volume holding maybe two gigs of real data squeezed down to an 832 MB qcow2. That &lt;strong&gt;golden image&lt;/strong&gt; went into S3, in the same region as the metal hosts, so pulling it back down is fast and free.&lt;/p&gt;
&lt;p&gt;Around it I wrote an orchestrator — the OpenBSD sibling of the FreeBSD/NetBSD tool I already had. One command does the whole dance: launch an &lt;code&gt;a1.metal&lt;/code&gt;, wait for it, install QEMU, pull the golden image from S3 through a presigned URL (so the host needs no AWS credentials of its own), boot the OpenBSD guest with the exact virtio-PCI-and-&lt;code&gt;vectors=0&lt;/code&gt; incantation the afternoon taught me, and wait for the guest's SSH to answer. The guest is reachable only through a port forward on the host, so the orchestrator jumps through the host to reach it — the build key never leaves my laptop, and no extra port is ever opened to the world. Then it pipes the build into the guest, runs it natively, copies the binary back out, checksums it, and — in a &lt;code&gt;finally&lt;/code&gt; block, so it happens whether the build succeeds, fails, or throws — &lt;strong&gt;terminates the metal host.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Spin up, build, collect, spin down. The instance exists for the length of one build and then it's gone, and the bill is loose change.&lt;/p&gt;
&lt;h3&gt;The last wall: the build that wouldn't build&lt;/h3&gt;
&lt;p&gt;I ran the orchestrator end to end, and it was beautiful right up until the part that mattered. It launched the host, pulled the image, booted OpenBSD, SSH'd in, started the build — and the build died compiling a TLS library, deep in my engine's dependency tree.&lt;/p&gt;
&lt;p&gt;I knew exactly what it was. Or I thought I did. My ballistics engine has an optional "online" feature, on by default, that pulls in an HTTP client and with it a whole TLS stack — &lt;code&gt;rustls&lt;/code&gt;, the &lt;code&gt;ring&lt;/code&gt; crypto backend, the works. Of course &lt;em&gt;that&lt;/em&gt; was the thing that wouldn't build on an OS this far off the beaten path. I turned the feature off, the build went green, and I jotted down a tidy little lesson about exotic platforms and the liabilities of convenient defaults.&lt;/p&gt;
&lt;p&gt;The lesson was wrong, and I found out a few hours later. The release binary that already ships for this exact platform has that entire TLS stack compiled into it — &lt;code&gt;rustls&lt;/code&gt; builds on OpenBSD/arm64 perfectly well. So that was never the wall. The real wall was disk. OpenBSD's installer auto-layout splits the disk into a fistful of small partitions, and the build was running in &lt;code&gt;/tmp&lt;/code&gt; — about a gigabyte. A Rust release &lt;code&gt;target/&lt;/code&gt; directory does not fit in a gigabyte, and &lt;code&gt;rustls&lt;/code&gt; happens to be a large crate, so the partition filled mid-compile and the compiler fell over with an error that &lt;em&gt;looked&lt;/em&gt; like a code problem. Turning off the feature "fixed" it only because a leaner build squeaked under the limit. The actual fix was one line — build in &lt;code&gt;/usr/obj&lt;/code&gt;, the roomy partition OpenBSD hands you for exactly this — and with room to work, the full build, TLS and all, finishes fine.&lt;/p&gt;
&lt;p&gt;Here's the part that stings, and the reason I'm telling it on myself. I am not new to this. I've dabbled in the BSDs for a long time — FreeBSD was my daily driver in the early 2000s — and I know OpenBSD well enough that its installer holds no surprises; it has barely changed in twenty years. "OpenBSD carves the disk into small partitions and you do your building in &lt;code&gt;/usr/obj&lt;/code&gt;" is not arcana to me, it's reflex. A version of me at the keyboard would have read &lt;em&gt;compiler died, OpenBSD, &lt;code&gt;/tmp&lt;/code&gt;&lt;/em&gt; and smelled &lt;strong&gt;out of disk&lt;/strong&gt; before finishing the line. But I wasn't at the keyboard — I'd handed it to the same agent that, a few screens earlier, had typed &lt;code&gt;vio0&lt;/code&gt; into the DNS field. An agent has read about OpenBSD without ever once running out of disk on it, so it had no instinct for the boring failure. It reached instead for the exotic one sitting right there in the dependency graph — the explanation that was plausible, pre-loaded, and a little flattering, because if the crypto stack won't compile you're wrestling something genuinely hard, rather than something you'd have caught in 2003.&lt;/p&gt;
&lt;p&gt;And that is the trap worth naming, sharper than "niche platforms are hard." On an unfamiliar system every failure &lt;em&gt;presents&lt;/em&gt; as exotic; the strange explanation announces itself and the mundane one doesn't. &lt;strong&gt;The further off the beaten path you are, the more deliberately you have to rule out the boring thing first — because out here everything wears the platform's costume, and an out-of-disk error in a one-gigabyte &lt;code&gt;/tmp&lt;/code&gt; looks exactly like a dependency that can't be built, right up until someone who's been burned before tells you it's just disk.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;What it actually was about&lt;/h3&gt;
&lt;p&gt;Step back and the whole project rhymes with a pattern I keep meeting. The headline problem — "build OpenBSD/arm64 binaries on AWS" — has a one-sentence answer once you have it: run OpenBSD as a KVM guest on a bare-metal Graviton host. That sentence is the &lt;em&gt;easy&lt;/em&gt; part. Everything real lived in the gap between two systems that were each, on their own terms, completely correct.&lt;/p&gt;
&lt;p&gt;OpenBSD is correct to omit a driver for hardware almost none of its users run; its restraint is exactly why it's OpenBSD. AWS is correct to present its network through a custom adapter built for the scale it operates at. Neither is wrong. They simply grew up with no expectation of meeting, and the moment you ask them to share a machine, every quiet assumption each one made surfaces at once — the missing driver, the MMIO-versus-PCI transport, the MSI-X interrupts that don't land on first-gen silicon, the DHCP lease that doesn't carry what the installer hoped, the cramped &lt;code&gt;/tmp&lt;/code&gt; masquerading as a dependency that wouldn't compile.&lt;/p&gt;
&lt;p&gt;The hypervisor in the middle isn't really there to virtualize a CPU. It's there to be the place where two designs that disagree about what hardware &lt;em&gt;is&lt;/em&gt; can both be right at the same time. OpenBSD gets virtio and is happy. AWS gets &lt;code&gt;ena&lt;/code&gt; and is happy. The seam between them holds because something whose entire job is to translate sits exactly on it.&lt;/p&gt;
&lt;p&gt;And the build server that came out the other end is genuinely good: a single command that conjures an ARM machine, runs a native OpenBSD build at full speed, and dissolves the machine when it's done, for the price of a vending-machine snack. The operating system that couldn't see the network now turns out release binaries on the very cloud it can't directly run on — because at no point does anyone ask it to see the network. That was never going to work. The trick was to stop asking.&lt;/p&gt;</description><category>aarch64</category><category>arm64</category><category>aws</category><category>bare metal</category><category>bsd</category><category>build server</category><category>ci</category><category>cross-compilation</category><category>ec2</category><category>graviton</category><category>infrastructure</category><category>kvm</category><category>openbsd</category><category>qemu</category><category>rust</category><category>uefi</category><category>virtio</category><category>virtualization</category><guid>https://tinycomputers.io/posts/the-os-that-couldnt-see-the-network-native-openbsd-arm64-on-aws-graviton.html</guid><pubDate>Thu, 18 Jun 2026 19:45:00 GMT</pubDate></item></channel></rss>