{ config, lib, pkgs, ... }: let cfg = config.dns; in { options.dns = { bind = { enable = lib.mkEnableOption "BIND DNS server"; settings = { interfaces = lib.mkOption { type = lib.types.listOf lib.types.str; default = ["127.0.0.1"]; description = "Network interfaces BIND should listen on"; }; zones = lib.mkOption { type = lib.types.listOf (lib.types.submodule { options = { name = lib.mkOption { type = lib.types.str; description = "Name of the DNS zone"; }; type = lib.mkOption { type = lib.types.enum ["master" "slave"]; default = "master"; description = "Type of DNS zone"; }; file = lib.mkOption { type = lib.types.str; default = ""; description = "Path to zone file"; }; }; }); default = []; description = "DNS zones to configure"; }; extraConfig = lib.mkOption { type = lib.types.lines; default = ""; description = "Additional BIND configuration options"; }; }; }; technitium = { enable = lib.mkEnableOption "Technitium DNS server"; settings = { address = lib.mkOption { type = lib.types.str; default = "0.0.0.0"; description = "IP address Technitium should listen on"; }; port = lib.mkOption { type = lib.types.port; default = 5380; description = "Port for Technitium DNS server"; }; extraOptions = lib.mkOption { type = lib.types.attrs; default = {}; description = "Additional Technitium configuration options"; }; }; }; }; # Validate that only one DNS server is enabled imports = [ (lib.mkIf (cfg.bind.enable && cfg.technitium.enable) (throw "Only one DNS server can be enabled at a time")) ]; # Implementation of the configuration config = lib.mkMerge [ # BIND DNS Server Configuration (lib.mkIf cfg.bind.enable { services.named = { enable = true; interfaces = cfg.bind.settings.interfaces; zones = map (zone: { name = zone.name; type = zone.type; file = zone.file; }) cfg.bind.settings.zones; extraConfig = cfg.bind.settings.extraConfig; }; networking.firewall = { allowedTCPPorts = [53]; allowedUDPPorts = [53]; }; environment.systemPackages = [pkgs.bind]; }) # Technitium DNS Server Configuration (lib.mkIf cfg.technitium.enable { # Create a systemd service for Technitium systemd.services.technitium-dns = { description = "Technitium DNS Server"; wantedBy = ["multi-user.target"]; serviceConfig = { ExecStart = "${pkgs.technitium}/bin/dns-server-start.sh"; Restart = "on-failure"; }; # Environment configuration environment = { DNS_LISTEN_ADDRESS = cfg.technitium.settings.address; DNS_LISTEN_PORT = toString cfg.technitium.settings.port; } // lib.mapAttrs' ( name: value: lib.nameValuePair "DNS_${lib.toUpper name}" (toString value) ) cfg.technitium.settings.extraOptions; }; networking.firewall = { allowedTCPPorts = [cfg.technitium.settings.port]; allowedUDPPorts = [cfg.technitium.settings.port]; }; environment.systemPackages = [pkgs.technitium]; }) ]; }