Generate host-side microVM networking on nexus #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "agent/microvm-host-network"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Generates the host-side networking the microVM guests will attach to: the
microvm0bridge, them-*TAP attachment policy, the manager split with NetworkManager, and egress for192.168.123.0/24.This module imports nothing from microvm.nix, composes no host module, and declares no guest, which is why it is implementable now:
allod/vmandallod/archetypescarry zeromicrovmreferences today, and this slice needs none of them.Refs vnprc/notes#73
What changes on nexus
The starting state was verified against the composed configuration, not assumed:
systemd.network.enablewasfalse,systemd.network.wait-online.enablewastrue, NetworkManager owned every link,services.resolved.enablewasfalse, and/etc/qemu/bridge.confwasallow virbr0.networkd runs on this host for the first time. It matches
microvm0andm-*and nothing else, so every other link stays unmatched and therefore NetworkManager's.systemd.network.wait-online.enableis set tofalsebecause NetworkManager is responsible for this host's internet connection — upstream's own documentation names exactly that case — and leaving the default would risk a boot-time wait, and a timeout, on an interface set networkd was never meant to own.Egress is
networking.natwithinternalIPs = [ "192.168.123.0/24" ]and noexternalInterface, which emits exactlyiptables -w -t nat -A nixos-nat-post -s '192.168.123.0/24' -j MASQUERADE. Source-based on purpose: binding it to the uplink interface name would need a live-host fact and would break when NetworkManager renames or replaces that interface. IPv4 forwarding is not re-declared;net.ipv4.ip_forwardis alreadytruein the composed configuration.No firewall input is opened on the bridge. That is expressed as absence rather than as an empty per-interface block, because an "empty"
networking.firewall.interfaces.<name>block still generates interface-named rules. The deploy-side check asserts the absence.There is no DHCP server, reservation, lease file, or resolver on this network. Static inventory ownership plus TAP teardown is the whole lifecycle, which is why nothing here has a
virsh net-update,dhcp_release, orvirbr0.statuscounterpart. The libvirt path keeps all of those, untouched.The network values live in one file,
modules/microvm-host-network-values.nix, exported aslib.microvmHostNetwork. The nexus module and themicrovm-networkcheck invnprc/deployboth derive from it, so neither carries a second copy of the bridge name or the prefix (architecture.mdprinciple 8).A host-wide default this turns on, decided explicitly
Turning networkd on flips one default nobody asked for. nixpkgs' networkd module sets
services.resolved.enable = mkDefault true, and on this host that would replace NetworkManager'sresolv.confwith the resolved stub, addsystemd-resolved.serviceand/etc/systemd/resolved.conf, and removeresolvconf.service— a second resolver stack on a live desktop hypervisor, for a feature nothing in this arc needs. This is the same shape as thehardware.ksm.enablefinding the dev plan records against the public host module, and it gets the same treatment: the value is decided explicitly in the private layer (services.resolved.enable = false), and the deploy-side check asserts the chosen value so a later upstream default change is a build failure rather than a silent DNS change on a live host.With that pinned, the full generated delta against the pre-change nexus configuration is exactly:
systemd-networkd,systemd-networkd-wait-online,systemd-networkd-wait-online@(the latter two generated withenable = false, so no unit file is installed)systemd-networkdenvironment.etc:systemd/network/40-microvm0.netdev,systemd/network/40-microvm0.network,systemd/network/41-microvm-tap.network,systemd/networkd.confnetwork-setup.service,resolvconf.service,/etc/resolv.confhandling, and every libvirt artifact are unchanged.Risk
R3. This changes generated host networking on a live desktop hypervisor that also runs every libvirt domain, so a bad composition disturbs more than the first guest. Three specific residuals for human scrutiny:
Running a second network manager alongside NetworkManager is the substantive change. The mitigation is that networkd matches only two link names, both unmanaged in NetworkManager, and
wait-onlineis off so nothing gates boot. Every.networkis required by the check to pin[Match] Nameand to use no other match key, because a.networkwith an empty[Match]claims every link on the host.The NAT module raises
net.ipv4.conf.all.forwardingtotrueatmkOverride 99. On this host that knob is the same kernel setting asnet.ipv4.ip_forward, which is alreadytrue, so the runtime effect is nil and the declaration merely becomes coherent — but it is a declared change and is called out rather than buried.The masquerade rule has no output-interface binding, so it applies to traffic from the microVM prefix leaving any interface. Traffic that stays on
microvm0is bridged rather than routed and does not traverse the nat POSTROUTING hook, so this is the intended source-based shape. It is stated here because the alternative reading — an! -o microvm0clause — has nonetworking.natoption and would have to be hand-written into the firewall script, which is more fragile and less checkable.Not in this PR, and deliberately: no microvm.nix import, no host module composition, no guest configuration, no per-machine microVM addresses, no ramfs, no volumes, no launcher. Those wait on the plan's Agent Gate —
allod/strategy#22landing at its canonicalmasterpath, andallod/nexus#21,#22,#23landing.Nothing here has been activated. Host build, activation, and any live network change remain human-only.
Validation
nix flake check path:<profiles>passes.nix build --no-link path:<deploy>#nixosConfigurations.nexus.config.system.build.toplevelwith this branch overridden in builds successfully. All eightnixosConfigurationsstill evaluate, and every existingdeploy#checks.x86_64-linux.*check passes.The generated networkd units are exactly three files: a
microvm0bridge netdev; amicrovm0.networkcarryingAddress=192.168.123.1/24,ConfigureWithoutCarrier=true,RequiredForOnline=no, and no DHCP or DNS; and anm-*.networkcarryingBridge=microvm0andRequiredForOnline=no.The paired
deploy#checks.x86_64-linux.microvm-networkcheck (vnprc/deploy PR) asserts all of this against the generated artifacts and carries the sabotage evidence:wait-onlinere-enabled, the masquerade bound to an uplink name, a firewall input opened on the bridge, a third.networkmatch, a.networkwith no[Match] Name, a DHCP server on the bridge, a resolver on the bridge,services.resolvedleft at the networkd default, libvirt disabled,/etc/qemu/bridge.confwidened toallow all, and the TAP match repointed off the bridge — each fails with its own message, and the restored copy re-runs clean.