Various updates.
This commit is contained in:
parent
070a5e1831
commit
b9def9eba9
108
lib/fudo/kdc.nix
108
lib/fudo/kdc.nix
@ -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 ]);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
120
lib/fudo/nsd.nix
120
lib/fudo/nsd.nix
@ -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] <ip-address> <key-name | NOKEY></code>
|
Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></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 ];
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
# '';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user