pdns-recursor: add service

rnhmjoj 6bcf89f2 d79ea39d

Changed files
+170
nixos
modules
misc
services
networking
+1
nixos/modules/misc/ids.nix
···
glance = 266;
couchpotato = 267;
gogs = 268;
+
pdns-recursor = 269;
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
+1
nixos/modules/module-list.nix
···
./services/networking/pdnsd.nix
./services/networking/polipo.nix
./services/networking/powerdns.nix
+
./services/networking/pdns-recursor.nix
./services/networking/pptpd.nix
./services/networking/prayer.nix
./services/networking/privoxy.nix
+168
nixos/modules/services/networking/pdns-recursor.nix
···
+
{ config, lib, pkgs, ... }:
+
+
with lib;
+
+
let
+
dataDir = "/var/lib/pdns-recursor";
+
username = "pdns-recursor";
+
+
cfg = config.services.pdns-recursor;
+
zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
+
+
configFile = pkgs.writeText "recursor.conf" ''
+
local-address=${cfg.dns.address}
+
local-port=${toString cfg.dns.port}
+
allow-from=${concatStringsSep "," cfg.dns.allowFrom}
+
+
webserver-address=${cfg.api.address}
+
webserver-port=${toString cfg.api.port}
+
webserver-allow-from=${concatStringsSep "," cfg.api.allowFrom}
+
+
forward-zones=${concatStringsSep "," zones}
+
export-etc-hosts=${if cfg.exportHosts then "yes" else "no"}
+
dnssec=${cfg.dnssecValidation}
+
serve-rfc1918=${if cfg.serveRFC1918 then "yes" else "no"}
+
+
${cfg.extraConfig}
+
'';
+
+
in {
+
options.services.pdns-recursor = {
+
enable = mkEnableOption "PowerDNS Recursor, a recursive DNS server";
+
+
dns.address = mkOption {
+
type = types.str;
+
default = "0.0.0.0";
+
description = ''
+
IP address Recursor DNS server will bind to.
+
'';
+
};
+
+
dns.port = mkOption {
+
type = types.int;
+
default = 53;
+
description = ''
+
Port number Recursor DNS server will bind to.
+
'';
+
};
+
+
dns.allowFrom = mkOption {
+
type = types.listOf types.str;
+
default = [ "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" ];
+
example = [ "0.0.0.0/0" ];
+
description = ''
+
IP address ranges of clients allowed to make DNS queries.
+
'';
+
};
+
+
api.address = mkOption {
+
type = types.str;
+
default = "0.0.0.0";
+
description = ''
+
IP address Recursor REST API server will bind to.
+
'';
+
};
+
+
api.port = mkOption {
+
type = types.int;
+
default = 8082;
+
description = ''
+
Port number Recursor REST API server will bind to.
+
'';
+
};
+
+
api.allowFrom = mkOption {
+
type = types.listOf types.str;
+
default = [ "0.0.0.0/0" ];
+
description = ''
+
IP address ranges of clients allowed to make API requests.
+
'';
+
};
+
+
exportHosts = mkOption {
+
type = types.bool;
+
default = false;
+
description = ''
+
Whether to export names and IP addresses defined in /etc/hosts.
+
'';
+
};
+
+
forwardZones = mkOption {
+
type = types.attrs;
+
example = { eth = "127.0.0.1:5353"; };
+
default = {};
+
description = ''
+
DNS zones to be forwarded to other servers.
+
'';
+
};
+
+
dnssecValidation = mkOption {
+
type = types.enum ["off" "process-no-validate" "process" "log-fail" "validate"];
+
default = "validate";
+
description = ''
+
Controls the level of DNSSEC processing done by the PowerDNS Recursor.
+
See https://doc.powerdns.com/md/recursor/dnssec/ for a detailed explanation.
+
'';
+
};
+
+
serveRFC1918 = mkOption {
+
type = types.bool;
+
default = true;
+
description = ''
+
Whether to directly resolve the RFC1918 reverse-mapping domains:
+
<literal>10.in-addr.arpa</literal>,
+
<literal>168.192.in-addr.arpa</literal>,
+
<literal>16-31.172.in-addr.arpa</literal>
+
This saves load on the AS112 servers.
+
'';
+
};
+
+
extraConfig = mkOption {
+
type = types.lines;
+
default = "";
+
description = ''
+
Extra options to be appended to the configuration file.
+
'';
+
};
+
};
+
+
config = mkIf cfg.enable {
+
+
users.extraUsers."${username}" = {
+
home = dataDir;
+
createHome = true;
+
uid = config.ids.uids.pdns-recursor;
+
description = "PowerDNS Recursor daemon user";
+
};
+
+
systemd.services.pdns-recursor = {
+
unitConfig.Documentation = "man:pdns_recursor(1) man:rec_control(1)";
+
description = "PowerDNS recursive server";
+
wantedBy = [ "multi-user.target" ];
+
after = [ "network.target" ];
+
+
serviceConfig = {
+
User = username;
+
Restart ="on-failure";
+
RestartSec = "5";
+
PrivateTmp = true;
+
PrivateDevices = true;
+
AmbientCapabilities = "cap_net_bind_service";
+
ExecStart = ''${pkgs.pdns-recursor}/bin/pdns_recursor \
+
--config-dir=${dataDir} \
+
--socket-dir=${dataDir} \
+
--disable-syslog
+
'';
+
};
+
+
preStart = ''
+
# Link configuration file into recursor home directory
+
configPath=${dataDir}/recursor.conf
+
if [ "$(realpath $configPath)" != "${configFile}" ]; then
+
rm -f $configPath
+
ln -s ${configFile} $configPath
+
fi
+
'';
+
};
+
};
+
}