From 19e1acda51356dabc0a4c8ff81b886ffebeede93 Mon Sep 17 00:00:00 2001 From: Berwn Date: Fri, 31 Jul 2026 11:39:54 +0700 Subject: [PATCH] Renumber gw-cnx-1 to the fleet addressing scheme (OPNsense replacement) The newedge.house site adopts the 10.1..0/24 convention: mgmt 10 (the old untagged LAN), lan 20, iot 40, voip 50, dmz 60, unit1-5 110-150. PPPoE is untagged at this site. Static leases move to a new per-VLAN dhcp.reservations option rendered into Kea host reservations. --- docs/src/gateways.md | 10 +++++++--- machines/gw-cnx-1/configuration.nix | 27 +++++++++++++++++++++++++-- modules/router/default.nix | 19 +++++++++++++++++++ modules/router/dns-dhcp.nix | 5 +++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/docs/src/gateways.md b/docs/src/gateways.md index b9916fb..8a2c591 100644 --- a/docs/src/gateways.md +++ b/docs/src/gateways.md @@ -42,9 +42,13 @@ should also shorten `dhcp.leaseTime` (default 86400 s) so the pool recycles. First user: `gw-cnx-2` (site 2) runs the public WiFi — guest VLAN 30 at `10.2.128.0/22`, pool `10.2.128.100 – 10.2.131.250`, `dhcp.leaseTime = 3600`. -| Site | siteId | mgmt | lan | -| ---- | ------ | -------------- | -------------- | -| cnx | 1 | `10.1.10.0/24` | `10.1.20.0/24` | +| Site | siteId | mgmt | lan | site-specific VLANs | +| ---- | ------ | -------------- | -------------- | --------------------------------------------------------------- | +| cnx | 1 | `10.1.10.0/24` | `10.1.20.0/24` | iot 40, voip 50, dmz 60, unit1–5 110/120/130/140/150 (all /24s) | + +Static DHCP leases are declared per VLAN via `dhcp.reservations` (attribute +name = hostname, plus `hwAddress`/`ipAddress`); park them outside the pool, +in the `.2–.99` infra range or `.200–.254`. Trust model: mgmt → everything; other VLANs → router DNS/DHCP + internet only (no inter-VLAN); WAN → nothing inbound; mesh → SSH, metrics, Omada UI. diff --git a/machines/gw-cnx-1/configuration.nix b/machines/gw-cnx-1/configuration.nix index 4b3a43f..849aead 100644 --- a/machines/gw-cnx-1/configuration.nix +++ b/machines/gw-cnx-1/configuration.nix @@ -25,15 +25,38 @@ site = "cnx"; siteId = 1; wan.interface = "enp1s0"; - wan.vlanId = 10; # AIS delivers PPPoE tagged on VLAN 10 + wan.vlanId = null; # this ISP runs PPPoE untagged on the port trunkPorts = [ "enp2s0" "enp3s0" "enp4s0" ]; + # Replaces the newedge.house OPNsense box; renumbered to the fleet + # convention (10.1..0/24, router .1, pool .100-.199). The old + # untagged LAN becomes tagged mgmt — infra switch ports get PVID 10. vlans = { - mgmt.id = 10; # 10.1.10.0/24 — APs, switches, Omada, admin + mgmt = { + id = 10; # 10.1.10.0/24 — servers, APs, switches, Omada, admin + dhcp.reservations.storinator01 = { + hwAddress = "7c:c2:55:e0:d6:40"; + ipAddress = "10.1.10.53"; + }; + }; lan.id = 20; # 10.1.20.0/24 — trusted clients + iot.id = 40; # 10.1.40.0/24 + voip.id = 50; # 10.1.50.0/24 + dmz.id = 60; # 10.1.60.0/24 + unit1.id = 110; # 10.1.110.0/24 + unit2.id = 120; # 10.1.120.0/24 + unit3.id = 130; # 10.1.130.0/24 + unit4.id = 140; # 10.1.140.0/24 + unit5 = { + id = 150; # 10.1.150.0/24 + dhcp.reservations.newt = { + hwAddress = "7c:d3:0a:21:58:0b"; + ipAddress = "10.1.150.22"; + }; + }; }; # This site runs the Omada controller for its APs/switches. omada.enable = true; diff --git a/modules/router/default.nix b/modules/router/default.nix index c7564c7..c6e722a 100644 --- a/modules/router/default.nix +++ b/modules/router/default.nix @@ -68,6 +68,25 @@ let e.g. public-WiFi guest VLANs (3600-7200), so the pool recycles. ''; }; + reservations = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule { + options = { + hwAddress = lib.mkOption { + type = lib.types.str; + example = "aa:bb:cc:dd:ee:ff"; + description = "Client MAC address."; + }; + ipAddress = lib.mkOption { + type = lib.types.str; + description = "Fixed address handed to this client (inside the VLAN's subnet, outside the pool)."; + }; + }; + } + ); + default = { }; + description = "Static DHCP leases; the attribute name becomes the client's hostname."; + }; }; allowWan = lib.mkOption { type = lib.types.bool; diff --git a/modules/router/dns-dhcp.nix b/modules/router/dns-dhcp.nix index 98cf776..f1c945c 100644 --- a/modules/router/dns-dhcp.nix +++ b/modules/router/dns-dhcp.nix @@ -29,6 +29,11 @@ in interface = "vlan-${name}"; valid-lifetime = vlan.dhcp.leaseTime; pools = [ { pool = "${vlan.dhcp.pool.from} - ${vlan.dhcp.pool.to}"; } ]; + reservations = lib.mapAttrsToList (host: res: { + hostname = host; + hw-address = res.hwAddress; + ip-address = res.ipAddress; + }) vlan.dhcp.reservations; option-data = [ { name = "routers";