commit 7220a04d754177942f34386a585b869de38643ab
parent 61701e9af73a46083ede1a6388798f5c4cb19f57
Author: Katja (ctucx) <git@ctu.cx>
Date: Wed, 21 May 2025 13:00:50 +0200
parent 61701e9af73a46083ede1a6388798f5c4cb19f57
Author: Katja (ctucx) <git@ctu.cx>
Date: Wed, 21 May 2025 13:00:50 +0200
config/nixos/modules/services: add `knot`
1 file changed, 174 insertions(+), 0 deletions(-)
A
|
174
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/config/nixos/modules/services/knot.nix b/config/nixos/modules/services/knot.nix @@ -0,0 +1,174 @@ +{ + inputs, + povSelf, + hostConfig, + config, + lib, + pkgs, + ... +}: +let + inherit (lib) types; + cfg = lib.getAttrFromPath povSelf config; + + dnsServerAddresses = isPrimary: lib.flatten ( + inputs.self.nixosConfigurations + |> lib.filterAttrs (hostName: hostConfig: let + cfgModule = lib.getAttrFromPath povSelf hostConfig.config; + in (cfgModule.enable && cfgModule.primary == isPrimary)) + |> lib.mapAttrsToList ( + hostName: hostConfig: [ + (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip6Address != "") inputs.self.hosts."${hostName}".networking.ip6Address) + (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip4Address != "") inputs.self.hosts."${hostName}".networking.ip4Address) + ] + ) + ); + + dnsServerSecondaries = ( + inputs.self.nixosConfigurations + |> lib.filterAttrs (hostName: hostConfig: let + cfgModule = lib.getAttrFromPath povSelf hostConfig.config; + in (cfgModule.enable && !cfgModule.primary)) + |> lib.mapAttrs( + hostName: hostConfig: { + address = [ + (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip6Address != "") inputs.self.hosts."${hostName}".networking.ip6Address) + (lib.mkIf (inputs.self.hosts."${hostName}".networking.ip4Address != "") inputs.self.hosts."${hostName}".networking.ip4Address) + ]; + } + ) + ); + +in +{ + + options = { + enable = { + type = types.bool; + default = false; + }; + + primary = { + type = types.bool; + default = false; + }; + + dataDir = { + type = types.str; + default = "/var/lib/knot"; + }; + + keyFiles = { + type = types.listOf types.path; + default = []; + }; + + zones = { + type = (pkgs.formats.yaml { }).type; + default = {}; + }; + + extraACL = { + type = (pkgs.formats.yaml { }).type; + default = {}; + }; + }; + + config = lib.mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ 53 ]; + networking.firewall.allowedUDPPorts = [ 53 ]; + + systemd.tmpfiles.settings = { + knotDataDir."${cfg.dataDir}".d = { + group = "knot"; + user = "knot"; + mode = "770"; + age = "-"; + }; + }; + + services.knot = let + primaryAddresses = dnsServerAddresses true; + secondaryAddresses = dnsServerAddresses false; + secondaries = dnsServerSecondaries; + + in { + enable = true; + keyFiles = lib.mkIf (cfg.keyFiles != []) cfg.keyFiles; + settings = { + log.syslog.any = "info"; + + server.listen = [ + (lib.mkIf (hostConfig.networking.ip6Address != "") "${hostConfig.networking.ip6Address}@53") + (lib.mkIf (hostConfig.networking.ip4Address != "") "${hostConfig.networking.ip4Address}@53") + "::1@53" + ]; + + mod-rrl.default.rate-limit = 200; + mod-rrl.default.slip = 2; + + remote = { primary.address = primaryAddresses; } // secondaries; + + acl = { + allowTransfer = lib.mkIf (secondaryAddresses != []) { + address = secondaryAddresses; + action = "transfer"; + }; + + allowNotify.address = primaryAddresses; + allowNotify.action = "notify"; + } // cfg.extraACL; + + template = let + notify = { + acl = lib.mkIf (config.services.knot.settings.acl ? allowTransfer) "allowTransfer"; + notify = lib.mkIf (config.services.knot.settings.acl ? allowTransfer) (builtins.attrNames secondaries); + }; + + catalog = { + catalog-role = "member"; + catalog-zone = "catalog."; + }; + + in { + + default = { + semantic-checks = true; + global-module = "mod-rrl/default"; + }; + + notifyZone = notify; + nixZone = notify // catalog; + + secondaryZone = { + master = "primary"; + acl = "allowNotify"; + + journal-content = "all"; + + zonefile-sync = -1; + zonefile-load = "none"; + }; + }; + + zone = (if !cfg.primary then { + "catalog.".catalog-role = "interpret"; + "catalog.".catalog-template = "secondaryZone"; + "catalog.".template = "secondaryZone"; + } else { + "catalog.".catalog-role = "generate"; + "catalog.".template = "notifyZone"; + }) // (lib.mapAttrs (name: zone: zone // { + template = "nixZone"; + acl = lib.mkIf (zone ? acl) ( + if (config.services.knot.settings.acl ? allowTransfer) then + lib.flatten [ [ "allowTransfer" ] zone.acl ] + else + zone.acl + ); + }) cfg.zones); + }; + }; + }; + +}