Network Manager refactor

This commit is contained in:
Audiobuzz
2026-06-17 13:40:28 +00:00
parent 4b0e0135b3
commit 55aa517976
10 changed files with 198 additions and 62 deletions
+33 -10
View File
@@ -26,7 +26,8 @@ http/ks.cfg Kickstart for the throwaway build VM
files/dracut/95dot1x-macsec/ Custom dracut module (the heart of the system)
files/etc/dot1x/ Supplicant config + RADIUS CA (placeholder)
files/etc/dracut.conf.d/90-diskless.conf no-hostonly + drivers + modules
files/etc/NetworkManager/ NM unmanaged-device config
(NM unmanaged split is now runtime:
95dot1x-macsec/nm-unmanaged.sh, secure-mode only)
scripts/extract-artifacts.sh qcow2 -> kernel/initramfs/erofs+verity/cmdline
scripts/build-oci.sh ukify + sbsign + roothash gate + OCI image
serving/ Lab serving stack: dnsmasq + nginx + SPDK
@@ -75,10 +76,27 @@ instead of working around it.
1. **The supplicant must survive switch-root.** It is launched with
`exec -a @wpa_supplicant` (systemd root-storage-daemon convention) and
its state lives under `/run`. Do not “clean up” the `@`, move state off
`/run`, or hand the interface to NetworkManager — MKA times out in ~6 s
without keepalives and the root filesystem link dies. The NM
unmanaged-devices config exists for this reason; keep it in sync with
`/run`, or hand the **physical NIC** to NetworkManager — MKA times out in
~6 s without keepalives and the root filesystem link dies. The NM
unmanaged split exists for this reason (see below); keep it in sync with
interface naming.
1. **NM owns IP/DHCP; wpa_supplicant owns the physical NIC.** The initramfs
uses the `network-manager` dracut module (not `network-legacy`) so NM
**renews the DHCP lease** in the running system after switch-root — without
this the one-shot lease expired, the address was dropped, and the NVMe/TCP
root died (“keep alive timeout” / “no route to host”). The managed/unmanaged
split is therefore load-bearing and **mode-aware**:
- **Secure path:** IP rides on **`macsec0`**, which must stay **MANAGED** by
NM. The **physical NIC (`en*`)** must stay **UNMANAGED** (wpa_supplicant
owns EAPOL+MKA on it). This is enforced at runtime by the cmdline-stage
hook `nm-unmanaged.sh`, which writes
`/run/NetworkManager/conf.d/10-dot1x-unmanaged.conf` **before NM starts**.
- **Test path (`rd.dot1x=0`):** no macsec0; the physical NIC carries IP and
must be **MANAGED** so NM renews it — so the hook writes nothing.
There is intentionally **no static `99-dot1x-unmanaged.conf`** (it couldn't
be mode-aware — it wrongly unmanaged `en*` in test mode, blocking renewal).
Never add macsec0 back to an unmanaged list, and never statically unmanage
`en*` for all modes.
1. **roothash coupling is a hard gate.** `build-oci.sh` refuses to build if
the `roothash=` in the UKI cmdline ≠ `verity.json`. Never weaken, skip,
or warn-instead-of-fail this check: a mismatched UKI/rootfs pair is an
@@ -137,10 +155,15 @@ instead of working around it.
**two separate NVMe namespaces** (`rootfs.erofs` + `rootfs.hash`, distinct
pinned UUIDs), so the cmdline uses plain `systemd.verity_root_data=` /
`systemd.verity_root_hash=` by-id devices with no offset.
- `network-legacy` dracut module needs `dhclient`; RHEL 9 omits it from the
minimal install, so the provisioner installs `dhcp-client` (without it dracut
fails "module network-legacy can't be installed"). dhclient is deprecated —
the durable fix is porting the hook to the `network-manager` dracut module.
- **Network module: `network-manager` (ported 2026-06-17 from `network-legacy`).**
network-legacy's one-shot DHCP lease was never renewed after switch-root, so
at lease expiry the address was dropped and the NVMe/TCP root died. The
`network-manager` module hands its initramfs connections to the real-root NM
(state under `/run/NetworkManager`), which renews the lease. No more
`dhcp-client`/`dhclient` (deprecated). The hook drives macsec0 DHCP via `nmcli`
(not `ifup`). See invariant on the managed/unmanaged split. BENCH-VERIFY: lease
actually renews past expiry (test path); macsec0 managed + `en*` unmanaged with
MKA surviving switch-root (secure path).
- Writable root overlay is `systemd.volatile=overlay`, **not** `rootovl`:
RHEL/Rocky dracut ships no `overlayfs`/`rootovl` module. Needs
`systemd-volatile-root.service` in the initramfs (bundled by recent dracut;
@@ -164,8 +187,8 @@ These bit us bringing the build up on Rocky 9.8; they are easy to regress.
the dest to exist or the tree lands elsewhere and later `install` steps fail.
- **dracut module name** in `add_dracutmodules` omits the `NN` dir-prefix: the
directory is `95dot1x-macsec` but the module is `dot1x-macsec` (cf. `nvmf`).
- **`network-legacy` → `dhcp-client`** and **overlay → `systemd.volatile=overlay`**:
see the bench-verify items above.
- **`network-manager` dracut module** (was `network-legacy`+`dhcp-client`) and
**overlay → `systemd.volatile=overlay`**: see the bench-verify items above.
- **Test toggle**: `disable_dot1x=true` bakes `rd.dot1x=0`; the hook then skips
802.1X/MACsec and DHCPs the NIC directly for NVMe-oF on an open port. The auth
stack stays in the image, dormant. The matching lab DHCP/HTTP/NVMe-oF serving