diff options
Diffstat (limited to 'hostnix/elmo/dyndns.nix')
| -rw-r--r-- | hostnix/elmo/dyndns.nix | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/hostnix/elmo/dyndns.nix b/hostnix/elmo/dyndns.nix new file mode 100644 index 0000000..56a46cc --- /dev/null +++ b/hostnix/elmo/dyndns.nix @@ -0,0 +1,76 @@ +{ config, pkgs, ... }: + +{ + systemd.tmpfiles.rules = [ + "d /var/secrets 0750 root wheel" + ]; + + # Needs to be started manually, and the key added to nameservers. + # Based on https://nixos.org/manual/nixos/stable/index.html#module-security-acme-config-dns + systemd.services.sig0-keygen = { + unitConfig = { + ConditionPathExists = "!/var/secrets/dyndns"; + }; + serviceConfig = { + Type = "oneshot"; + }; + scriptArgs = config.networking.fqdn; + script = '' + mkdir /var/secrets/dyndns + cd /var/secrets/dyndns + ${pkgs.bind}/bin/dnssec-keygen -a RSASHA512 -b 2048 -n HOST -T KEY $1. > basename + ''; + }; + + # Unused with authoritative DNS on the router. We leave it for redundancy. + systemd.services.dyndns = { + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + unitConfig = { + AssertPathExists = "/var/secrets/dyndns"; + # Retry ~30min before giving up. + StartLimitIntervalSec = "45min"; + StartLimitBurst = "60"; + OnFailure = "status-email@%n.service"; + }; + serviceConfig = { + Type = "oneshot"; + Restart = "on-failure"; + # Restart must be faster than the regular timer interval to exceed the + # start limit when flapping. + RestartSec = "30"; + # Defer OnFailure until after retries. + RestartMode = "direct"; + }; + path = [ pkgs.dnsutils pkgs.gawk pkgs.iproute2 ]; + scriptArgs = config.networking.fqdn; + script = '' + RR=''${1%%.*}.dynamic.''${1#*.} + + IP4=`dig +short @1.1.1.1 ch txt whoami.cloudflare | tr -d \"` + if [ -z "$IP4" ]; then + echo "Missing IP: $IP4" >&2 + exit 100 + fi + + OLDIP4=`dig +short @popfresh.mou.fo $RR A 2> /dev/null` + [ "x$IP4" = "x$OLDIP4" ] && exit 0 # no update + + nsupdate -v -k /var/secrets/dyndns/`< /var/secrets/dyndns/basename`.private <<. + update delete $RR. A + update add $RR. 300 A $IP4 + update delete $RR. TXT + update add $RR. 300 TXT "v=spf1 include:_spf.mou.fo ~all" + send + . + ''; + }; + + systemd.timers.dyndns = { + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnStartupSec = "10"; + OnUnitActiveSec = "1min"; + }; + }; +} |
