Add DNS accounts, Let's Encrypt, password change, reboot, HTTP redirect
- router.dnsProviders: named accounts at DNS providers, used by dynamic DNS and certificates (ddclient and lego provider lists in pkgs/router-webui/providers.json). Schema 2 migrates router.ddns. - router.acme: a Let's Encrypt certificate for the web UI via security.acme (DNS-01, resolver 1.1.1.1), served and reloaded by the web UI; Certificate page. - Web UI: password change (web UI and root), reboot button, HTTP to HTTPS redirect (router.webui.httpPort), grouped menu. - Latest kernel (linuxPackages_latest); 7.3 and 7.3.0 are the same kernel for the reboot hint. - SPECS.md: wanted later (REST API, GraphQL, MCP). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
+25
-11
@@ -10,6 +10,16 @@
|
||||
let
|
||||
cfg = config.router;
|
||||
ddns = cfg.ddns;
|
||||
# The connection (an empty one when it is missing: the assertion says so).
|
||||
providers = builtins.fromJSON (builtins.readFile ../../pkgs/router-webui/providers.json);
|
||||
has = ddns.provider != null && cfg.dnsProviders ? ${ddns.provider};
|
||||
prov =
|
||||
cfg.dnsProviders.${if ddns.provider == null then "" else ddns.provider} or {
|
||||
type = "none";
|
||||
username = "token";
|
||||
server = null;
|
||||
secretFile = null;
|
||||
};
|
||||
|
||||
# Where the addresses are: IPv4 on the PPP device, IPv6 on the physical uplink
|
||||
# (or the PPP device when IPv6 runs over it).
|
||||
@@ -47,22 +57,26 @@ in
|
||||
message = "router.ddns: neither IPv4 nor IPv6 is enabled.";
|
||||
}
|
||||
{
|
||||
assertion = ddns.passwordFile != null && !lib.hasPrefix "/nix/store" ddns.passwordFile;
|
||||
message = "router.ddns.passwordFile must name a file outside the Nix store (the secret must not be copied into it).";
|
||||
assertion = has;
|
||||
message = "router.ddns.provider must name a connection in router.dnsProviders.";
|
||||
}
|
||||
{
|
||||
assertion = !has || lib.elem prov.type providers.ddns;
|
||||
message = "router.ddns: ddclient has no protocol ${prov.type}.";
|
||||
}
|
||||
{
|
||||
assertion = !has || (prov.secretFile != null && !lib.hasPrefix "/nix/store" prov.secretFile);
|
||||
message = "The secretFile of router.dnsProviders.${toString ddns.provider} must name a file outside the Nix store (the secret must not be copied into it).";
|
||||
}
|
||||
];
|
||||
|
||||
services.ddclient = {
|
||||
enable = true;
|
||||
inherit (ddns)
|
||||
protocol
|
||||
username
|
||||
passwordFile
|
||||
domains
|
||||
ssl
|
||||
interval
|
||||
;
|
||||
server = lib.optionalString (ddns.server != null) ddns.server;
|
||||
inherit (ddns) domains ssl interval;
|
||||
protocol = prov.type;
|
||||
inherit (prov) username;
|
||||
passwordFile = prov.secretFile;
|
||||
server = lib.optionalString (prov.server != null) prov.server;
|
||||
zone = lib.optionalString (ddns.zone != null) ddns.zone;
|
||||
usev4 = lib.optionalString ddns.ipv4 "ifv4, ifv4=${dev4}";
|
||||
usev6 = lib.optionalString ddns.ipv6 "ifv6, ifv6=${dev6}";
|
||||
|
||||
Reference in New Issue
Block a user