mob next [ci-skip] [ci skip] [skip ci]

lastFile:docs/src/gateways.md
This commit is contained in:
2026-09-09 13:43:46 +07:00
parent b85d6637f1
commit a3705e7a93
37 changed files with 1303 additions and 909 deletions
+87
View File
@@ -1,5 +1,10 @@
{ 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
@@ -23,6 +28,9 @@ in
inventory.machines = fleet;
# Services defined in this repo (module.input = "self"). See modules/clan/.
modules.router = ./modules/clan/router;
inventory.instances = {
# Admin SSH keys + root password, split per the clan-core migration off
@@ -87,6 +95,85 @@ 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