diff options
Diffstat (limited to 'hostnix/elmo/dyndns.nix')
| -rw-r--r-- | hostnix/elmo/dyndns.nix | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/hostnix/elmo/dyndns.nix b/hostnix/elmo/dyndns.nix new file mode 100644 index 0000000..a59c665 --- /dev/null +++ b/hostnix/elmo/dyndns.nix @@ -0,0 +1,78 @@ +{ config, pkgs, ... }: + +{ + # 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/lib/secrets/${config.networking.fqdn}.id"; + }; + serviceConfig = { + Type = "oneshot"; + }; + path = [ pkgs.bind ]; + scriptArgs = config.networking.fqdn; + script = '' + mkdir -p /var/lib/secrets + chmod 755 /var/lib/secrets + cd /var/lib/secrets + dnssec-keygen -a RSASHA512 -b 2048 -n HOST -T KEY $1. > $1.id + ''; + }; + + systemd.services.dyndns = { + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + unitConfig = { + AssertPathExists = "/var/lib/secrets/${config.networking.fqdn}.id"; + # Defer errors for ~45min, throttle e-mails to ~hourly. + StartLimitIntervalSec = "1hr"; + StartLimitBurst = "45"; + }; + serviceConfig = { + Type = "oneshot"; + Restart = "on-failure"; + RestartSec = "1min"; + }; + 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 + + # Follow some RFC 6724 default address guidance, excluding ULA. + # It might be more robust to bind a public source socket (RFC 5014). + IP6=`ip -6 address show scope global -deprecated | awk -F'[ /]+' '$2 == "inet6" && $3 !~ /^f[cd]/ { print $3; exit }'` + + OLDIP4=`dig +short @popfresh.mou.fo $RR A 2> /dev/null` + OLDIP6=`dig +short @popfresh.mou.fo $RR AAAA 2> /dev/null` + # [ "x$IP" = "x$OLDIP4" ] && exit 0 # no update + if [ "x$IP4" = "x$OLDIP4" -a "x$IP6" = "x$OLDIP6" ]; then + exit 0 + fi + + nsupdate -v -k /var/lib/secrets/`< /var/lib/secrets/$1.id`.private <<. + update delete $RR. A + update add $RR. 300 A $IP4 + update delete $RR. AAAA + ''${IP6:+update add $RR. 300 AAAA $IP6} + 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"; + }; + }; +} |
