From 314be7620fa4c09411ac0f620d368efc8a398e65 Mon Sep 17 00:00:00 2001 From: Jack O'Sullivan Date: Sun, 15 Nov 2026 16:21:28 +0000 Subject: [PATCH] nixos/home: Gate DDNS updates on WAN readiness Start updates when the WAN gate opens and skip timer runs while it is inactive. Keep periodic retries and wait for the local DNS services. --- docs/networking.md | 6 ++++-- nixos/boxes/home/routing-common/dns.nix | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/networking.md b/docs/networking.md index ee83366..2b3f299 100644 --- a/docs/networking.md +++ b/docs/networking.md @@ -374,8 +374,10 @@ route on `wan`, while `river`'s `pppd` hooks start and stop it. Consumers such a `wantedBy` + `partOf` + `after`, never `requires`/`wants`, so they cannot pull the target in early and they reload on WAN flap. -DDNS starts after `network.target` rather than this WAN gate and can fail before the WAN is -ready. Its timer retries periodically; `doas systemctl start ddns-update.service` retries +DDNS starts when this WAN gate opens, after the local authoritative server and recursor. +Its five-minute timer retries failed updates and refreshes the public records; timer and manual +starts skip the update while the WAN gate is inactive, without activating it. `river` also +updates immediately after PPPoE reconnects. `doas systemctl start ddns-update.service` retries immediately once connectivity is available. ### WAN paths (summary) diff --git a/nixos/boxes/home/routing-common/dns.nix b/nixos/boxes/home/routing-common/dns.nix index bc1a8cf..f86685e 100644 --- a/nixos/boxes/home/routing-common/dns.nix +++ b/nixos/boxes/home/routing-common/dns.nix @@ -127,18 +127,21 @@ in pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; ddns-update = { description = "DNS update script"; - after = [ "network.target" ]; + after = [ "wan-online.target" "pdns.service" "pdns-recursor.service" ]; + wantedBy = [ "wan-online.target" ]; + partOf = [ "wan-online.target" ]; path = [ (pkgs.python3.withPackages (ps: [ ps.cloudflare ])) pkgs.ldns ]; serviceConfig = { Type = "oneshot"; + # Timer retries must not pull in the WAN gate or run before it opens. + ExecCondition = "${config.systemd.package}/bin/systemctl --quiet is-active wan-online.target"; ExecStart = ''${./dns_update.py} -k ${config.age.secrets."home/ddclient-cloudflare.key".path} '' + ''${pubDomain} ns${toString (index + 1)}.${config.networking.domain}''; }; - wantedBy = [ "multi-user.target" ]; }; }; timers = {