From 84f6206a3986086f4b2f53fc0e2333d8a808ca13 Mon Sep 17 00:00:00 2001 From: SebastianStork Date: Sun, 1 Mar 2026 21:25:23 +0100 Subject: [PATCH] nameservers/overlay: Switch from unbound to nsd --- flake.lock | 37 +++++++++ flake.nix | 5 ++ .../nixos/services/nameservers/overlay.nix | 81 +++++++++++++------ tests/infrastructure/default.nix | 2 +- 4 files changed, 99 insertions(+), 26 deletions(-) diff --git a/flake.lock b/flake.lock index 41f1eee..32fe23c 100644 --- a/flake.lock +++ b/flake.lock @@ -59,6 +59,27 @@ "type": "github" } }, + "dns": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1768143854, + "narHash": "sha256-E5/kyPz4zAZn/lZdvqlF83jMgCWNxmqYjjWuadngCbk=", + "owner": "kirelagin", + "repo": "dns.nix", + "rev": "a97cf4156e9f044fe4bed5be531061000dfabb07", + "type": "github" + }, + "original": { + "owner": "kirelagin", + "repo": "dns.nix", + "type": "github" + } + }, "firefox-addons": { "inputs": { "nixpkgs": [ @@ -136,6 +157,21 @@ "type": "github" } }, + "flake-utils": { + "locked": { + "lastModified": 1614513358, + "narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5466c5bbece17adaab2d82fae80b46e807611bf3", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -313,6 +349,7 @@ "betterfox": "betterfox", "comin": "comin", "disko": "disko", + "dns": "dns", "firefox-addons": "firefox-addons", "flake-parts": "flake-parts", "home-manager": "home-manager", diff --git a/flake.nix b/flake.nix index 6706269..91d7d1b 100644 --- a/flake.nix +++ b/flake.nix @@ -57,6 +57,11 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + dns = { + url = "github:kirelagin/dns.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + radicale-birthday-calendar = { url = "github:iBigQ/radicale-birthday-calendar"; flake = false; diff --git a/modules/nixos/services/nameservers/overlay.nix b/modules/nixos/services/nameservers/overlay.nix index 523f7c7..65f8216 100644 --- a/modules/nixos/services/nameservers/overlay.nix +++ b/modules/nixos/services/nameservers/overlay.nix @@ -1,5 +1,6 @@ { config, + inputs, self, lib, allHosts, @@ -8,37 +9,67 @@ let cfg = config.custom.services.nameservers.overlay; netCfg = config.custom.networking; + + zoneData = { + SOA = { + nameServer = "${netCfg.overlay.fqdn}."; + adminEmail = "hostmaster@sstork.dev"; + serial = 1; + }; + NS = + allHosts + |> lib.attrValues + |> lib.filter (host: host.config.custom.services.nameservers.overlay.enable) + |> lib.map (host: "${host.config.custom.networking.overlay.fqdn}."); + + subdomains = + let + mkRecord = + { name, address }: + { + inherit name; + value.A = [ address ]; + }; + + nodeRecords = + netCfg.nodes + |> lib.map ( + node: + mkRecord { + name = node.hostName; + inherit (node.overlay) address; + } + ); + serviceRecords = + allHosts + |> lib.attrValues + |> lib.concatMap ( + host: + host.config.custom.services.caddy.virtualHosts + |> lib.attrValues + |> lib.map (vHost: vHost.domain) + |> lib.filter (domain: self.lib.isPrivateDomain domain) + |> lib.map ( + domain: + mkRecord { + name = domain |> lib.removeSuffix ".${netCfg.overlay.domain}"; + inherit (host.config.custom.networking.overlay) address; + } + ) + ); + in + (nodeRecords ++ serviceRecords) |> lib.listToAttrs; + }; in { options.custom.services.nameservers.overlay.enable = lib.mkEnableOption ""; config = lib.mkIf cfg.enable { services = { - unbound = { + nsd = { enable = true; - - settings.server = { - interface = [ netCfg.overlay.interface ]; - access-control = [ "${toString netCfg.overlay.networkCidr} allow" ]; - - local-zone = "\"${netCfg.overlay.domain}.\" static"; - local-data = - let - nodeRecords = netCfg.nodes |> lib.map (node: "\"${node.overlay.fqdn}. A ${node.overlay.address}\""); - serviceRecords = - allHosts - |> lib.attrValues - |> lib.concatMap ( - host: - host.config.custom.services.caddy.virtualHosts - |> lib.attrValues - |> lib.map (vHost: vHost.domain) - |> lib.filter (domain: self.lib.isPrivateDomain domain) - |> lib.map (domain: "\"${domain}. A ${host.config.custom.networking.overlay.address}\"") - ); - in - nodeRecords ++ serviceRecords; - }; + interfaces = [ netCfg.overlay.interface ]; + zones.${netCfg.overlay.domain}.data = zoneData |> inputs.dns.lib.toString netCfg.overlay.domain; }; nebula.networks.mesh.firewall.inbound = lib.singleton { @@ -48,7 +79,7 @@ in }; }; - systemd.services.unbound = { + systemd.services.nsd = { requires = [ netCfg.overlay.systemdUnit ]; after = [ netCfg.overlay.systemdUnit ]; }; diff --git a/tests/infrastructure/default.nix b/tests/infrastructure/default.nix index 2110107..ee077bf 100644 --- a/tests/infrastructure/default.nix +++ b/tests/infrastructure/default.nix @@ -133,7 +133,7 @@ client1.wait_for_unit("${client1NetCfg.overlay.systemdUnit}") client2.wait_for_unit("${client2NetCfg.overlay.systemdUnit}") - lighthouse.wait_for_unit("unbound.service") + lighthouse.wait_for_unit("nsd.service") lighthouse.wait_for_open_port(53, "${lighthouseNetCfg.overlay.address}") server.wait_for_unit("sshd.service")