Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Phase 404 — minimal QEMU user networking proof

ItemValue
Commandmake phase 404
Underlying make target/scriptsvm/phase4/materialize-etc.sh --network, then vm/phase4/network-probe.sh
Mutates disk/image?Yes, it mounts artifacts/onix-image/onix.raw and installs bootstrap networking pieces
Boots QEMU?Yes, it runs an automated serial-controlled network proof
Main proofThe booted ONIX image configures its QEMU virtio network card and reports ONIX_NETWORK_OK iface=<name> ip=10.0.2.15 router=10.0.2.2.

The basic Linux networking idea

A Linux machine does not become networked just because a virtual network card exists.

There are several layers:

hardware / virtual device       the NIC exists
kernel driver                   Linux can talk to the NIC
interface name                  Linux exposes it as enp0s3, eth0, ...
link state                      the interface is brought up
IP address                      the interface receives an address
route                           the kernel knows where to send packets
DNS                             names can be translated to IP addresses

Phase 403 proved we can type commands inside the booted image.

Phase 404 uses that control path to prove the next base-system fact:

ONIX can bring up its first network interface and install an IPv4 route.

Why this phase uses QEMU’s static contract

The obvious first idea was DHCP.

But the current boot image still uses the borrowed Alpine kernel/initramfs/module payload from Phase 2. The module set imported in Phase 214 is intentionally small: it was just enough to mount filesystems and keep the boot proof moving.

BusyBox udhcpc needs Linux packet-socket support. In this borrowed kernel setup that support may live in a module that is not currently part of our minimal imported module set.

So Phase 404 makes a deliberate boundary decision:

do not expand kernel/module ownership inside Phase 4

Kernel and module ownership belongs to Phase 3.

Instead, Phase 404 uses the stable QEMU user-networking contract. QEMU normally gives guests this private NAT layout:

guest IP     10.0.2.15
gateway      10.0.2.2
DNS helper   10.0.2.3

That is enough to prove:

  • the virtio network device appears,
  • the kernel driver works,
  • ONIX has network tools,
  • ONIX can assign an IPv4 address,
  • ONIX can install a default route.

It is not the final network stack.

It is the first honest userspace networking proof.

What provides the network tools

Phase 404 still uses the temporary musl BusyBox payload introduced in Phase 403.

BusyBox provides small versions of early network tools:

ifconfig
ip
route
ping
nslookup
nc
netstat
wget

The important tools for this phase are:

ifconfig    bring the interface up and assign 10.0.2.15
route       install the default route through 10.0.2.2

This is old-school networking on purpose. It avoids adding a larger network manager before the base image is ready for one.

Runtime state under /run

Phase 404 writes runtime network state under:

/run/onix/network.env
/run/onix/resolv.conf

The state file looks conceptually like:

method=static-qemu-user
interface=enp0s3
ip=10.0.2.15
subnet=255.255.255.0
router=10.0.2.2
dns=10.0.2.3

It lives under /run because this is not permanent machine configuration.

That means:

reboot -> /run is empty again -> networking is configured again

The interface name is not hardcoded because Linux may rename the virtio NIC. In our current boot logs it is commonly:

enp0s3

but the script accepts the first non-loopback interface it sees.

The systemd unit

Phase 404 installs:

onix-bootstrap-network.service

into the same temporary copied systemd unit tree used by Phase 403:

/nix/store/...-systemd-.../example/systemd/system/
/persist/nix/store/...-systemd-.../example/systemd/system/

The /persist copy matters for the same reason learned in Phase 403:

/nix is bind-mounted from /persist/nix at boot

If a unit only exists in the root filesystem’s hidden pre-mount /nix, systemd may not see it after the real /persist partition is mounted.

The service runs:

/bin/sh /usr/lib/onix/bootstrap-network-up

That script:

  1. waits for a non-loopback interface,
  2. brings up lo,
  3. assigns 10.0.2.15/24 to the virtio interface,
  4. installs a default route through 10.0.2.2,
  5. writes runtime state to /run/onix/network.env,
  6. prints ONIX_BOOTSTRAP_NETWORK_READY.

The automated proof

make phase 404 has two parts.

First it mutates the image:

./materialize-etc.sh --network

That installs:

/usr/lib/onix/bootstrap-network-up
/usr/lib/onix/bootstrap-network-status
/usr/lib/onix/bootstrap-network-proof
/usr/share/onix/bootstrap/networking.txt
onix-bootstrap-network.service

Then it boots QEMU:

./network-probe.sh

The network probe reuses the Phase 403 serial shell on ttyS1.

It waits until the bootstrap shell is ready, then sends:

/usr/lib/onix/bootstrap-network-proof

That proof script waits for the network service to write /run/onix/network.env and then runs:

/usr/lib/onix/bootstrap-network-status

The phase passes only when the serial output contains:

ONIX_NETWORK_OK iface=<name> ip=10.0.2.15 router=10.0.2.2

That proves:

  • the virtio network driver loaded,
  • Linux exposed a non-loopback network interface,
  • BusyBox networking applets exist,
  • the guest has the expected QEMU NAT address,
  • the guest has a default route through QEMU.

Run it

From the repo root:

make phase 404

Expected image-mutation output includes:

network  : /usr/lib/onix/bootstrap-network-up
network  : /usr/lib/onix/bootstrap-network-status
network  : /usr/lib/onix/bootstrap-network-proof
unit     : /nix/store/.../onix-bootstrap-network.service
unit     : /persist/nix/store/.../onix-bootstrap-network.service
proof    : /usr/share/onix/bootstrap/networking.txt

Expected QEMU proof output ends with:

command : observed ONIX_NETWORK_OK iface=[^[:space:]]+ ip=10\.0\.2\.15 router=10\.0\.2\.2

==> success
Phase 404 proved minimal QEMU user networking inside the booted ONIX image.

The actual serial log contains the concrete interface name, for example:

ONIX_NETWORK_OK iface=enp0s3 ip=10.0.2.15 router=10.0.2.2

What this phase does not do

Phase 404 is not the final ONIX network architecture.

It does not decide yet:

  • whether ONIX uses systemd-networkd,
  • whether ONIX uses NetworkManager later for desktop systems,
  • where permanent DNS policy belongs,
  • how Wi-Fi is managed,
  • how static IPs are configured outside QEMU,
  • how DHCP should be provided once Phase 3 owns the full module story,
  • how user-facing network commands should look.

It only proves the smallest useful base-system networking fact:

the booted image can configure QEMU user networking and report it from inside ONIX

That is enough to continue toward remote inspection in the next phase.