summaryrefslogtreecommitdiff
path: root/hostnix/elmo/dyndns.nix
blob: 750f64491b9f981e98c2c75bd9824ef6de15332b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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 ~3min before giving up.
      StartLimitIntervalSec = "5min";
      StartLimitBurst = "7";
      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";
    };
  };
}