Various updates.

This commit is contained in:
niten 2022-08-22 11:30:04 -07:00
parent 070a5e1831
commit b9def9eba9
4 changed files with 266 additions and 250 deletions

View File

@ -9,12 +9,10 @@ let
localhost-ips = let localhost-ips = let
addr-only = addrinfo: addrinfo.address; addr-only = addrinfo: addrinfo.address;
interface = config.networking.interfaces.lo; interface = config.networking.interfaces.lo;
in in (map addr-only interface.ipv4.addresses)
(map addr-only interface.ipv4.addresses) ++ ++ (map addr-only interface.ipv6.addresses);
(map addr-only interface.ipv6.addresses);
host-ips = host-ips = (pkgs.lib.fudo.network.host-ips hostname) ++ localhost-ips;
(pkgs.lib.fudo.network.host-ips hostname) ++ localhost-ips;
state-directory = toplevel.config.fudo.auth.kdc.state-directory; state-directory = toplevel.config.fudo.auth.kdc.state-directory;
@ -24,8 +22,7 @@ let
master-server = cfg.master-config != null; master-server = cfg.master-config != null;
slave-server = cfg.slave-config != null; slave-server = cfg.slave-config != null;
get-fqdn = hostname: get-fqdn = hostname: "${hostname}.${config.fudo.hosts.${hostname}.domain}";
"${hostname}.${config.fudo.hosts.${hostname}.domain}";
kdc-conf = generate-kdc-conf { kdc-conf = generate-kdc-conf {
realm = cfg.realm; realm = cfg.realm;
@ -34,27 +31,28 @@ let
acl-data = if master-server then cfg.master-config.acl else null; acl-data = if master-server then cfg.master-config.acl else null;
}; };
initialize-db = initialize-db = { realm, user, group, kdc-conf, key-file, db-name
{ realm, user, group, kdc-conf, key-file, db-name, max-lifetime, max-renewal, , max-lifetime, max-renewal, primary-keytab, kadmin-keytab, kpasswd-keytab
primary-keytab, kadmin-keytab, kpasswd-keytab, ipropd-keytab, local-hostname }: let , ipropd-keytab, local-hostname }:
let
kadmin-cmd = "kadmin -l -c ${kdc-conf} --"; kadmin-cmd = "kadmin -l -c ${kdc-conf} --";
get-domain-hosts = domain: let get-domain-hosts = domain:
let
host-in-subdomain = host: hostOpts: host-in-subdomain = host: hostOpts:
(builtins.match "(.+[.])?${domain}$" hostOpts.domain) != null; (builtins.match "(.+[.])?${domain}$" hostOpts.domain) != null;
in attrNames (filterAttrs host-in-subdomain config.fudo.hosts); in attrNames (filterAttrs host-in-subdomain config.fudo.hosts);
get-host-principals = realm: hostname: let get-host-principals = realm: hostname:
host = config.fudo.hosts.${hostname}; let host = config.fudo.hosts.${hostname};
in map (service: "${service}/${hostname}.${host.domain}@${realm}") in map (service: "${service}/${hostname}.${host.domain}@${realm}")
host.kerberos-services; host.kerberos-services;
add-principal-str = principal: add-principal-str = principal:
"${kadmin-cmd} add --random-key --use-defaults ${principal}"; "${kadmin-cmd} add --random-key --use-defaults ${principal}";
test-existence = principal: test-existence = principal: "[[ $( ${kadmin-cmd} get ${principal} ) ]]";
"[[ $( ${kadmin-cmd} get ${principal} ) ]]";
exists-or-add = principal: '' exists-or-add = principal: ''
if ${test-existence principal}; then if ${test-existence principal}; then
@ -65,21 +63,19 @@ let
''; '';
ensure-host-principals = realm: ensure-host-principals = realm:
concatStringsSep "\n" concatStringsSep "\n" (map exists-or-add
(map exists-or-add
(concatMap (get-host-principals realm) (concatMap (get-host-principals realm)
(get-domain-hosts (toLower realm)))); (get-domain-hosts (toLower realm))));
slave-hostnames = map get-fqdn cfg.master-config.slave-hosts; slave-hostnames = map get-fqdn cfg.master-config.slave-hosts;
ensure-iprop-principals = concatStringsSep "\n" ensure-iprop-principals = concatStringsSep "\n"
(map (host: exists-or-add "iprop/${host}@${realm}") (map (host: exists-or-add "iprop/${host}@${realm}") [ local-hostname ]
[ local-hostname ] ++ slave-hostnames); ++ slave-hostnames);
copy-slave-principals-file = let copy-slave-principals-file = let
slave-principals = map slave-principals =
(host: "iprop/${hostname}@${cfg.realm}") map (host: "iprop/${hostname}@${cfg.realm}") slave-hostnames;
slave-hostnames;
slave-principals-file = pkgs.writeText "heimdal-slave-principals" slave-principals-file = pkgs.writeText "heimdal-slave-principals"
(concatStringsSep "\n" slave-principals); (concatStringsSep "\n" slave-principals);
in optionalString (slave-principals-file != null) '' in optionalString (slave-principals-file != null) ''
@ -128,8 +124,10 @@ let
dbname = sqlite:${db-file} dbname = sqlite:${db-file}
realm = ${realm} realm = ${realm}
mkey_file = ${key-file} mkey_file = ${key-file}
${optionalString (acl-data != null) ${
"acl_file = ${generate-acl-file acl-data}"} optionalString (acl-data != null)
"acl_file = ${generate-acl-file acl-data}"
}
log_file = ${iprop-log} log_file = ${iprop-log}
} }
@ -171,18 +169,17 @@ let
}; };
}; };
generate-acl-file = acl-entries: let generate-acl-file = acl-entries:
perms-to-permstring = perms: concatStringsSep "," perms; let perms-to-permstring = perms: concatStringsSep "," perms;
in in pkgs.writeText "kdc.acl" (concatStringsSep "\n" (mapAttrsToList
pkgs.writeText "kdc.acl" (concatStringsSep "\n" (mapAttrsToList
(principal: opts: (principal: opts:
"${principal} ${perms-to-permstring opts.perms}${ "${principal} ${perms-to-permstring opts.perms}${
optionalString (opts.target != null) " ${opts.target}" }") optionalString (opts.target != null) " ${opts.target}"
acl-entries)); }") acl-entries));
kadmin-local = kdc-conf: kadmin-local = kdc-conf:
pkgs.writeShellScriptBin "kadmin.local" '' pkgs.writeShellScriptBin "kadmin.local" ''
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} $@ ${pkgs.heimdal}/bin/kadmin -l -c ${kdc-conf} $@
''; '';
masterOpts = { ... }: { masterOpts = { ... }: {
@ -329,8 +326,7 @@ in {
} }
{ {
assertion = !(master-server && slave-server); assertion = !(master-server && slave-server);
message = message = "Only one of master-config and slave-config may be provided.";
"Only one of master-config and slave-config may be provided.";
} }
]; ];
@ -363,7 +359,7 @@ in {
}; };
environment = { environment = {
systemPackages = [ pkgs.heimdalFull (kadmin-local kdc-conf) ]; systemPackages = [ pkgs.heimdal (kadmin-local kdc-conf) ];
## This shouldn't be necessary...every host gets a krb5.keytab ## This shouldn't be necessary...every host gets a krb5.keytab
# etc = { # etc = {
@ -376,9 +372,8 @@ in {
# }; # };
}; };
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules =
"d ${state-directory} 0740 ${cfg.user} ${cfg.group} - -" [ "d ${state-directory} 0740 ${cfg.user} ${cfg.group} - -" ];
];
fudo.system = { fudo.system = {
services = if master-server then { services = if master-server then {
@ -391,7 +386,8 @@ in {
after = [ "network.target" ]; after = [ "network.target" ];
description = description =
"Heimdal Kerberos Key Distribution Center (ticket server)."; "Heimdal Kerberos Key Distribution Center (ticket server).";
execStart = "${pkgs.heimdalFull}/libexec/heimdal/kdc -c ${kdc-conf} --ports=88 ${listen-addrs}"; execStart =
"${pkgs.heimdal}/libexec/heimdal/kdc -c ${kdc-conf} --ports=88 ${listen-addrs}";
user = cfg.user; user = cfg.user;
group = cfg.group; group = cfg.group;
workingDirectory = state-directory; workingDirectory = state-directory;
@ -426,19 +422,22 @@ in {
execStart = "${init-cmd}"; execStart = "${init-cmd}";
user = cfg.user; user = cfg.user;
group = cfg.group; group = cfg.group;
path = with pkgs; [ heimdalFull ]; path = with pkgs; [ heimdal ];
protectSystem = "full"; protectSystem = "full";
addressFamilies = [ "AF_INET" "AF_INET6" ]; addressFamilies = [ "AF_INET" "AF_INET6" ];
workingDirectory = state-directory; workingDirectory = state-directory;
environment = { KRB5_CONFIG = "/etc/krb5.conf"; }; environment = { KRB5_CONFIG = "/etc/krb5.conf"; };
}; };
heimdal-ipropd-master = mkIf (length cfg.master-config.slave-hosts > 0) { heimdal-ipropd-master =
mkIf (length cfg.master-config.slave-hosts > 0) {
requires = [ "heimdal-kdc.service" ]; requires = [ "heimdal-kdc.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Propagate changes to the master KDC DB to all slaves."; description =
path = with pkgs; [ heimdalFull ]; "Propagate changes to the master KDC DB to all slaves.";
execStart = "${pkgs.heimdalFull}/libexec/heimdal/ipropd-master -c ${kdc-conf} -k ${cfg.master.ipropd-keytab}"; path = with pkgs; [ heimdal ];
execStart =
"${pkgs.heimdal}/libexec/heimdal/ipropd-master -c ${kdc-conf} -k ${cfg.master.ipropd-keytab}";
user = cfg.user; user = cfg.user;
group = cfg.group; group = cfg.group;
workingDirectory = state-directory; workingDirectory = state-directory;
@ -453,7 +452,7 @@ in {
listen-addrs = concatStringsSep " " listen-addrs = concatStringsSep " "
(map (addr: "--addresses=${addr}") cfg.bind-addresses); (map (addr: "--addresses=${addr}") cfg.bind-addresses);
command = command =
"${pkgs.heimdalFull}/libexec/heimdal/kdc -c ${kdc-conf} --ports=88 ${listen-addrs}"; "${pkgs.heimdal}/libexec/heimdal/kdc -c ${kdc-conf} --ports=88 ${listen-addrs}";
in { in {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
@ -471,10 +470,11 @@ in {
heimdal-ipropd-slave = { heimdal-ipropd-slave = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
description = "Receive changes propagated from the KDC master server."; description =
path = with pkgs; [ heimdalFull ]; "Receive changes propagated from the KDC master server.";
path = with pkgs; [ heimdal ];
execStart = concatStringsSep " " [ execStart = concatStringsSep " " [
"${pkgs.heimdalFull}/libexec/heimdal/ipropd-slave" "${pkgs.heimdal}/libexec/heimdal/ipropd-slave"
"--config-file=${kdc-conf}" "--config-file=${kdc-conf}"
"--keytab=${cfg.slave-config.ipropd-keytab}" "--keytab=${cfg.slave-config.ipropd-keytab}"
"--realm=${cfg.realm}" "--realm=${cfg.realm}"
@ -501,7 +501,7 @@ in {
{ {
name = "kerberos-adm"; name = "kerberos-adm";
user = cfg.user; user = cfg.user;
server = "${pkgs.heimdalFull}/libexec/heimdal/kadmind"; server = "${pkgs.heimdal}/libexec/heimdal/kadmind";
protocol = "tcp"; protocol = "tcp";
serverArgs = serverArgs =
"--config-file=${kdc-conf} --keytab=${cfg.master-config.kadmin-keytab}"; "--config-file=${kdc-conf} --keytab=${cfg.master-config.kadmin-keytab}";
@ -509,7 +509,7 @@ in {
{ {
name = "kpasswd"; name = "kpasswd";
user = cfg.user; user = cfg.user;
server = "${pkgs.heimdalFull}/libexec/heimdal/kpasswdd"; server = "${pkgs.heimdal}/libexec/heimdal/kpasswdd";
protocol = "udp"; protocol = "udp";
serverArgs = serverArgs =
"--config-file=${kdc-conf} --keytab=${cfg.master-config.kpasswdd-keytab}"; "--config-file=${kdc-conf} --keytab=${cfg.master-config.kpasswdd-keytab}";
@ -519,12 +519,10 @@ in {
networking = { networking = {
firewall = { firewall = {
allowedTCPPorts = [ 88 ] ++ allowedTCPPorts = [ 88 ] ++ (optionals master-server [ 749 ])
(optionals master-server [ 749 ]) ++ ++ (optionals slave-server [ 2121 ]);
(optionals slave-server [ 2121 ]); allowedUDPPorts = [ 88 ] ++ (optionals master-server [ 464 ])
allowedUDPPorts = [ 88 ] ++ ++ (optionals slave-server [ 2121 ]);
(optionals master-server [ 464 ]) ++
(optionals slave-server [ 2121 ]);
}; };
}; };
}; };

View File

@ -1,8 +1,7 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib; with lib;
let let cfg = config.fudo.minecraft-server;
cfg = config.fudo.minecraft-server;
in { in {
options.fudo.minecraft-server = { options.fudo.minecraft-server = {
@ -11,7 +10,7 @@ in {
package = mkOption { package = mkOption {
type = types.package; type = types.package;
description = "Minecraft package to use."; description = "Minecraft package to use.";
default = pkgs.minecraft-server_1_15_1; default = pkgs.minecraft-current;
}; };
data-dir = mkOption { data-dir = mkOption {
@ -27,6 +26,7 @@ in {
motd = mkOption { motd = mkOption {
type = types.str; type = types.str;
description = "Welcome message for newcomers."; description = "Welcome message for newcomers.";
default = "Welcome to Minecraft! Have fun building...";
}; };
game-mode = mkOption { game-mode = mkOption {
@ -40,12 +40,15 @@ in {
description = "Difficulty level, where 0 is peaceful and 3 is hard."; description = "Difficulty level, where 0 is peaceful and 3 is hard.";
default = 2; default = 2;
}; };
allow-cheats = mkOption {
type = types.bool;
default = false;
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
environment.systemPackages = [ environment.systemPackages = [ cfg.package ];
cfg.package
];
services.minecraft-server = { services.minecraft-server = {
enable = true; enable = true;
@ -58,6 +61,7 @@ in {
motd = cfg.motd; motd = cfg.motd;
difficulty = cfg.difficulty; difficulty = cfg.difficulty;
gamemode = cfg.game-mode; gamemode = cfg.game-mode;
allow-cheats = true;
}; };
}; };
}; };

View File

@ -18,19 +18,20 @@ let
ipv6 = cfg.ipv6; ipv6 = cfg.ipv6;
ratelimit = cfg.ratelimit.enable; ratelimit = cfg.ratelimit.enable;
rootServer = cfg.rootServer; rootServer = cfg.rootServer;
zoneStats = length (collect (x: (x.zoneStats or null) != null) cfg.zones) > 0; zoneStats = length (collect (x: (x.zoneStats or null) != null) cfg.zones)
> 0;
}; };
mkZoneFileName = name: if name == "." then "root" else name; mkZoneFileName = name: if name == "." then "root" else name;
# replaces include: directives for keys with fake keys for nsd-checkconf # replaces include: directives for keys with fake keys for nsd-checkconf
injectFakeKeys = keys: concatStrings injectFakeKeys = keys:
(mapAttrsToList concatStrings (mapAttrsToList (keyName: keyOptions: ''
(keyName: keyOptions: '' fakeKey="$(${pkgs.bind}/bin/tsig-keygen -a ${
fakeKey="$(${pkgs.bind}/bin/tsig-keygen -a ${escapeShellArgs [ keyOptions.algorithm keyName ]} | grep -oP "\s*secret \"\K.*(?=\";)")" escapeShellArgs [ keyOptions.algorithm keyName ]
} | grep -oP "\s*secret \"\K.*(?=\";)")"
sed "s@^\s*include:\s*\"${stateDir}/private/${keyName}\"\$@secret: $fakeKey@" -i $out/nsd.conf sed "s@^\s*include:\s*\"${stateDir}/private/${keyName}\"\$@secret: $fakeKey@" -i $out/nsd.conf
'') '') keys);
keys);
nsdEnv = pkgs.buildEnv { nsdEnv = pkgs.buildEnv {
name = "nsd-env"; name = "nsd-env";
@ -64,13 +65,13 @@ let
''; '';
}; };
writeZoneData = name: text: pkgs.writeTextFile { writeZoneData = name: text:
pkgs.writeTextFile {
name = "nsd-zone-${mkZoneFileName name}"; name = "nsd-zone-${mkZoneFileName name}";
inherit text; inherit text;
destination = "/zones/${mkZoneFileName name}"; destination = "/zones/${mkZoneFileName name}";
}; };
# options are ordered alphanumerically by the nixos option name # options are ordered alphanumerically by the nixos option name
configFile = pkgs.writeTextDir "nsd.conf" '' configFile = pkgs.writeTextDir "nsd.conf" ''
server: server:
@ -129,10 +130,10 @@ let
yesOrNo = b: if b then "yes" else "no"; yesOrNo = b: if b then "yes" else "no";
maybeString = prefix: x: if x == null then "" else ''${prefix} "${x}"''; maybeString = prefix: x: if x == null then "" else ''${prefix} "${x}"'';
maybeToString = prefix: x: if x == null then "" else ''${prefix} ${toString x}''; maybeToString = prefix: x:
if x == null then "" else "${prefix} ${toString x}";
forEach = pre: l: concatMapStrings (x: pre + x + "\n") l; forEach = pre: l: concatMapStrings (x: pre + x + "\n") l;
keyConfigFile = concatStrings (mapAttrsToList (keyName: keyOptions: '' keyConfigFile = concatStrings (mapAttrsToList (keyName: keyOptions: ''
key: key:
name: "${keyName}" name: "${keyName}"
@ -148,7 +149,6 @@ let
chmod 0400 "$dest" chmod 0400 "$dest"
'') cfg.keys); '') cfg.keys);
# options are ordered alphanumerically by the nixos option name # options are ordered alphanumerically by the nixos option name
zoneConfigFile = name: zone: '' zoneConfigFile = name: zone: ''
zone: zone:
@ -174,27 +174,19 @@ let
zoneConfigs' = parent: name: zone: zoneConfigs' = parent: name: zone:
if !(zone ? children) || zone.children == null || zone.children == { } if !(zone ? children) || zone.children == null || zone.children == { }
# leaf -> actual zone # leaf -> actual zone
then listToAttrs [ (nameValuePair name (parent // zone)) ] then
listToAttrs [
(nameValuePair name (parent // zone))
]
# fork -> pattern # fork -> pattern
else zipAttrsWith (name: head) ( else
mapAttrsToList (name: child: zoneConfigs' (parent // zone // { children = {}; }) name child) zipAttrsWith (name: head) (mapAttrsToList (name: child:
zone.children zoneConfigs' (parent // zone // { children = { }; }) name child)
); zone.children);
# fighting infinite recursion
zoneOptions = zoneOptionsRaw // childConfig zoneOptions1 true;
zoneOptions1 = zoneOptionsRaw // childConfig zoneOptions2 false;
zoneOptions2 = zoneOptionsRaw // childConfig zoneOptions3 false;
zoneOptions3 = zoneOptionsRaw // childConfig zoneOptions4 false;
zoneOptions4 = zoneOptionsRaw // childConfig zoneOptions5 false;
zoneOptions5 = zoneOptionsRaw // childConfig zoneOptions6 false;
zoneOptions6 = zoneOptionsRaw // childConfig null false;
childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; };
# options are ordered alphanumerically # options are ordered alphanumerically
zoneOptionsRaw = types.submodule { zoneOptions = types.submodule {
options = { options = {
allowAXFRFallback = mkOption { allowAXFRFallback = mkOption {
@ -209,7 +201,9 @@ let
allowNotify = mkOption { allowNotify = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ ]; default = [ ];
example = [ "192.0.2.0/24 NOKEY" "10.0.0.1-10.0.0.5 my_tsig_key_name" example = [
"192.0.2.0/24 NOKEY"
"10.0.0.1-10.0.0.5 my_tsig_key_name"
"10.0.3.4&255.255.0.0 BLOCKED" "10.0.3.4&255.255.0.0 BLOCKED"
]; ];
description = '' description = ''
@ -231,6 +225,13 @@ let
}; };
children = mkOption { children = mkOption {
# TODO: This relies on the fact that `types.anything` doesn't set any
# values of its own to any defaults, because in the above zoneConfigs',
# values from children override ones from parents, but only if the
# attributes are defined. Because of this, we can't replace the element
# type here with `zoneConfigs`, since that would set all the attributes
# to default values, breaking the parent inheriting function.
type = types.attrsOf types.anything;
default = { }; default = { };
description = '' description = ''
Children zones inherit all options of their parents. Attributes Children zones inherit all options of their parents. Attributes
@ -245,7 +246,6 @@ let
data = mkOption { data = mkOption {
type = types.lines; type = types.lines;
default = ""; default = "";
example = "";
description = '' description = ''
The actual zone data. This is the content of your zone file. The actual zone data. This is the content of your zone file.
Use imports or pkgs.lib.readFile if you don't want this data in your config file. Use imports or pkgs.lib.readFile if you don't want this data in your config file.
@ -274,7 +274,8 @@ let
}; };
zsk = mkOption { zsk = mkOption {
type = keyPolicy; type = keyPolicy;
default = { keySize = 2048; default = {
keySize = 2048;
prePublish = "1w"; prePublish = "1w";
postPublish = "1w"; postPublish = "1w";
rollPeriod = "1mo"; rollPeriod = "1mo";
@ -283,7 +284,8 @@ let
}; };
ksk = mkOption { ksk = mkOption {
type = keyPolicy; type = keyPolicy;
default = { keySize = 4096; default = {
keySize = 4096;
prePublish = "1mo"; prePublish = "1mo";
postPublish = "1mo"; postPublish = "1mo";
rollPeriod = "0"; rollPeriod = "0";
@ -329,7 +331,6 @@ let
''; '';
}; };
notify = mkOption { notify = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ ]; default = [ ];
@ -380,14 +381,25 @@ let
requestXFR = mkOption { requestXFR = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ ]; default = [ ];
example = [];
description = '' description = ''
Format: <code>[AXFR|UDP] &lt;ip-address&gt; &lt;key-name | NOKEY&gt;</code> Format: <code>[AXFR|UDP] &lt;ip-address&gt; &lt;key-name | NOKEY&gt;</code>
''; '';
}; };
rrlWhitelist = mkOption { rrlWhitelist = mkOption {
type = with types; listOf (enum [ "nxdomain" "error" "referral" "any" "rrsig" "wildcard" "nodata" "dnskey" "positive" "all" ]); type = with types;
listOf (enum [
"nxdomain"
"error"
"referral"
"any"
"rrsig"
"wildcard"
"nodata"
"dnskey"
"positive"
"all"
]);
default = [ ]; default = [ ];
description = '' description = ''
Whitelists the given rrl-types. Whitelists the given rrl-types.
@ -430,7 +442,8 @@ let
}; };
}; };
dnssecZones = (filterAttrs (n: v: if v ? dnssec then v.dnssec else false) zoneConfigs); dnssecZones =
(filterAttrs (n: v: if v ? dnssec then v.dnssec else false) zoneConfigs);
dnssec = dnssecZones != { }; dnssec = dnssecZones != { };
@ -443,11 +456,14 @@ let
${concatStrings (mapAttrsToList signZone dnssecZones)} ${concatStrings (mapAttrsToList signZone dnssecZones)}
''; '';
signZone = name: zone: '' signZone = name: zone: ''
${dnssecTools}/bin/dnssec-keymgr -g ${dnssecTools}/bin/dnssec-keygen -s ${dnssecTools}/bin/dnssec-settime -K ${stateDir}/dnssec -c ${policyFile name zone.dnssecPolicy} ${name} ${dnssecTools}/bin/dnssec-keymgr -g ${dnssecTools}/bin/dnssec-keygen -s ${dnssecTools}/bin/dnssec-settime -K ${stateDir}/dnssec -c ${
policyFile name zone.dnssecPolicy
} ${name}
${dnssecTools}/bin/dnssec-signzone -S -K ${stateDir}/dnssec -o ${name} -O full -N date ${stateDir}/zones/${name} ${dnssecTools}/bin/dnssec-signzone -S -K ${stateDir}/dnssec -o ${name} -O full -N date ${stateDir}/zones/${name}
${nsdPkg}/sbin/nsd-checkzone ${name} ${stateDir}/zones/${name}.signed && mv -v ${stateDir}/zones/${name}.signed ${stateDir}/zones/${name} ${nsdPkg}/sbin/nsd-checkzone ${name} ${stateDir}/zones/${name}.signed && mv -v ${stateDir}/zones/${name}.signed ${stateDir}/zones/${name}
''; '';
policyFile = name: policy: pkgs.writeText "${name}.policy" '' policyFile = name: policy:
pkgs.writeText "${name}.policy" ''
zone ${name} { zone ${name} {
algorithm ${policy.algorithm}; algorithm ${policy.algorithm};
key-size zsk ${toString policy.zsk.keySize}; key-size zsk ${toString policy.zsk.keySize};
@ -462,13 +478,18 @@ let
coverage ${policy.coverage}; coverage ${policy.coverage};
}; };
''; '';
in in {
{
# options are ordered alphanumerically # options are ordered alphanumerically
options.fudo.nsd = { options.fudo.nsd = {
enable = mkEnableOption "NSD authoritative DNS server"; enable = mkEnableOption "NSD authoritative DNS server";
stateDir = mkOption {
type = types.str;
description = "Directory at which to store NSD state data.";
default = "/var/lib/nsd";
};
bind8Stats = mkEnableOption "BIND8 like statistics"; bind8Stats = mkEnableOption "BIND8 like statistics";
dnssecInterval = mkOption { dnssecInterval = mkOption {
@ -587,6 +608,7 @@ in
reuseport = mkOption { reuseport = mkOption {
type = types.bool; type = types.bool;
default = pkgs.stdenv.isLinux; default = pkgs.stdenv.isLinux;
defaultText = literalExpression "pkgs.stdenv.isLinux";
description = '' description = ''
Whether to enable SO_REUSEPORT on all used sockets. This lets multiple Whether to enable SO_REUSEPORT on all used sockets. This lets multiple
processes bind to the same port. This speeds up operation especially processes bind to the same port. This speeds up operation especially
@ -614,13 +636,6 @@ in
''; '';
}; };
stateDir = mkOption {
type = types.str;
description = "Directory at which to store NSD state data.";
default = "/var/lib/nsd";
};
statistics = mkOption { statistics = mkOption {
type = types.nullOr types.int; type = types.nullOr types.int;
default = null; default = null;
@ -689,7 +704,6 @@ in
''; '';
}; };
keys = mkOption { keys = mkOption {
type = types.attrsOf (types.submodule { type = types.attrsOf (types.submodule {
options = { options = {
@ -715,7 +729,7 @@ in
}; };
}); });
default = { }; default = { };
example = literalExample '' example = literalExpression ''
{ "tsig.example.org" = { { "tsig.example.org" = {
algorithm = "hmac-md5"; algorithm = "hmac-md5";
keyFile = "/path/to/my/key"; keyFile = "/path/to/my/key";
@ -727,7 +741,6 @@ in
''; '';
}; };
ratelimit = { ratelimit = {
enable = mkEnableOption "ratelimit capabilities"; enable = mkEnableOption "ratelimit capabilities";
@ -788,7 +801,6 @@ in
}; };
remoteControl = { remoteControl = {
enable = mkEnableOption "remote control via nsd-control"; enable = mkEnableOption "remote control via nsd-control";
@ -850,7 +862,7 @@ in
zones = mkOption { zones = mkOption {
type = types.attrsOf zoneOptions; type = types.attrsOf zoneOptions;
default = { }; default = { };
example = literalExample '' example = literalExpression ''
{ "serverGroup1" = { { "serverGroup1" = {
provideXFR = [ "10.1.2.3 NOKEY" ]; provideXFR = [ "10.1.2.3 NOKEY" ];
children = { children = {
@ -975,4 +987,6 @@ in
}; };
}; };
meta.maintainers = with lib.maintainers; [ hrdinka ];
} }

View File

@ -32,7 +32,6 @@ let
pdns-config-dir = pkgs.writeTextDir "pdns.conf" '' pdns-config-dir = pkgs.writeTextDir "pdns.conf" ''
local-address=${concatStringsSep ", " cfg.listen-v4-addresses} local-address=${concatStringsSep ", " cfg.listen-v4-addresses}
local-ipv6=${concatStringsSep ", " cfg.listen-v6-addresses}
local-port=${toString cfg.port} local-port=${toString cfg.port}
launch= launch=
include-dir=${runtime-dir} include-dir=${runtime-dir}
@ -305,13 +304,14 @@ in {
psql -f ${pkgs.powerdns}/share/doc/pdns/schema.pgsql.sql psql -f ${pkgs.powerdns}/share/doc/pdns/schema.pgsql.sql
fi fi
''; '';
# Wait until posgresql is available before starting ## Doesn't seem to use env vars, and so fails if remote
ExecStartPre = ## Wait until posgresql is available before starting
pkgs.writeShellScript "ensure-postgresql-running.sh" '' # ExecStartPre =
while [ ! "$( psql -tAc "SELECT 1" )" ]; do # pkgs.writeShellScript "ensure-postgresql-running.sh" ''
${pkgs.coreutils}/bin/sleep 3 # while [ ! "$( psql -tAc "SELECT 1" )" ]; do
done # ${pkgs.coreutils}/bin/sleep 3
''; # done
# '';
}; };
}; };