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:
+143
-5
@@ -313,10 +313,14 @@ let
|
||||
ddnsValid = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/var/lib/router/dns-secrets/cf";
|
||||
};
|
||||
ddns = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
domains = [ "home.example.org" ];
|
||||
passwordFile = "/var/lib/router/ddns-secret";
|
||||
};
|
||||
};
|
||||
expect = [ ];
|
||||
@@ -324,20 +328,39 @@ let
|
||||
ddnsSecretInTheStore = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-secret";
|
||||
};
|
||||
ddns = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
domains = [ "home.example.org" ];
|
||||
passwordFile = "/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-secret";
|
||||
};
|
||||
};
|
||||
expect = [ "outside the Nix store" ];
|
||||
};
|
||||
ddnsWithoutNames = {
|
||||
ddnsWithoutProvider = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
ddns = {
|
||||
enable = true;
|
||||
passwordFile = "/var/lib/router/ddns-secret";
|
||||
provider = "nothing";
|
||||
domains = [ "home.example.org" ];
|
||||
};
|
||||
};
|
||||
expect = [ "must name a connection in router.dnsProviders" ];
|
||||
};
|
||||
ddnsWithoutNames = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/var/lib/router/dns-secrets/cf";
|
||||
};
|
||||
ddns = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
};
|
||||
};
|
||||
expect = [ "no domains to update" ];
|
||||
@@ -345,15 +368,130 @@ let
|
||||
ddnsWithoutAnyFamily = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/var/lib/router/dns-secrets/cf";
|
||||
};
|
||||
ddns = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
domains = [ "home.example.org" ];
|
||||
passwordFile = "/var/lib/router/ddns-secret";
|
||||
ipv4 = false;
|
||||
};
|
||||
};
|
||||
expect = [ "neither IPv4 nor IPv6" ];
|
||||
};
|
||||
acmeValid = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/var/lib/router/dns-secrets/cf";
|
||||
};
|
||||
acme = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
domains = [
|
||||
"router.example.org"
|
||||
"*.home.example.org"
|
||||
];
|
||||
email = "me@example.org";
|
||||
acceptTerms = true;
|
||||
};
|
||||
};
|
||||
expect = [ ];
|
||||
};
|
||||
acmeProviderCannotDoDNS01 = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.dyn = {
|
||||
type = "dyndns2";
|
||||
secretFile = "/var/lib/router/dns-secrets/dyn";
|
||||
};
|
||||
acme = {
|
||||
enable = true;
|
||||
provider = "dyn";
|
||||
domains = [ "router.example.org" ];
|
||||
email = "me@example.org";
|
||||
acceptTerms = true;
|
||||
};
|
||||
};
|
||||
expect = [ "lego has no DNS provider dyndns2" ];
|
||||
};
|
||||
acmeEnvironmentProviderValid = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.aws = {
|
||||
type = "route53";
|
||||
environmentFile = "/var/lib/router/dns-secrets/aws.env";
|
||||
};
|
||||
acme = {
|
||||
enable = true;
|
||||
provider = "aws";
|
||||
domains = [ "router.example.org" ];
|
||||
email = "me@example.org";
|
||||
acceptTerms = true;
|
||||
};
|
||||
};
|
||||
expect = [ ];
|
||||
};
|
||||
acmeEnvironmentProviderWithoutFile = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.aws.type = "route53";
|
||||
acme = {
|
||||
enable = true;
|
||||
provider = "aws";
|
||||
domains = [ "router.example.org" ];
|
||||
email = "me@example.org";
|
||||
acceptTerms = true;
|
||||
};
|
||||
};
|
||||
expect = [ "needs environmentFile for certificates" ];
|
||||
};
|
||||
ddnsProviderUnknownToDdclient = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.aws = {
|
||||
type = "route53";
|
||||
secretFile = "/var/lib/router/dns-secrets/aws";
|
||||
};
|
||||
ddns = {
|
||||
enable = true;
|
||||
provider = "aws";
|
||||
domains = [ "home.example.org" ];
|
||||
};
|
||||
};
|
||||
expect = [ "ddclient has no protocol route53" ];
|
||||
};
|
||||
acmeTermsNotAccepted = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
dnsProviders.cf = {
|
||||
type = "cloudflare";
|
||||
secretFile = "/var/lib/router/dns-secrets/cf";
|
||||
};
|
||||
acme = {
|
||||
enable = true;
|
||||
provider = "cf";
|
||||
domains = [ "router.example.org" ];
|
||||
email = "me@example.org";
|
||||
};
|
||||
};
|
||||
expect = [ "subscriber agreement must be accepted" ];
|
||||
};
|
||||
acmeWithoutProvider = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
acme = {
|
||||
enable = true;
|
||||
domains = [ "router.example.org" ];
|
||||
email = "me@example.org";
|
||||
acceptTerms = true;
|
||||
};
|
||||
};
|
||||
expect = [ "must name a connection in router.dnsProviders" ];
|
||||
};
|
||||
ruleSourcePortsWithoutProtocol = {
|
||||
router = {
|
||||
lans = {
|
||||
|
||||
Reference in New Issue
Block a user