router: stagingPort option, move gw-cnx-1 staging uplink into it

The pre-cutover DHCP-client uplink into the old LAN was a hand-written
systemd.network block in the gw-cnx-1 machine config. Make it a router
setting next to trunkPorts/accessPorts so every replacement gateway can
stage the same way, with an assertion that the port is not also the WAN,
a trunk or an access port. gw-cnx-1 sets stagingPort = "enp3s0" in the
inventory; the machine-local block is gone.
This commit is contained in:
2026-09-16 08:30:14 +00:00
parent c0c2193429
commit c9b04711c9
6 changed files with 57 additions and 33 deletions
+19 -1
View File
@@ -21,6 +21,16 @@ in
assertion = lib.all (p: !(cfg.accessPorts ? ${p})) cfg.trunkPorts;
message = "router: a port cannot be both a trunk and an access port.";
}
{
assertion =
cfg.stagingPort == null
|| !(
cfg.stagingPort == cfg.wan.interface
|| lib.elem cfg.stagingPort cfg.trunkPorts
|| cfg.accessPorts ? ${cfg.stagingPort}
);
message = "router: stagingPort ${toString cfg.stagingPort} is also the WAN, a trunk or an access port.";
}
];
# Router diagnostics toolkit: packets (tcpdump), path (mtr), link
@@ -73,7 +83,15 @@ in
let
taggedAll = lib.mapAttrsToList (_: vlan: { VLAN = vlan.id; }) cfg.vlans;
in
{
lib.optionalAttrs (cfg.stagingPort != null) {
# Staging uplink (see interface.nix): plain DHCPv4 client on a spare
# port, no bridge/VLAN membership, so the firewall treats it as untrusted.
"05-staging" = {
matchConfig.Name = cfg.stagingPort;
networkConfig.DHCP = "ipv4";
};
}
// {
# WAN port carries only the PPPoE session; no IP config of its own.
"10-wan" = {
matchConfig.Name = cfg.wan.interface;