Add router-on-a-stick, commit-confirm rollback and an example config

- Allow the WAN link to also carry LANs when the uplink is PPPoE on a
  VLAN with IPv6 off; only the PPP device counts as an uplink then, so
  LAN traffic can never match WAN rules.
- Add router.rollback: router-arm / router-confirm / router-rollback
  plus `nix run .#deploy`, a commit-confirm deployment flow.
- Wait for the LAN devices instead of the uplink in networkd
  wait-online, so an unplugged uplink cannot block boot or activation.
- Add examples/desktop (single NIC, PPPoE on VLAN 1001) as
  nixosConfigurations.example, built as a flake check.

Covered by the onestick and rollback VM tests and new assertion cases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 23:09:09 +01:00
co-authored by Claude Sonnet 5.5
parent 3f8f2f4199
commit 0653b5cf2f
14 changed files with 714 additions and 89 deletions
+62
View File
@@ -722,6 +722,67 @@ let
};
expect = [ "not a valid IPv6" ];
};
sharedLinkValid = {
router = {
wan = {
ipv4 = {
type = "pppoe";
pppoe = {
vlan = 1001;
username = "u";
passwordFile = "/var/lib/pw";
};
};
};
lans.main = lan { interface = "eth0"; };
};
expect = [ ];
};
sharedLinkIpv6 = {
router = {
wan = {
ipv4 = {
type = "pppoe";
pppoe = {
vlan = 1001;
username = "u";
passwordFile = "/var/lib/pw";
};
};
ipv6.enable = true;
};
lans.main = lan { interface = "eth0"; };
};
expect = [ "also used by a LAN" ];
};
sharedLinkUntaggedUplink = {
router = {
wan = {
ipv4.type = "dhcp";
};
lans.main = lan { interface = "eth0"; };
};
expect = [ "also used by a LAN" ];
};
sharedLinkVlanClash = {
router = {
wan = {
ipv4 = {
type = "pppoe";
pppoe = {
vlan = 1001;
username = "u";
passwordFile = "/var/lib/pw";
};
};
};
lans.main = lan {
interface = "eth0";
vlan = 1001;
};
};
expect = [ "used by both the PPPoE uplink and a LAN" ];
};
nonOverlappingLans = {
router.lans = {
a = lan { };
@@ -769,6 +830,7 @@ let
"ruleValid"
"wgValid"
"wanValid"
"sharedLinkValid"
];
subnet =