2021-05-06 03:21:58 +02:00
|
|
|
{ hostName, config, lib, pkgs, self, inputs, ... }:
|
2021-05-03 01:26:57 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
let
|
2021-05-06 03:21:58 +02:00
|
|
|
serial =
|
|
|
|
let
|
|
|
|
timestamp = toString self.lastModified;
|
|
|
|
datePkg = pkgs.runCommandLocal "date-${timestamp}" {} ''
|
|
|
|
date -d @${timestamp} +%Y%m%d%H > $out
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
toString (import datePkg);
|
|
|
|
|
|
|
|
generateZoneFile = { name, ns, records, dynamic }:
|
|
|
|
builtins.toFile "${name}.zone" ''
|
|
|
|
$ORIGIN ${name}.
|
|
|
|
$TTL 1h
|
|
|
|
|
2021-05-06 16:24:31 +02:00
|
|
|
@ IN SOA ${lib.dns.ns}. astro.spaceboyz.net. (
|
2021-05-06 03:21:58 +02:00
|
|
|
${serial} ; serial
|
|
|
|
1h ; refresh
|
|
|
|
1m ; retry
|
|
|
|
2h ; expire
|
|
|
|
1m ; minimum
|
|
|
|
)
|
|
|
|
${lib.concatMapStrings (ns: " IN NS ${ns}.\n") ns}
|
|
|
|
|
|
|
|
${lib.concatMapStrings ({ name, type, data }:
|
|
|
|
"${name} IN ${type} ${data}\n"
|
|
|
|
) records}
|
|
|
|
'';
|
2021-05-05 23:19:41 +02:00
|
|
|
in
|
|
|
|
{
|
|
|
|
options =
|
|
|
|
with lib;
|
2021-05-03 01:26:57 +02:00
|
|
|
let
|
2021-05-05 23:19:41 +02:00
|
|
|
recordOpts = {
|
|
|
|
name = mkOption {
|
|
|
|
description = "DNS label";
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
type = mkOption {
|
|
|
|
type = types.enum [ "A" "AAAA" "PTR" ];
|
|
|
|
};
|
|
|
|
data = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
};
|
2021-05-03 01:26:57 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
zoneOpts = {
|
|
|
|
name = mkOption {
|
|
|
|
description = "DNS FQDN w/o trailing dot";
|
|
|
|
type = types.str;
|
|
|
|
};
|
|
|
|
ns = mkOption {
|
|
|
|
type = with types; listOf str;
|
|
|
|
};
|
|
|
|
records = mkOption {
|
|
|
|
type = with types; listOf (submodule {
|
|
|
|
options = recordOpts;
|
|
|
|
});
|
|
|
|
};
|
2021-05-06 03:21:58 +02:00
|
|
|
dynamic = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
};
|
2021-05-05 23:19:41 +02:00
|
|
|
};
|
2021-05-03 01:26:57 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
in {
|
|
|
|
site.dns.localZones = mkOption {
|
|
|
|
type = with types; listOf (submodule {
|
|
|
|
options = zoneOpts;
|
|
|
|
});
|
2021-05-03 01:26:57 +02:00
|
|
|
};
|
2021-05-05 23:19:41 +02:00
|
|
|
};
|
2021-05-03 01:26:57 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
config = {
|
2021-05-06 16:24:31 +02:00
|
|
|
site.dns.localZones = lib.dns.localZones;
|
2021-05-03 01:26:57 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
services.bind = lib.mkIf config.site.hosts.${hostName}.services.dns.enable (
|
|
|
|
let
|
2021-05-06 03:21:58 +02:00
|
|
|
generateZone = zone@{ name, dynamic, ... }: {
|
2021-05-05 23:19:41 +02:00
|
|
|
inherit name;
|
|
|
|
master = true;
|
|
|
|
# allowed for zone-transfer
|
|
|
|
slaves = [
|
|
|
|
# ns.c3d2.de
|
|
|
|
"217.197.84.53" "2001:67c:1400:2240::a"
|
|
|
|
# ns.spaceboyz.net
|
|
|
|
"172.22.24.4" "2a01:4f9:4b:39ec::4"
|
|
|
|
];
|
2021-05-06 03:21:58 +02:00
|
|
|
file =
|
|
|
|
if dynamic
|
|
|
|
then "/var/db/bind/${name}.zone"
|
|
|
|
else generateZoneFile zone;
|
|
|
|
extraConfig = lib.optionalString dynamic ''
|
|
|
|
allow-update { key "dyndns"; };
|
2021-05-05 23:19:41 +02:00
|
|
|
'';
|
|
|
|
};
|
2021-05-06 03:21:58 +02:00
|
|
|
|
2021-05-05 23:19:41 +02:00
|
|
|
in {
|
|
|
|
enable = true;
|
|
|
|
zones = map generateZone config.site.dns.localZones;
|
2021-05-06 03:21:58 +02:00
|
|
|
|
|
|
|
extraConfig = ''
|
|
|
|
key "dyndns" {
|
|
|
|
algorithm hmac-sha256;
|
|
|
|
secret "${inputs.zentralwerk-network-key.lib.dyndnsKey}";
|
|
|
|
};
|
2021-05-06 15:51:58 +02:00
|
|
|
'';
|
|
|
|
extraOptions = ''
|
2021-05-06 15:46:16 +02:00
|
|
|
# allow underscores in dynamic hostnames
|
|
|
|
${lib.concatMapStringsSep "\n" (type: ''
|
|
|
|
check-names ${type} ignore;
|
|
|
|
'') [ "master" "slave" "response" ]}
|
2021-05-06 03:21:58 +02:00
|
|
|
'';
|
2021-05-05 23:19:41 +02:00
|
|
|
});
|
|
|
|
|
2021-05-06 15:46:37 +02:00
|
|
|
systemd.services.create-dynamic-zones = {
|
|
|
|
description = "Creates dynamic zone files";
|
2021-05-06 03:21:58 +02:00
|
|
|
requiredBy = [ "bind.service" ];
|
|
|
|
before = [ "bind.service" ];
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
script = ''
|
|
|
|
mkdir -p /var/db/bind
|
|
|
|
|
|
|
|
${lib.concatMapStringsSep "\n" (zone@{ name, ... }: ''
|
|
|
|
[ -e /var/db/bind/${name}.zone ] || \
|
|
|
|
cp ${generateZoneFile zone} /var/db/bind/${name}.zone
|
|
|
|
chown -R named /var/db/bind
|
|
|
|
chmod -R u+rwX /var/db/bind
|
|
|
|
'') (
|
|
|
|
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
|
|
|
|
)}
|
|
|
|
'';
|
|
|
|
};
|
2021-05-06 15:46:37 +02:00
|
|
|
systemd.services.update-dynamic-zones = {
|
|
|
|
description = "Creates initial records in dynamic zone files";
|
|
|
|
requiredBy = [ "bind.service" ];
|
|
|
|
after = [ "bind.service" ];
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
path = [ pkgs.dnsutils ];
|
|
|
|
script = ''
|
|
|
|
${lib.concatMapStrings (zone: ''
|
|
|
|
nsupdate -y "hmac-sha256:dyndns:${inputs.zentralwerk-network-key.lib.dyndnsKey}" <<EOF
|
|
|
|
server localhost
|
|
|
|
|
|
|
|
${lib.concatMapStringsSep "\n" ({ name, type, data }: ''
|
|
|
|
delete ${name}.${zone.name}. IN ${type}
|
|
|
|
add ${name}.${zone.name}. 3600 IN ${type} ${data}
|
|
|
|
'') zone.records}
|
|
|
|
|
|
|
|
send
|
|
|
|
EOF
|
|
|
|
'') (
|
|
|
|
builtins.filter ({ dynamic, ... }: dynamic) config.site.dns.localZones
|
|
|
|
)}
|
|
|
|
'';
|
|
|
|
};
|
2021-05-05 23:19:41 +02:00
|
|
|
};
|
2021-05-03 01:26:57 +02:00
|
|
|
}
|