New cnx.router.accessPorts option pins a port untagged to one VLAN via bridge PVID/EgressUntagged; convention is the last copper port as an always-available mgmt recovery port. gw-cnx-1 port roles: enp1s0 WAN, enp2s0 trunk, enp3s0 temporary DHCP uplink into the old OPNsense LAN (back to trunk at cutover), enp4s0 untagged mgmt.
92 lines
3.3 KiB
Nix
92 lines
3.3 KiB
Nix
# Site gateway Chiang Mai (site 1): Topton 1U, Intel N300, 4x i226-V 2.5G.
|
|
# Port roles below use the expected igc names — verify against facter.json
|
|
# after the first install and adjust if the box enumerates differently.
|
|
{ config, lib, ... }:
|
|
{
|
|
imports = [
|
|
../../modules/router
|
|
../../modules/monitoring/exporters.nix
|
|
(import ../../modules/dns/acme-gw-secret.nix "gw-cnx-1")
|
|
];
|
|
|
|
clan.core.sops.defaultGroups = [ "admins" ];
|
|
|
|
# Until the install generates facter.json (which normally provides this).
|
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
|
|
|
# ZFS (disko.nix) needs a stable machine-unique hostId; derive it from the
|
|
# hostname so every gateway gets one for free when copied for a new site.
|
|
networking.hostId = builtins.substring 0 8 (
|
|
builtins.hashString "sha256" config.networking.hostName
|
|
);
|
|
|
|
cnx.router = {
|
|
enable = true;
|
|
site = "cnx";
|
|
siteId = 1;
|
|
wan.interface = "enp1s0";
|
|
wan.vlanId = null; # this ISP runs PPPoE untagged on the port
|
|
trunkPorts = [
|
|
"enp2s0"
|
|
# "enp3s0" # STAGING: serves as the uplink below until cutover
|
|
];
|
|
# Dedicated on-site recovery port: untagged mgmt, always available even
|
|
# if the switch config is broken.
|
|
accessPorts.enp4s0 = "mgmt";
|
|
# Replaces the newedge.house OPNsense box; renumbered to the fleet
|
|
# convention (10.1.<vlanId>.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 — 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;
|
|
|
|
# Internal reverse proxy: real wildcard cert *.cnx1.cnx.network; Blocky
|
|
# resolves the names to the router's LAN address for mgmt+lan clients.
|
|
proxy = {
|
|
enable = true;
|
|
services.omada = {
|
|
# Omada's UI is HTTPS with a self-signed cert on the host network.
|
|
backend = "https://127.0.0.1:8043";
|
|
insecureSkipVerify = true;
|
|
};
|
|
};
|
|
};
|
|
|
|
# STAGING (remove at cutover, and restore enp3s0 to trunkPorts): DHCP-client
|
|
# uplink into the existing OPNsense LAN so the box has internet + mesh while
|
|
# it runs alongside the old router. Default-deny firewall on this interface
|
|
# (it's in no VLAN zone); PPPoE simply retries until the WAN port is cabled.
|
|
# Do NOT connect the trunk ports to the production switch while staging —
|
|
# Kea on tag 10 would fight the OPNsense LAN DHCP in one broadcast domain.
|
|
systemd.network.networks."05-staging" = {
|
|
matchConfig.Name = "enp3s0";
|
|
networkConfig.DHCP = "ipv4";
|
|
};
|
|
|
|
time.timeZone = "Etc/GMT-7"; # UTC+7 (Thailand, fixed offset, no DST)
|
|
services.chrony.enable = true;
|
|
}
|