at 24.11-pre 6.0 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 "PowerDNS Recursor, a recursive DNS server"; 31 32 dns.address = mkOption { 33 type = oneOrMore types.str; 34 default = [ "::" "0.0.0.0" ]; 35 description = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 = '' 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 environment.etc."pdns-recursor".source = configDir; 163 164 services.pdns-recursor.settings = mkDefaultAttrs { 165 local-address = cfg.dns.address; 166 local-port = cfg.dns.port; 167 allow-from = cfg.dns.allowFrom; 168 169 webserver-address = cfg.api.address; 170 webserver-port = cfg.api.port; 171 webserver-allow-from = cfg.api.allowFrom; 172 173 forward-zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; 174 forward-zones-recurse = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZonesRecurse; 175 export-etc-hosts = cfg.exportHosts; 176 dnssec = cfg.dnssecValidation; 177 serve-rfc1918 = cfg.serveRFC1918; 178 lua-config-file = pkgs.writeText "recursor.lua" cfg.luaConfig; 179 180 daemon = false; 181 write-pid = false; 182 log-timestamp = false; 183 disable-syslog = true; 184 }; 185 186 systemd.packages = [ pkgs.pdns-recursor ]; 187 188 systemd.services.pdns-recursor = { 189 wantedBy = [ "multi-user.target" ]; 190 191 serviceConfig = { 192 ExecStart = [ "" "${pkgs.pdns-recursor}/bin/pdns_recursor --config-dir=${configDir}" ]; 193 }; 194 }; 195 196 users.users.pdns-recursor = { 197 isSystemUser = true; 198 group = "pdns-recursor"; 199 description = "PowerDNS Recursor daemon user"; 200 }; 201 202 users.groups.pdns-recursor = {}; 203 204 }; 205 206 imports = [ 207 (mkRemovedOptionModule [ "services" "pdns-recursor" "extraConfig" ] 208 "To change extra Recursor settings use services.pdns-recursor.settings instead.") 209 ]; 210 211 meta.maintainers = with lib.maintainers; [ rnhmjoj ]; 212 213}