summaryrefslogtreecommitdiffstats
path: root/krebs/3modules/zones.nix
blob: 51e559d88398029021507a1813c99edf4fae24a9 (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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{ config, pkgs, lib, ... }:
with lib; {

  options.krebs.zone-head-config = mkOption {
    type = lib.types.attrsOf lib.types.str;
    description = ''
      The zone configuration head which is being used to create the
      zone files. The string for each key is pre-pended to the zone file.
    '';
    default = {
      "krebsco.de" = /* bindzone */ ''
        $TTL 60
        @ 3600 IN SOA spam.krebsco.de. spam.krebsco.de. 0 7200 3600 86400 3600
        @ 3600 IN NS ns1
        @ 3600 IN NS ni
        @ 3600 IN NS ns2.he.net.
        @ 3600 IN NS ns3.he.net.
        @ 3600 IN NS ns2.hosting.de.

        _acme-challenge IN NS ns1

        panda NS panda
        panda A 130.61.237.100

        xkey A 217.197.83.17
        xkey AAAA 2a0a:4580:5011::1
      '';
    };
  };

  config = {
    environment.etc =
      mapAttrs'
        (name: pkg: {
          name = "zones/${name}";
          value.source = pkg;
        })
        pkgs.krebs.zones;

    nixpkgs.overlays = [
      # Explicit zones generated from config.krebs.hosts.*.extraZones
      (self: super: let
        stripEmptyLines = s: (concatStringsSep "\n"
          (remove "\n" (remove "" (splitString "\n" s)))) + "\n";
        all-zones = foldAttrs (sum: current: sum + "\n" + current) ""
          ([config.krebs.zone-head-config] ++ combined-hosts);
        combined-hosts =
          mapAttrsToList (name: getAttr "extraZones") config.krebs.hosts;
      in {
        krebs = super.krebs or {} // {
          zones = super.krebs.zones or {} //
            mapAttrs'
              (name: value: {
                name = name;
                value = self.writeText "${name}.zone" (stripEmptyLines value);
              })
              all-zones;
        };
      })

      # Implicit zones generated from config.krebs.hosts.*.nets.*.ip{4,6}.addr
      (self: super: let
        # record : { name : str, type : enum [ "A" "AAAA" ], data : str }

        # toRecord : record.name -> record.type -> record.data -> record
        toRecord = name: type: data:
          { inherit name type data; };

        # toRecords : str -> host -> [record]
        toRecords = netname: host:
          let
            net = host.nets.${netname};
          in
          optionals
            (hasAttr netname host.nets)
            (filter
              (x: x.data != null)
              (concatLists [
                (map
                  (name: toRecord name "A" (net.ip4.addr or null))
                  (concatMap
                    (name: [ "${name}." "4.${name}." ])
                    (net.aliases or [])))
                (map
                  (name: toRecord name "AAAA" (net.ip6.addr or null))
                  (concatMap
                    (name: [ "${name}." "6.${name}." ])
                    (net.aliases or [])))
              ]));

        # formatRecord : record -> str
        formatRecord = { name, type, data }: "${name} IN ${type} ${data}";

        # writeZone : attrs -> package
        writeZone =
          { name ? "${domain}.zone"
          , domain ? substring 0 1 netname
          , nameservers ? [ "ni" ]
          , netname
          , hosts ? config.krebs.hosts
          }:
          self.writeText name /* bindzone */ ''
            $TTL 60
            @ IN SOA ns admin 1 3600 600 86400 60
            @ IN NS ns
            ${concatMapStringsSep "\n"
              (name: /* bindzone */ "ns IN CNAME ${name}")
              nameservers
            }
            ${concatMapStringsSep
                "\n"
                formatRecord
                (concatMap
                  (toRecords netname)
                  (attrValues hosts))
            }
          '';
      in {
        krebs = super.krebs or {} // {
          zones = super.krebs.zones or {} // {
            i = writeZone { netname = "internet"; };
            r = writeZone { netname = "retiolum"; };
            w = writeZone { netname = "wiregrill"; };
          };
        };
      })
    ];
  };

}