Add dynamic DNS and show the running kernel on the overview

router.ddns keeps provider records on the uplink's addresses with ddclient,
run by a timer and by a watcher that starts it when an address changes. The
Dynamic DNS page edits it; the secret is a private file on the router. The
overview shows the running kernel and says when the current system boots a
different one. PLAN.md records why the A/B image approach was not pursued.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
2026-10-30 13:35:57 +01:00
co-authored by Claude Sonnet 5.5
parent c198ffbe37
commit a36cebc827
19 changed files with 732 additions and 8 deletions
+10
View File
@@ -144,6 +144,16 @@ pkgs.testers.runNixOSTest {
saved = router.succeed(f"cat {cfg}")
assert '"dnat": true' in saved and '"from": "wan"' in saved, saved
with subtest("dynamic DNS is saved with its secret kept out of the settings"):
dd = {"enabled": "on", "protocol": "cloudflare", "username": "token", "zone": "example.org",
"domains": "home.example.org", "ipv4": "on", "ssl": "on", "interval": "5min"}
assert post("/ddns", {"csrf": csrf("/ddns"), **dd}) == "422"
assert post("/ddns", {"csrf": csrf("/ddns"), "secret": "tok3n-abc", **dd}) == "303"
saved = router.succeed(f"cat {cfg}")
assert '"home.example.org"' in saved and "tok3n-abc" not in saved, saved
assert router.succeed("stat -c '%a' /var/lib/router/ddns-secret").strip() == "600"
assert "tok3n-abc" not in curl(f"{ui}/ddns")
with subtest("the web UI hands out a backup of the router's state"):
curl(f"-sf -d csrf={csrf('/advanced')} -o /tmp/backup.tar.gz {ui}/backup")
files = client.succeed("tar -tzf /tmp/backup.tar.gz")