inventory.nix: router instance for gw-cnx-1
Move the `router` service instance out of clan.nix into its own clan module, inventory.nix, imported by clan.nix. Fleet-wide role settings (mesh subnet, proxy domain/ACME) and the gw-cnx-1 site layout live there; clan.nix keeps the machine list and the clan-core services. The gw-cnx-1 toplevel is byte-identical before and after the move.
This commit is contained in:
@@ -1,10 +1,6 @@
|
||||
{ config, lib, ... }:
|
||||
{ ... }:
|
||||
let
|
||||
hosts = import ./modules/hosts.nix;
|
||||
mesh = import ./modules/mesh-hosts.nix {
|
||||
dir = config.directory;
|
||||
inherit lib;
|
||||
};
|
||||
|
||||
# Single source of the machine list: inventory AND the per-machine baseline
|
||||
# below are both derived from it, so no machine can be added without the
|
||||
@@ -22,6 +18,9 @@ let
|
||||
};
|
||||
in
|
||||
{
|
||||
# Site gateways: the router service instance lives in inventory.nix.
|
||||
imports = [ ./inventory.nix ];
|
||||
|
||||
# Ensure this is unique among all clans you want to use.
|
||||
meta.name = "cnx-network-clan";
|
||||
meta.domain = "cnx-network.internal";
|
||||
@@ -95,85 +94,6 @@ in
|
||||
roles.server.machines.control = { };
|
||||
roles.client.machines.ns1 = { };
|
||||
};
|
||||
|
||||
# Site gateways: one router instance per site, settings = the site's
|
||||
# port/VLAN layout. Everything else (PPPoE, Kea/Blocky, nftables, IPv6-PD,
|
||||
# CrowdSec, iperf3, speedtest) follows from modules/clan/router.
|
||||
router = {
|
||||
module = {
|
||||
name = "router";
|
||||
input = "self";
|
||||
};
|
||||
# Fleet-wide settings: admin paths (SSH, scrapes, iperf3, Omada UI) are
|
||||
# opened to the mesh; internal proxy names live under
|
||||
# <site><n>.cnx.network with wildcard certs issued via DNS-01 against
|
||||
# ns1 (which must declare the gateway's acme-secret.nix generator).
|
||||
roles.default.settings = {
|
||||
mesh.subnet = mesh.subnet;
|
||||
proxy = {
|
||||
domain = "cnx.network";
|
||||
acme.nameserver = hosts.ns1.ipv4;
|
||||
acme.email = "postmaster@cnx.email";
|
||||
};
|
||||
};
|
||||
# Chiang Mai (site 1): Topton 1U, Intel N300, 4x i226-V 2.5G. Port roles
|
||||
# use the expected igc names — verify against facter.json after the
|
||||
# first install and adjust if the box enumerates differently.
|
||||
roles.default.machines.gw-cnx-1.settings = {
|
||||
site = "cnx";
|
||||
siteId = 1;
|
||||
wan.interface = "enp1s0";
|
||||
wan.vlanId = null; # this ISP runs PPPoE untagged on the port
|
||||
wan.macAddress = "a8:b8:e0:01:06:87";
|
||||
trunkPorts = [
|
||||
"enp2s0"
|
||||
# "enp3s0" # STAGING: serves as the uplink until cutover (see the machine config)
|
||||
];
|
||||
# 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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Fleet-wide baseline applied to every machine. Secrets minted by
|
||||
|
||||
@@ -5,8 +5,8 @@ NixOS routers (OPNsense replacements) on Topton 1U fanless boxes — Intel N300,
|
||||
Four sites are planned; the first is `gw-cnx-1` (Chiang Mai). Everything lives
|
||||
in the `router` clan service (`modules/clan/router/`, registered as
|
||||
`modules.router` in `clan.nix`); a site joins by adding its machine to the
|
||||
`router` inventory instance with settings for port names, VLANs, and feature
|
||||
flags (`inventory.instances.router.roles.default.machines.<gw>.settings`).
|
||||
`router` inventory instance in `inventory.nix` with settings for port names,
|
||||
VLANs, and feature flags (`roles.default.machines.<gw>.settings`).
|
||||
|
||||
Naming: `gw-<city>-<n>`, e.g. `gw-cnx-1`.
|
||||
|
||||
@@ -70,7 +70,7 @@ Trust model: mgmt → everything; other VLANs → router DNS/DHCP + internet onl
|
||||
hostId, timezone). Fill the real disk id in `disko.nix` (from the
|
||||
installer: `ls -l /dev/disk/by-id/`).
|
||||
2. Add the machine to `inventory.machines` in `clan.nix`, to the `router`
|
||||
instance (`roles.default.machines.gw-<city>-<n>.settings`: `site`,
|
||||
instance in `inventory.nix` (`roles.default.machines.gw-<city>-<n>.settings`: `site`,
|
||||
`siteId` (next free number), port names, VLANs, `omada.enable`; keep the
|
||||
`mgmt`/`lan` VLANs), and to the machine list in `modules/mesh-hosts.nix`.
|
||||
Do **not** add it to `modules/hosts.nix` (dynamic PPPoE IP; clan connects
|
||||
@@ -129,7 +129,7 @@ proxy = {
|
||||
PPPoE with zero inbound reachability, and browsers trust it without a CA
|
||||
install. Each gateway has its own TSIG key (`acme_gw_<city>_<n>`) that ns1
|
||||
scopes to `_acme-challenge.<site><n>` TXT records only. The zone, ns1's
|
||||
address and the ACME contact are fleet-wide role settings in `clan.nix`
|
||||
address and the ACME contact are fleet-wide role settings in `inventory.nix`
|
||||
(`proxy.domain`, `proxy.acme.nameserver`, `proxy.acme.email`).
|
||||
- **Resolution**: the names exist only internally — Blocky answers
|
||||
`*.<site><n>.cnx.network` with the router's `lan` address; the public
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# Site gateways: the `router` service instance (modules/clan/router). One
|
||||
# instance for the fleet; each site adds its machine with the site's port /
|
||||
# VLAN layout under roles.default.machines.<gw>.settings. Everything else
|
||||
# (PPPoE, Kea/Blocky, nftables, IPv6-PD, CrowdSec, iperf3, speedtest) follows
|
||||
# from the service. Imported by clan.nix.
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
hosts = import ./modules/hosts.nix;
|
||||
mesh = import ./modules/mesh-hosts.nix {
|
||||
dir = config.directory;
|
||||
inherit lib;
|
||||
};
|
||||
in
|
||||
{
|
||||
inventory.instances.router = {
|
||||
module = {
|
||||
name = "router";
|
||||
input = "self";
|
||||
};
|
||||
|
||||
# Fleet-wide settings: admin paths (SSH, scrapes, iperf3, Omada UI) are
|
||||
# opened to the mesh; internal proxy names live under
|
||||
# <site><n>.cnx.network with wildcard certs issued via DNS-01 against
|
||||
# ns1 (which must declare the gateway's acme-secret.nix generator).
|
||||
roles.default.settings = {
|
||||
mesh.subnet = mesh.subnet;
|
||||
proxy = {
|
||||
domain = "cnx.network";
|
||||
acme.nameserver = hosts.ns1.ipv4;
|
||||
acme.email = "postmaster@cnx.email";
|
||||
};
|
||||
};
|
||||
|
||||
# Chiang Mai (site 1): Topton 1U, Intel N300, 4x i226-V 2.5G. Port roles
|
||||
# use the expected igc names — verify against facter.json after the
|
||||
# first install and adjust if the box enumerates differently.
|
||||
roles.default.machines.gw-cnx-1.settings = {
|
||||
site = "cnx";
|
||||
siteId = 1;
|
||||
wan.interface = "enp1s0";
|
||||
wan.vlanId = null; # this ISP runs PPPoE untagged on the port
|
||||
wan.macAddress = "a8:b8:e0:01:06:87";
|
||||
trunkPorts = [
|
||||
"enp2s0"
|
||||
# "enp3s0" # STAGING: serves as the uplink until cutover (see the machine config)
|
||||
];
|
||||
# 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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user