diff options
| author | Alejandro Soto <alejandro@34project.org> | 2025-04-19 10:48:15 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2025-04-24 14:27:38 -0600 |
| commit | 1039d1d47a53be0c814a03608e94a9d0e8f4405b (patch) | |
| tree | a6cf802896f0ad41742354499df8063d9065eb02 /sys/ns/ns.nix | |
| parent | f4ed93ff7d01e659960b9cd3dc5bc3d6d6e27d01 (diff) | |
sys/ns: implement automatic PTR zones
Diffstat (limited to 'sys/ns/ns.nix')
| -rw-r--r-- | sys/ns/ns.nix | 152 |
1 files changed, 108 insertions, 44 deletions
diff --git a/sys/ns/ns.nix b/sys/ns/ns.nix index 4c242b6..a1b1605 100644 --- a/sys/ns/ns.nix +++ b/sys/ns/ns.nix @@ -1,54 +1,118 @@ { config, lib, ... }: with lib; let - inherit (config.local.ns.server) tsigName; + inherit (config.networking) domain; inherit (config.local.nets) gate-public; + inherit (config.local.ns.server) tsigName; + + ptrNets = config.local.ns.ptr; in { options.local.ns.zones = mkOption { - type = with lib.types; attrsOf (submodule ({ config, name, ... }: - let - cfg = config.localNS; - in - { - options.localNS = { - enable = mkEnableOption "local NS settings"; - - primary = mkOption { - type = str; - default = "ns1"; - }; - }; - - config = mkIf cfg.enable { - # https://docs.gandi.net/en/domain_names/advanced_users/secondary_nameserver.html - nsdConfig = - let - providerSecondary = [ - "37.205.15.45 ${tsigName}" # ns3.vpsfree.cz - "37.205.11.85 ${tsigName}" # ns4.vpsfree.cz - "2a03:3b40:fe:2be::1 ${tsigName}" # ns3.vpsfree.cz - "2a03:3b40:101:4::1 ${tsigName}" # ns4.vpsfree.cz - ]; - in - { - notify = providerSecondary; - provideXFR = providerSecondary; + type = with lib.types; attrsOf + (submodule + ({ config, name, ... }: + let + inherit (config.soa) primary; + + cfg = config.localNS; + ptrDomain = cfg.ptrNet.v4 != null || cfg.ptrNet.v6 != null; + in + { + options.localNS = { + enable = mkEnableOption "local NS settings"; + + ptrNet = { + v4 = mkOption { + type = nullOr str; + default = null; + }; + + v6 = mkOption { + type = nullOr str; + default = null; + }; + }; }; - ns = [ - { name = "@"; host = cfg.primary; } - { name = "@"; host = "ns3.vpsfree.cz."; } - { name = "@"; host = "ns4.vpsfree.cz."; } - ]; - - a = [ - { name = cfg.primary; ipv4 = gate-public.hosts.gate.v4.address; } - ]; - - aaaa = [ - { name = cfg.primary; ipv6 = gate-public.hosts.gate.v6.address; } - ]; - }; - })); + config = mkIf cfg.enable + { + ptrName = + let + name = + if cfg.ptrNet.v6 != null + then "${cfg.ptrNet.v6}-v6" + else "${cfg.ptrNet.v4}-v4"; + in + mkIf ptrDomain name; + + # https://docs.gandi.net/en/domain_names/advanced_users/secondary_nameserver.html + nsdConfig = + let + providerSecondary = [ + "37.205.15.45 ${tsigName}" # ns3.vpsfree.cz + "37.205.11.85 ${tsigName}" # ns4.vpsfree.cz + "2a03:3b40:fe:2be::1 ${tsigName}" # ns3.vpsfree.cz + "2a03:3b40:101:4::1 ${tsigName}" # ns4.vpsfree.cz + ]; + in + { + notify = providerSecondary; + provideXFR = providerSecondary; + }; + + ns = [ + { name = "@"; host = primary; } + { name = "@"; host = "ns3.vpsfree.cz."; } + { name = "@"; host = "ns4.vpsfree.cz."; } + ]; + + a = optional (!ptrDomain) + { name = primary; ipv4 = gate-public.hosts.gate.v4.address; ptr = null; }; + + aaaa = optional (!ptrDomain) + { name = primary; ipv6 = gate-public.hosts.gate.v6.address; ptr = null; }; + + ptr = + let + ptrsToRecords = mapAttrsToList (suffix: target: { + name = suffix; + inherit target; + }); + + v4Net = cfg.ptrNet.v4; + v6Net = cfg.ptrNet.v6; + + v4Records = optionals (v4Net != null) (ptrsToRecords ptrNets.${v4Net}.v4.targets); + v6Records = optionals (v6Net != null) (ptrsToRecords ptrNets.${v6Net}.v6.targets); + in + v4Records ++ v6Records; + + soa = mkIf ptrDomain { + authorityZone = mkDefault "${domain}."; + }; + }; + })); }; + + config = + { + assertions = mapAttrsToList + (name: zone: { + assertion = zone.localNS.ptrNet.v4 != null -> zone.localNS.ptrNet.v6 == null; + message = "zone '${name}' defined as both a v4 and v6 PTR zone"; + }) + config.local.ns.zones; + + local.ns.ptr = + let + zonePtrNets = name: zone: + optionalAttrs (zone.localNS.ptrNet.v4 != null) + { + ${zone.localNS.ptrNet.v4}.v4.zone = name; + } // optionalAttrs (zone.localNS.ptrNet.v6 != null) { + ${zone.localNS.ptrNet.v6}.v6.zone = name; + }; + in + mkMerge (flatten (mapAttrsToList zonePtrNets (filterAttrs (_: zone: zone.localNS.enable) config.local.ns.zones))); + }; } |
