Add internal reverse proxy for gateways (Caddy, wildcard via DNS-01)
cnx.router.proxy serves <service>.<site><n>.cnx.network with a real Let's Encrypt wildcard obtained via a gateway-scoped TSIG key against ns1; Blocky resolves the names to the router's LAN address, so they exist only internally. First user: Omada UI on gw-cnx-1 (omada.cnx1.cnx.network).
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
imports = [
|
||||
../../modules/router
|
||||
../../modules/monitoring/exporters.nix
|
||||
(import ../../modules/dns/acme-gw-secret.nix "gw-cnx-1")
|
||||
];
|
||||
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
@@ -36,6 +37,17 @@
|
||||
};
|
||||
# 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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
time.timeZone = "Etc/GMT-7"; # UTC+7 (Thailand, fixed offset, no DST)
|
||||
|
||||
@@ -14,6 +14,7 @@ in
|
||||
../../modules/dns/authoritative.nix
|
||||
../../modules/dns/acme-mx1-secret.nix
|
||||
../../modules/dns/acme-web01-secret.nix
|
||||
(import ../../modules/dns/acme-gw-secret.nix "gw-cnx-1")
|
||||
../../modules/static-ipv6.nix
|
||||
../../modules/monitoring/exporters.nix
|
||||
];
|
||||
@@ -93,10 +94,29 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
# ACME DNS-01, dedicated gateway keys. Same pattern as web01: each gateway
|
||||
# holds its own TSIG key (acme_gw_<site>_<n>), rendered from the shared
|
||||
# secret generator imported above. acl_acme_gw_<site>_<n> scopes it to TXT
|
||||
# updates at _acme-challenge.<site><n> on cnx.network — the owner its internal
|
||||
# wildcard *.<site><n>.cnx.network challenge uses — and nothing else.
|
||||
clan.core.vars.generators.dns-acme-gw-cnx-1-knot = {
|
||||
files."acme.conf" = {
|
||||
secret = true;
|
||||
owner = "knot";
|
||||
group = "knot";
|
||||
};
|
||||
dependencies = [ "dns-acme-gw-cnx-1-secret" ];
|
||||
script = ''
|
||||
printf 'key:\n - id: acme_gw_cnx_1\n algorithm: hmac-sha256\n secret: %s\n' \
|
||||
"$(cat "$in"/dns-acme-gw-cnx-1-secret/secret)" > "$out"/acme.conf
|
||||
'';
|
||||
};
|
||||
|
||||
services.knot.keyFiles = [
|
||||
config.clan.core.vars.generators.dns-acme-tsig.files."acme.conf".path
|
||||
config.clan.core.vars.generators.dns-acme-mx1-knot.files."acme.conf".path
|
||||
config.clan.core.vars.generators.dns-acme-web01-knot.files."acme.conf".path
|
||||
config.clan.core.vars.generators.dns-acme-gw-cnx-1-knot.files."acme.conf".path
|
||||
];
|
||||
|
||||
services.knot.settings.acl = [
|
||||
@@ -133,6 +153,17 @@ in
|
||||
# i.e. _acme-challenge at the cnx.network apex (where this acl is attached).
|
||||
"update-owner-name" = [ "_acme-challenge" ];
|
||||
}
|
||||
{
|
||||
id = "acl_acme_gw_cnx_1";
|
||||
key = "acme_gw_cnx_1";
|
||||
action = [ "update" ];
|
||||
"update-type" = [ "TXT" ];
|
||||
"update-owner" = "name";
|
||||
"update-owner-match" = "sub-or-equal";
|
||||
# The internal wildcard *.cnx1.cnx.network places its challenge at
|
||||
# _acme-challenge.cnx1.cnx.network.
|
||||
"update-owner-name" = [ "_acme-challenge.cnx1" ];
|
||||
}
|
||||
];
|
||||
|
||||
# Automatic DNSSEC signing policy (primary only). ECDSA P-256/SHA-256 with
|
||||
@@ -168,6 +199,9 @@ in
|
||||
"acl_acme"
|
||||
]
|
||||
++ lib.optionals (d == "cnx.email") [ "acl_acme_mx1" ]
|
||||
++ lib.optionals (d == "cnx.network") [ "acl_acme_web01" ];
|
||||
++ lib.optionals (d == "cnx.network") [
|
||||
"acl_acme_web01"
|
||||
"acl_acme_gw_cnx_1"
|
||||
];
|
||||
}) domains;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user