at 23.11-pre 6.1 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.pdns-recursor; 7 8 oneOrMore = type: with types; either type (listOf type); 9 valueType = with types; oneOf [ int str bool path ]; 10 configType = with types; attrsOf (nullOr (oneOrMore valueType)); 11 12 toBool = val: if val then "yes" else "no"; 13 serialize = val: with types; 14 if str.check val then val 15 else if int.check val then toString val 16 else if path.check val then toString val 17 else if bool.check val then toBool val 18 else if builtins.isList val then (concatMapStringsSep "," serialize val) 19 else ""; 20 21 configDir = pkgs.writeTextDir "recursor.conf" 22 (concatStringsSep "\n" 23 (flip mapAttrsToList cfg.settings 24 (name: val: "${name}=${serialize val}"))); 25 26 mkDefaultAttrs = mapAttrs (n: v: mkDefault v); 27 28in { 29 options.services.pdns-recursor = { 30 enable = mkEnableOption (lib.mdDoc "PowerDNS Recursor, a recursive DNS server"); 31 32 dns.address = mkOption { 33 type = oneOrMore types.str; 34 default = [ "::" "0.0.0.0" ]; 35 description = lib.mdDoc '' 36 IP addresses Recursor DNS server will bind to. 37 ''; 38 }; 39 40 dns.port = mkOption { 41 type = types.port; 42 default = 53; 43 description = lib.mdDoc '' 44 Port number Recursor DNS server will bind to. 45 ''; 46 }; 47 48 dns.allowFrom = mkOption { 49 type = types.listOf types.str; 50 default = [ 51 "127.0.0.0/8" "10.0.0.0/8" "100.64.0.0/10" 52 "169.254.0.0/16" "192.168.0.0/16" "172.16.0.0/12" 53 "::1/128" "fc00::/7" "fe80::/10" 54 ]; 55 example = [ "0.0.0.0/0" "::/0" ]; 56 description = lib.mdDoc '' 57 IP address ranges of clients allowed to make DNS queries. 58 ''; 59 }; 60 61 api.address = mkOption { 62 type = types.str; 63 default = "0.0.0.0"; 64 description = lib.mdDoc '' 65 IP address Recursor REST API server will bind to. 66 ''; 67 }; 68 69 api.port = mkOption { 70 type = types.port; 71 default = 8082; 72 description = lib.mdDoc '' 73 Port number Recursor REST API server will bind to. 74 ''; 75 }; 76 77 api.allowFrom = mkOption { 78 type = types.listOf types.str; 79 default = [ "127.0.0.1" "::1" ]; 80 example = [ "0.0.0.0/0" "::/0" ]; 81 description = lib.mdDoc '' 82 IP address ranges of clients allowed to make API requests. 83 ''; 84 }; 85 86 exportHosts = mkOption { 87 type = types.bool; 88 default = false; 89 description = lib.mdDoc '' 90 Whether to export names and IP addresses defined in /etc/hosts. 91 ''; 92 }; 93 94 forwardZones = mkOption { 95 type = types.attrs; 96 default = {}; 97 description = lib.mdDoc '' 98 DNS zones to be forwarded to other authoritative servers. 99 ''; 100 }; 101 102 forwardZonesRecurse = mkOption { 103 type = types.attrs; 104 example = { eth = "[::1]:5353"; }; 105 default = {}; 106 description = lib.mdDoc '' 107 DNS zones to be forwarded to other recursive servers. 108 ''; 109 }; 110 111 dnssecValidation = mkOption { 112 type = types.enum ["off" "process-no-validate" "process" "log-fail" "validate"]; 113 default = "validate"; 114 description = lib.mdDoc '' 115 Controls the level of DNSSEC processing done by the PowerDNS Recursor. 116 See https://doc.powerdns.com/md/recursor/dnssec/ for a detailed explanation. 117 ''; 118 }; 119 120 serveRFC1918 = mkOption { 121 type = types.bool; 122 default = true; 123 description = lib.mdDoc '' 124 Whether to directly resolve the RFC1918 reverse-mapping domains: 125 `10.in-addr.arpa`, 126 `168.192.in-addr.arpa`, 127 `16-31.172.in-addr.arpa` 128 This saves load on the AS112 servers. 129 ''; 130 }; 131 132 settings = mkOption { 133 type = configType; 134 default = { }; 135 example = literalExpression '' 136 { 137 loglevel = 8; 138 log-common-errors = true; 139 } 140 ''; 141 description = lib.mdDoc '' 142 PowerDNS Recursor settings. Use this option to configure Recursor 143 settings not exposed in a NixOS option or to bypass one. 144 See the full documentation at 145 <https://doc.powerdns.com/recursor/settings.html> 146 for the available options. 147 ''; 148 }; 149 150 luaConfig = mkOption { 151 type = types.lines; 152 default = ""; 153 description = lib.mdDoc '' 154 The content Lua configuration file for PowerDNS Recursor. See 155 <https://doc.powerdns.com/recursor/lua-config/index.html>. 156 ''; 157 }; 158 }; 159 160 config = mkIf cfg.enable { 161 162 services.pdns-recursor.settings = mkDefaultAttrs { 163 local-address = cfg.dns.address; 164 local-port = cfg.dns.port; 165 allow-from = cfg.dns.allowFrom; 166 167 webserver-address = cfg.api.address; 168 webserver-port = cfg.api.port; 169 webserver-allow-from = cfg.api.allowFrom; 170 171 forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; 172 forward-zones-recurse = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZonesRecurse; 173 export-etc-hosts = cfg.exportHosts; 174 dnssec = cfg.dnssecValidation; 175 serve-rfc1918 = cfg.serveRFC1918; 176 lua-config-file = pkgs.writeText "recursor.lua" cfg.luaConfig; 177 178 daemon = false; 179 write-pid = false; 180 log-timestamp = false; 181 disable-syslog = true; 182 }; 183 184 systemd.packages = [ pkgs.pdns-recursor ]; 185 186 systemd.services.pdns-recursor = { 187 wantedBy = [ "multi-user.target" ]; 188 189 serviceConfig = { 190 ExecStart = [ "" "${pkgs.pdns-recursor}/bin/pdns_recursor --config-dir=${configDir}" ]; 191 }; 192 }; 193 194 users.users.pdns-recursor = { 195 isSystemUser = true; 196 group = "pdns-recursor"; 197 description = "PowerDNS Recursor daemon user"; 198 }; 199 200 users.groups.pdns-recursor = {}; 201 202 }; 203 204 imports = [ 205 (mkRemovedOptionModule [ "services" "pdns-recursor" "extraConfig" ] 206 "To change extra Recursor settings use services.pdns-recursor.settings instead.") 207 ]; 208 209 meta.maintainers = with lib.maintainers; [ rnhmjoj ]; 210 211}