{ config, lib, ... }: let cfg = config.vhack.dns; zones = builtins.mapAttrs (name: value: { data = dns.types.zone.renderToString name value; }) cfg.zones; dns = import ./dns {inherit lib;}; ports = let parsePorts = listeners: let splitAddress = addr: lib.splitString "@" addr; extractPort = addr: let split = splitAddress addr; in lib.toInt ( if (builtins.length split) == 2 then builtins.elemAt split 1 else "53" ); in builtins.map extractPort listeners; in lib.unique (parsePorts cfg.interfaces); in { options.vhack.dns = { enable = lib.mkEnableOption "custom dns server"; openFirewall = lib.mkOption { type = lib.types.bool; default = false; description = '' Open the following ports: TCP (${lib.concatStringsSep ", " (map toString ports)}) UDP (${lib.concatStringsSep ", " (map toString ports)}) ''; }; interfaces = lib.mkOption { type = lib.types.listOf lib.types.str; description = '' A list of the interfaces to bind to. To select the port add `@` to the end of the interface. The default port is 53. ''; example = [ "192.168.1.3" "2001:db8:1::3" ]; }; zones = lib.mkOption { type = lib.types.attrsOf dns.types.zone.zone; description = "DNS zones"; }; }; config = lib.mkIf cfg.enable { services.nsd = { enable = true; verbosity = 4; inherit (cfg) interfaces; inherit zones; }; networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall ports; networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall ports; }; }