Phase 404 — minimal QEMU user networking proof
| Item | Value |
|---|---|
| Command | make phase 404 |
| Underlying make target/scripts | vm/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 proof | The 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:
- waits for a non-loopback interface,
- brings up
lo, - assigns
10.0.2.15/24to the virtio interface, - installs a default route through
10.0.2.2, - writes runtime state to
/run/onix/network.env, - 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.