{ config, lib, self, ... }: let cfg = config.dns; inherit (lib) mkEnableOption mkIf strings ; inherit (config.networking) fqdn; agenixDnsDir = "${self}/agenix/dns/${fqdn}"; agenixKeys = builtins.attrNames (builtins.readDir agenixDnsDir); keys = map ( filename: let zonesub = _: "zonesub"; subdomain = name: "subdomain ${name}"; zoneDomain = if strings.hasSuffix ".key.age" filename then strings.removeSuffix ".key.age" filename else throw "${filename} is not a `.key.age` file"; in { inherit (config.age.secrets."dns/${filename}") path; name = zoneDomain; type = if zoneDomain == fqdn then zonesub else subdomain; } ) agenixKeys; in { options.dns = { enable = mkEnableOption "" // { default = true; }; }; config = mkIf cfg.enable { age.secrets = builtins.listToAttrs ( map ( filename: let path = "${agenixDnsDir}/${filename}"; in { name = "dns/${filename}"; value = { file = path; group = "named"; owner = if config.acme.enable then "acme" else "named"; mode = "440"; }; } ) agenixKeys ); services.bind = { enable = true; extraConfig = builtins.concatStringsSep "\n" (map (key: "include \"${key.path}\";") keys); zones."${fqdn}" = { # grant "tuxcord.net" zonesub ANY; extraConfig = '' update-policy { ${builtins.concatStringsSep "\n" ( map (key: "grant \"${key.name}\" ${key.type key.name} ANY;") keys )} }; ''; file = "/var/dns/${fqdn}.zone"; # need to put default stuff master = true; }; }; environment.persistence."/persist".directories = [ { directory = "/var/dns"; group = "named"; user = "named"; } ]; networking.firewall = let ports = [ config.services.bind.listenOnPort ]; in { allowedTCPPorts = ports; allowedUDPPorts = ports; }; }; }