{ config, pkgs, ... }: let # ZeroTier addresses — zone transfers run over the mesh, not the public net. ns1zt = "fd06:1bad:ece2:92ad:ba99:939d:766d:8974"; ns2zt = "fd06:1bad:ece2:92ad:ba99:9323:61be:a09e"; in { # Shared TSIG key, generated once and copied to every machine that imports # this module, so primary and secondary authenticate transfers with the same key. clan.core.vars.generators.dns-tsig = { share = true; files."tsig.conf" = { secret = true; # knotd drops to the "knot" user, so the included key must be readable by it. owner = "knot"; group = "knot"; }; runtimeInputs = [ pkgs.knot-dns ]; script = '' keymgr -t cnx_xfr hmac-sha256 > "$out"/tsig.conf ''; }; networking.firewall.allowedTCPPorts = [ 53 ]; networking.firewall.allowedUDPPorts = [ 53 ]; # knot binds 0.0.0.0@53 and ::@53, so free port 53 by disabling the # systemd-resolved stub listener. Resolution still works via nss-resolve. services.resolved.extraConfig = "DNSStubListener=no"; services.knot = { enable = true; # Including the key via keyFiles keeps the secret out of the Nix store. keyFiles = [ config.clan.core.vars.generators.dns-tsig.files."tsig.conf".path ]; settings = { server.listen = [ "0.0.0.0@53" "::@53" ]; log = [ { target = "syslog"; any = "info"; } ]; remote = [ { id = "ns1"; address = [ ns1zt ]; key = "cnx_xfr"; } { id = "ns2"; address = [ ns2zt ]; key = "cnx_xfr"; } ]; acl = [ { id = "acl_ns1"; address = [ ns1zt ]; key = "cnx_xfr"; action = [ "transfer" "notify" ]; } { id = "acl_ns2"; address = [ ns2zt ]; key = "cnx_xfr"; action = [ "transfer" "notify" ]; } ]; }; }; }