{ config, lib, ... }: let inherit (config.networking) fqdn; agenixDnsDir = ../../agenix/dns + "/${fqdn}"; agenixKeys = builtins.attrNames (builtins.readDir agenixDnsDir); keys = map ( filename: let zonesub = _: "zonesub"; subdomain = name: "subdomain ${name}"; zoneDomain = if lib.strings.hasSuffix ".key.age" filename then lib.strings.removeSuffix ".key.age" filename else throw "${filename} is not a `.key.age` file"; in { name = zoneDomain; path = config.age.secrets."dns/${filename}".path; type = if zoneDomain == fqdn then zonesub else subdomain; } ) agenixKeys; cfg = config.dns; inherit (lib) mkEnableOption mkOption mkIf ; 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; }; }; }; networking.firewall.allowedTCPPorts = [ config.services.bind.listenOnPort ]; networking.firewall.allowedUDPPorts = [ config.services.bind.listenOnPort ]; environment.persistence."/persist" = { directories = [ { directory = "/var/dns"; group = "named"; user = "named"; } ]; }; }; }