Various updates.
This commit is contained in:
parent
070a5e1831
commit
b9def9eba9
110
lib/fudo/kdc.nix
110
lib/fudo/kdc.nix
@ -1,4 +1,4 @@
|
||||
{ config, lib, pkgs, ... } @ toplevel:
|
||||
{ config, lib, pkgs, ... }@toplevel:
|
||||
|
||||
with lib;
|
||||
let
|
||||
@ -9,12 +9,10 @@ let
|
||||
localhost-ips = let
|
||||
addr-only = addrinfo: addrinfo.address;
|
||||
interface = config.networking.interfaces.lo;
|
||||
in
|
||||
(map addr-only interface.ipv4.addresses) ++
|
||||
(map addr-only interface.ipv6.addresses);
|
||||
in (map addr-only interface.ipv4.addresses)
|
||||
++ (map addr-only interface.ipv6.addresses);
|
||||
|
||||
host-ips =
|
||||
(pkgs.lib.fudo.network.host-ips hostname) ++ localhost-ips;
|
||||
host-ips = (pkgs.lib.fudo.network.host-ips hostname) ++ localhost-ips;
|
||||
|
||||
state-directory = toplevel.config.fudo.auth.kdc.state-directory;
|
||||
|
||||
@ -24,8 +22,7 @@ let
|
||||
master-server = cfg.master-config != null;
|
||||
slave-server = cfg.slave-config != null;
|
||||
|
||||
get-fqdn = hostname:
|
||||
"${hostname}.${config.fudo.hosts.${hostname}.domain}";
|
||||
get-fqdn = hostname: "${hostname}.${config.fudo.hosts.${hostname}.domain}";
|
||||
|
||||
kdc-conf = generate-kdc-conf {
|
||||
realm = cfg.realm;
|
||||
@ -34,27 +31,28 @@ let
|
||||
acl-data = if master-server then cfg.master-config.acl else null;
|
||||
};
|
||||
|
||||
initialize-db =
|
||||
{ realm, user, group, kdc-conf, key-file, db-name, max-lifetime, max-renewal,
|
||||
primary-keytab, kadmin-keytab, kpasswd-keytab, ipropd-keytab, local-hostname }: let
|
||||
initialize-db = { realm, user, group, kdc-conf, key-file, db-name
|
||||
, max-lifetime, max-renewal, primary-keytab, kadmin-keytab, kpasswd-keytab
|
||||
, ipropd-keytab, local-hostname }:
|
||||
let
|
||||
|
||||
kadmin-cmd = "kadmin -l -c ${kdc-conf} --";
|
||||
|
||||
get-domain-hosts = domain: let
|
||||
get-domain-hosts = domain:
|
||||
let
|
||||
host-in-subdomain = host: hostOpts:
|
||||
(builtins.match "(.+[.])?${domain}$" hostOpts.domain) != null;
|
||||
in attrNames (filterAttrs host-in-subdomain config.fudo.hosts);
|
||||
|
||||
get-host-principals = realm: hostname: let
|
||||
host = config.fudo.hosts.${hostname};
|
||||
get-host-principals = realm: hostname:
|
||||
let host = config.fudo.hosts.${hostname};
|
||||
in map (service: "${service}/${hostname}.${host.domain}@${realm}")
|
||||
host.kerberos-services;
|
||||
|
||||
add-principal-str = principal:
|
||||
"${kadmin-cmd} add --random-key --use-defaults ${principal}";
|
||||
|
||||
test-existence = principal:
|
||||
"[[ $( ${kadmin-cmd} get ${principal} ) ]]";
|
||||
test-existence = principal: "[[ $( ${kadmin-cmd} get ${principal} ) ]]";
|
||||
|
||||
exists-or-add = principal: ''
|
||||
if ${test-existence principal}; then
|
||||
@ -65,21 +63,19 @@ let
|
||||
'';
|
||||
|
||||
ensure-host-principals = realm:
|
||||
concatStringsSep "\n"
|
||||
(map exists-or-add
|
||||
concatStringsSep "\n" (map exists-or-add
|
||||
(concatMap (get-host-principals realm)
|
||||
(get-domain-hosts (toLower realm))));
|
||||
|
||||
slave-hostnames = map get-fqdn cfg.master-config.slave-hosts;
|
||||
|
||||
ensure-iprop-principals = concatStringsSep "\n"
|
||||
(map (host: exists-or-add "iprop/${host}@${realm}")
|
||||
[ local-hostname ] ++ slave-hostnames);
|
||||
(map (host: exists-or-add "iprop/${host}@${realm}") [ local-hostname ]
|
||||
++ slave-hostnames);
|
||||
|
||||
copy-slave-principals-file = let
|
||||
slave-principals = map
|
||||
(host: "iprop/${hostname}@${cfg.realm}")
|
||||
slave-hostnames;
|
||||
slave-principals =
|
||||
map (host: "iprop/${hostname}@${cfg.realm}") slave-hostnames;
|
||||
slave-principals-file = pkgs.writeText "heimdal-slave-principals"
|
||||
(concatStringsSep "\n" slave-principals);
|
||||
in optionalString (slave-principals-file != null) ''
|
||||
@ -128,8 +124,10 @@ let
|
||||
dbname = sqlite:${db-file}
|
||||
realm = ${realm}
|
||||
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}
|
||||
}
|
||||
|
||||
@ -171,18 +169,17 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
generate-acl-file = acl-entries: let
|
||||
perms-to-permstring = perms: concatStringsSep "," perms;
|
||||
in
|
||||
pkgs.writeText "kdc.acl" (concatStringsSep "\n" (mapAttrsToList
|
||||
generate-acl-file = acl-entries:
|
||||
let perms-to-permstring = perms: concatStringsSep "," perms;
|
||||
in pkgs.writeText "kdc.acl" (concatStringsSep "\n" (mapAttrsToList
|
||||
(principal: opts:
|
||||
"${principal} ${perms-to-permstring opts.perms}${
|
||||
optionalString (opts.target != null) " ${opts.target}" }")
|
||||
acl-entries));
|
||||
optionalString (opts.target != null) " ${opts.target}"
|
||||
}") acl-entries));
|
||||
|
||||
kadmin-local = kdc-conf:
|
||||
pkgs.writeShellScriptBin "kadmin.local" ''
|
||||
${pkgs.heimdalFull}/bin/kadmin -l -c ${kdc-conf} $@
|
||||
${pkgs.heimdal}/bin/kadmin -l -c ${kdc-conf} $@
|
||||
'';
|
||||
|
||||
masterOpts = { ... }: {
|
||||
@ -329,8 +326,7 @@ in {
|
||||
}
|
||||
{
|
||||
assertion = !(master-server && slave-server);
|
||||
message =
|
||||
"Only one of master-config and slave-config may be provided.";
|
||||
message = "Only one of master-config and slave-config may be provided.";
|
||||
}
|
||||
];
|
||||
|
||||
@ -363,7 +359,7 @@ in {
|
||||
};
|
||||
|
||||
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
|
||||
# etc = {
|
||||
@ -376,9 +372,8 @@ in {
|
||||
# };
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${state-directory} 0740 ${cfg.user} ${cfg.group} - -"
|
||||
];
|
||||
systemd.tmpfiles.rules =
|
||||
[ "d ${state-directory} 0740 ${cfg.user} ${cfg.group} - -" ];
|
||||
|
||||
fudo.system = {
|
||||
services = if master-server then {
|
||||
@ -391,7 +386,8 @@ in {
|
||||
after = [ "network.target" ];
|
||||
description =
|
||||
"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;
|
||||
group = cfg.group;
|
||||
workingDirectory = state-directory;
|
||||
@ -426,19 +422,22 @@ in {
|
||||
execStart = "${init-cmd}";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
path = with pkgs; [ heimdalFull ];
|
||||
path = with pkgs; [ heimdal ];
|
||||
protectSystem = "full";
|
||||
addressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
workingDirectory = state-directory;
|
||||
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" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Propagate changes to the master KDC DB to all slaves.";
|
||||
path = with pkgs; [ heimdalFull ];
|
||||
execStart = "${pkgs.heimdalFull}/libexec/heimdal/ipropd-master -c ${kdc-conf} -k ${cfg.master.ipropd-keytab}";
|
||||
description =
|
||||
"Propagate changes to the master KDC DB to all slaves.";
|
||||
path = with pkgs; [ heimdal ];
|
||||
execStart =
|
||||
"${pkgs.heimdal}/libexec/heimdal/ipropd-master -c ${kdc-conf} -k ${cfg.master.ipropd-keytab}";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
workingDirectory = state-directory;
|
||||
@ -453,7 +452,7 @@ in {
|
||||
listen-addrs = concatStringsSep " "
|
||||
(map (addr: "--addresses=${addr}") cfg.bind-addresses);
|
||||
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 {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
@ -471,10 +470,11 @@ in {
|
||||
|
||||
heimdal-ipropd-slave = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Receive changes propagated from the KDC master server.";
|
||||
path = with pkgs; [ heimdalFull ];
|
||||
description =
|
||||
"Receive changes propagated from the KDC master server.";
|
||||
path = with pkgs; [ heimdal ];
|
||||
execStart = concatStringsSep " " [
|
||||
"${pkgs.heimdalFull}/libexec/heimdal/ipropd-slave"
|
||||
"${pkgs.heimdal}/libexec/heimdal/ipropd-slave"
|
||||
"--config-file=${kdc-conf}"
|
||||
"--keytab=${cfg.slave-config.ipropd-keytab}"
|
||||
"--realm=${cfg.realm}"
|
||||
@ -501,7 +501,7 @@ in {
|
||||
{
|
||||
name = "kerberos-adm";
|
||||
user = cfg.user;
|
||||
server = "${pkgs.heimdalFull}/libexec/heimdal/kadmind";
|
||||
server = "${pkgs.heimdal}/libexec/heimdal/kadmind";
|
||||
protocol = "tcp";
|
||||
serverArgs =
|
||||
"--config-file=${kdc-conf} --keytab=${cfg.master-config.kadmin-keytab}";
|
||||
@ -509,7 +509,7 @@ in {
|
||||
{
|
||||
name = "kpasswd";
|
||||
user = cfg.user;
|
||||
server = "${pkgs.heimdalFull}/libexec/heimdal/kpasswdd";
|
||||
server = "${pkgs.heimdal}/libexec/heimdal/kpasswdd";
|
||||
protocol = "udp";
|
||||
serverArgs =
|
||||
"--config-file=${kdc-conf} --keytab=${cfg.master-config.kpasswdd-keytab}";
|
||||
@ -519,12 +519,10 @@ in {
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
allowedTCPPorts = [ 88 ] ++
|
||||
(optionals master-server [ 749 ]) ++
|
||||
(optionals slave-server [ 2121 ]);
|
||||
allowedUDPPorts = [ 88 ] ++
|
||||
(optionals master-server [ 464 ]) ++
|
||||
(optionals slave-server [ 2121 ]);
|
||||
allowedTCPPorts = [ 88 ] ++ (optionals master-server [ 749 ])
|
||||
++ (optionals slave-server [ 2121 ]);
|
||||
allowedUDPPorts = [ 88 ] ++ (optionals master-server [ 464 ])
|
||||
++ (optionals slave-server [ 2121 ]);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,8 +1,7 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.fudo.minecraft-server;
|
||||
let cfg = config.fudo.minecraft-server;
|
||||
|
||||
in {
|
||||
options.fudo.minecraft-server = {
|
||||
@ -11,7 +10,7 @@ in {
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = "Minecraft package to use.";
|
||||
default = pkgs.minecraft-server_1_15_1;
|
||||
default = pkgs.minecraft-current;
|
||||
};
|
||||
|
||||
data-dir = mkOption {
|
||||
@ -27,10 +26,11 @@ in {
|
||||
motd = mkOption {
|
||||
type = types.str;
|
||||
description = "Welcome message for newcomers.";
|
||||
default = "Welcome to Minecraft! Have fun building...";
|
||||
};
|
||||
|
||||
game-mode = mkOption {
|
||||
type = types.enum ["survival" "creative" "adventure" "spectator"];
|
||||
type = types.enum [ "survival" "creative" "adventure" "spectator" ];
|
||||
description = "Game mode of the server.";
|
||||
default = "survival";
|
||||
};
|
||||
@ -40,12 +40,15 @@ in {
|
||||
description = "Difficulty level, where 0 is peaceful and 3 is hard.";
|
||||
default = 2;
|
||||
};
|
||||
|
||||
allow-cheats = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
];
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.minecraft-server = {
|
||||
enable = true;
|
||||
@ -58,6 +61,7 @@ in {
|
||||
motd = cfg.motd;
|
||||
difficulty = cfg.difficulty;
|
||||
gamemode = cfg.game-mode;
|
||||
allow-cheats = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
140
lib/fudo/nsd.nix
140
lib/fudo/nsd.nix
@ -1,4 +1,4 @@
|
||||
### NOTE:
|
||||
# ## NOTE:
|
||||
## This is a copy of the upstream version, which allows for overriding the state directory
|
||||
|
||||
{ config, pkgs, lib, ... }:
|
||||
@ -18,19 +18,20 @@ let
|
||||
ipv6 = cfg.ipv6;
|
||||
ratelimit = cfg.ratelimit.enable;
|
||||
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;
|
||||
|
||||
# replaces include: directives for keys with fake keys for nsd-checkconf
|
||||
injectFakeKeys = keys: concatStrings
|
||||
(mapAttrsToList
|
||||
(keyName: keyOptions: ''
|
||||
fakeKey="$(${pkgs.bind}/bin/tsig-keygen -a ${escapeShellArgs [ keyOptions.algorithm keyName ]} | grep -oP "\s*secret \"\K.*(?=\";)")"
|
||||
injectFakeKeys = keys:
|
||||
concatStrings (mapAttrsToList (keyName: keyOptions: ''
|
||||
fakeKey="$(${pkgs.bind}/bin/tsig-keygen -a ${
|
||||
escapeShellArgs [ keyOptions.algorithm keyName ]
|
||||
} | grep -oP "\s*secret \"\K.*(?=\";)")"
|
||||
sed "s@^\s*include:\s*\"${stateDir}/private/${keyName}\"\$@secret: $fakeKey@" -i $out/nsd.conf
|
||||
'')
|
||||
keys);
|
||||
'') keys);
|
||||
|
||||
nsdEnv = pkgs.buildEnv {
|
||||
name = "nsd-env";
|
||||
@ -64,13 +65,13 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
writeZoneData = name: text: pkgs.writeTextFile {
|
||||
writeZoneData = name: text:
|
||||
pkgs.writeTextFile {
|
||||
name = "nsd-zone-${mkZoneFileName name}";
|
||||
inherit text;
|
||||
destination = "/zones/${mkZoneFileName name}";
|
||||
};
|
||||
|
||||
|
||||
# options are ordered alphanumerically by the nixos option name
|
||||
configFile = pkgs.writeTextDir "nsd.conf" ''
|
||||
server:
|
||||
@ -129,10 +130,10 @@ let
|
||||
|
||||
yesOrNo = b: if b then "yes" else "no";
|
||||
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;
|
||||
|
||||
|
||||
keyConfigFile = concatStrings (mapAttrsToList (keyName: keyOptions: ''
|
||||
key:
|
||||
name: "${keyName}"
|
||||
@ -148,7 +149,6 @@ let
|
||||
chmod 0400 "$dest"
|
||||
'') cfg.keys);
|
||||
|
||||
|
||||
# options are ordered alphanumerically by the nixos option name
|
||||
zoneConfigFile = name: zone: ''
|
||||
zone:
|
||||
@ -169,32 +169,24 @@ let
|
||||
${forEach " provide-xfr: " zone.provideXFR}
|
||||
'';
|
||||
|
||||
zoneConfigs = zoneConfigs' {} "" { children = cfg.zones; };
|
||||
zoneConfigs = zoneConfigs' { } "" { children = cfg.zones; };
|
||||
|
||||
zoneConfigs' = parent: name: zone:
|
||||
if !(zone ? children) || zone.children == null || zone.children == { }
|
||||
# leaf -> actual zone
|
||||
then listToAttrs [ (nameValuePair name (parent // zone)) ]
|
||||
then
|
||||
listToAttrs [
|
||||
(nameValuePair name (parent // zone))
|
||||
]
|
||||
|
||||
# fork -> pattern
|
||||
else zipAttrsWith (name: head) (
|
||||
mapAttrsToList (name: child: 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; }; };
|
||||
else
|
||||
zipAttrsWith (name: head) (mapAttrsToList (name: child:
|
||||
zoneConfigs' (parent // zone // { children = { }; }) name child)
|
||||
zone.children);
|
||||
|
||||
# options are ordered alphanumerically
|
||||
zoneOptionsRaw = types.submodule {
|
||||
zoneOptions = types.submodule {
|
||||
options = {
|
||||
|
||||
allowAXFRFallback = mkOption {
|
||||
@ -209,7 +201,9 @@ let
|
||||
allowNotify = mkOption {
|
||||
type = types.listOf types.str;
|
||||
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"
|
||||
];
|
||||
description = ''
|
||||
@ -231,7 +225,14 @@ let
|
||||
};
|
||||
|
||||
children = mkOption {
|
||||
default = {};
|
||||
# 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 = { };
|
||||
description = ''
|
||||
Children zones inherit all options of their parents. Attributes
|
||||
defined in a child will overwrite the ones of its parent. Only
|
||||
@ -245,7 +246,6 @@ let
|
||||
data = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "";
|
||||
description = ''
|
||||
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.
|
||||
@ -274,7 +274,8 @@ let
|
||||
};
|
||||
zsk = mkOption {
|
||||
type = keyPolicy;
|
||||
default = { keySize = 2048;
|
||||
default = {
|
||||
keySize = 2048;
|
||||
prePublish = "1w";
|
||||
postPublish = "1w";
|
||||
rollPeriod = "1mo";
|
||||
@ -283,7 +284,8 @@ let
|
||||
};
|
||||
ksk = mkOption {
|
||||
type = keyPolicy;
|
||||
default = { keySize = 4096;
|
||||
default = {
|
||||
keySize = 4096;
|
||||
prePublish = "1mo";
|
||||
postPublish = "1mo";
|
||||
rollPeriod = "0";
|
||||
@ -329,10 +331,9 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
notify = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
example = [ "10.0.0.1@3721 my_key" "::5 NOKEY" ];
|
||||
description = ''
|
||||
This primary server will notify all given secondary servers about
|
||||
@ -369,7 +370,7 @@ let
|
||||
|
||||
provideXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ];
|
||||
description = ''
|
||||
Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
|
||||
@ -379,16 +380,27 @@ let
|
||||
|
||||
requestXFR = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
example = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code>
|
||||
'';
|
||||
};
|
||||
|
||||
rrlWhitelist = mkOption {
|
||||
type = with types; listOf (enum [ "nxdomain" "error" "referral" "any" "rrsig" "wildcard" "nodata" "dnskey" "positive" "all" ]);
|
||||
default = [];
|
||||
type = with types;
|
||||
listOf (enum [
|
||||
"nxdomain"
|
||||
"error"
|
||||
"referral"
|
||||
"any"
|
||||
"rrsig"
|
||||
"wildcard"
|
||||
"nodata"
|
||||
"dnskey"
|
||||
"positive"
|
||||
"all"
|
||||
]);
|
||||
default = [ ];
|
||||
description = ''
|
||||
Whitelists the given rrl-types.
|
||||
'';
|
||||
@ -430,9 +442,10 @@ 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 != { };
|
||||
|
||||
dnssecTools = pkgs.bind.override { enablePython = true; };
|
||||
|
||||
@ -443,11 +456,14 @@ let
|
||||
${concatStrings (mapAttrsToList signZone dnssecZones)}
|
||||
'';
|
||||
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}
|
||||
${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} {
|
||||
algorithm ${policy.algorithm};
|
||||
key-size zsk ${toString policy.zsk.keySize};
|
||||
@ -462,13 +478,18 @@ let
|
||||
coverage ${policy.coverage};
|
||||
};
|
||||
'';
|
||||
in
|
||||
{
|
||||
in {
|
||||
# options are ordered alphanumerically
|
||||
options.fudo.nsd = {
|
||||
|
||||
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";
|
||||
|
||||
dnssecInterval = mkOption {
|
||||
@ -587,6 +608,7 @@ in
|
||||
reuseport = mkOption {
|
||||
type = types.bool;
|
||||
default = pkgs.stdenv.isLinux;
|
||||
defaultText = literalExpression "pkgs.stdenv.isLinux";
|
||||
description = ''
|
||||
Whether to enable SO_REUSEPORT on all used sockets. This lets multiple
|
||||
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 {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
@ -689,7 +704,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
keys = mkOption {
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
@ -714,8 +728,8 @@ in
|
||||
|
||||
};
|
||||
});
|
||||
default = {};
|
||||
example = literalExample ''
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{ "tsig.example.org" = {
|
||||
algorithm = "hmac-md5";
|
||||
keyFile = "/path/to/my/key";
|
||||
@ -727,7 +741,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
ratelimit = {
|
||||
|
||||
enable = mkEnableOption "ratelimit capabilities";
|
||||
@ -788,7 +801,6 @@ in
|
||||
|
||||
};
|
||||
|
||||
|
||||
remoteControl = {
|
||||
|
||||
enable = mkEnableOption "remote control via nsd-control";
|
||||
@ -849,8 +861,8 @@ in
|
||||
|
||||
zones = mkOption {
|
||||
type = types.attrsOf zoneOptions;
|
||||
default = {};
|
||||
example = literalExample ''
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{ "serverGroup1" = {
|
||||
provideXFR = [ "10.1.2.3 NOKEY" ];
|
||||
children = {
|
||||
@ -975,4 +987,6 @@ in
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ hrdinka ];
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ let
|
||||
|
||||
pdns-config-dir = pkgs.writeTextDir "pdns.conf" ''
|
||||
local-address=${concatStringsSep ", " cfg.listen-v4-addresses}
|
||||
local-ipv6=${concatStringsSep ", " cfg.listen-v6-addresses}
|
||||
local-port=${toString cfg.port}
|
||||
launch=
|
||||
include-dir=${runtime-dir}
|
||||
@ -305,13 +304,14 @@ in {
|
||||
psql -f ${pkgs.powerdns}/share/doc/pdns/schema.pgsql.sql
|
||||
fi
|
||||
'';
|
||||
# Wait until posgresql is available before starting
|
||||
ExecStartPre =
|
||||
pkgs.writeShellScript "ensure-postgresql-running.sh" ''
|
||||
while [ ! "$( psql -tAc "SELECT 1" )" ]; do
|
||||
${pkgs.coreutils}/bin/sleep 3
|
||||
done
|
||||
'';
|
||||
## Doesn't seem to use env vars, and so fails if remote
|
||||
## Wait until posgresql is available before starting
|
||||
# ExecStartPre =
|
||||
# pkgs.writeShellScript "ensure-postgresql-running.sh" ''
|
||||
# while [ ! "$( psql -tAc "SELECT 1" )" ]; do
|
||||
# ${pkgs.coreutils}/bin/sleep 3
|
||||
# done
|
||||
# '';
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user