summaryrefslogtreecommitdiff
path: root/sys/ns/ns.nix
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sys/ns/ns.nix130
1 files changed, 130 insertions, 0 deletions
diff --git a/sys/ns/ns.nix b/sys/ns/ns.nix
new file mode 100644
index 0000000..1e74502
--- /dev/null
+++ b/sys/ns/ns.nix
@@ -0,0 +1,130 @@
+{ config, lib, ... }:
+with lib; let
+ 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
+ inherit (config.soa) primary;
+
+ cfg = config.localNS;
+ ptrDomain = cfg.ptrNet.v4 != null || cfg.ptrNet.v6 != null;
+ in
+ {
+ options.localNS = {
+ enable = mkEnableOption "local NS settings";
+
+ acme = mkOption {
+ default = { };
+ type = attrsOf str;
+ };
+
+ ptrNet = {
+ v4 = mkOption {
+ type = nullOr str;
+ default = null;
+ };
+
+ v6 = mkOption {
+ type = nullOr str;
+ default = null;
+ };
+ };
+ };
+
+ 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}.";
+ };
+
+ cname = mapAttrsToList
+ (name: id: {
+ name = "_acme-challenge" + optionalString (name != "@") ".${name}";
+ target = "${id}.acme-challenge.${domain}.";
+ })
+ cfg.acme;
+ };
+ }));
+ };
+
+ 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)));
+ };
+}