{ config, lib, pkgs, ... }: with lib; let knotKeys = let dir = ./keys; toKeyInfo = name: v: if v == "regular" || v == "symlink" then { path = dir + "/${name}"; inherit name; } else null; in filter (v: v != null) (mapAttrsToList toKeyInfo (builtins.readDir dir)); in { config = { services.unbound = { enable = true; resolveLocalQueries = false; stateDir = "/var/lib/unbound"; localControlSocketPath = "/run/unbound/unbound.ctl"; settings = { server = { interface = ["lo" "lan"]; prefer-ip6 = true; access-control = ["0.0.0.0/0 allow" "::/0 allow"]; root-hints = "${pkgs.dns-root-data}/root.hints"; num-threads = 12; so-reuseport = true; msg-cache-slabs = 16; rrset-cache-slabs = 16; infra-cache-slabs = 16; key-cache-slabs = 16; rrset-cache-size = "100m"; msg-cache-size = "50m"; outgoing-range = 8192; num-queries-per-thread = 4096; so-rcvbuf = "4m"; so-sndbuf = "4m"; # serve-expired = true; # serve-expired-ttl = 86400; # serve-expired-reply-ttl = 0; prefetch = true; prefetch-key = true; minimal-responses = false; extended-statistics = true; rrset-roundrobin = true; use-caps-for-id = true; do-not-query-localhost = false; local-zone = [ "141.10.in-addr.arpa. transparent" "1.0.0.0.a.d.a.0.2.5.0.0.0.0.0.4.3.0.a.2.ip6.arpa. transparent" "yggdrasil. transparent" ]; domain-insecure = [ "141.10.in-addr.arpa." "1.0.0.0.a.d.a.0.2.5.0.0.0.0.0.4.3.0.a.2.ip6.arpa." "yggdrasil." ]; }; stub-zone = map (name: { inherit name; stub-addr = "127.0.0.1@5353"; stub-first = true; stub-no-cache = true; stub-prime = false; }) ["yggdrasil." "arpa.in-addr.10.141." "1.0.0.0.a.d.a.0.2.5.0.0.0.0.0.4.3.0.a.2.ip6.arpa."]; }; }; services.knot = { enable = true; keyFiles = map ({name, ...}: config.sops.secrets.${name}.path) knotKeys; extraConfig = '' server: listen: 127.0.0.1@5353 listen: ::1@5353 listen: 10.141.1.1@53 listen: 10.141.2.1@53 listen: 2a03:4000:52:ada:1:1::@53 acl: - id: local_acl key: local_key action: update template: - id: local_zone storage: /var/lib/knot zonefile-sync: -1 zonefile-load: difference-no-serial serial-policy: dateserial journal-content: all semantic-checks: on acl: [local_acl] zone: - domain: yggdrasil template: local_zone file: ${./zones/yggdrasil.soa} - domain: 141.10.in-addr.arpa template: local_zone file: ${./zones/arpa.in-addr.10.141.soa} - domain: 1.0.0.0.a.d.a.0.2.5.0.0.0.0.0.4.3.0.a.2.ip6.arpa template: local_zone file: ${./zones/arpa.ip6.2.a.0.3.4.0.0.0.0.0.5.2.0.a.d.a.0.0.0.1.soa} ''; }; sops.secrets = listToAttrs (map ({name, path}: nameValuePair name { format = "binary"; owner = "knot"; sopsFile = path; }) knotKeys); }; }