about summary refs log tree commit diff
path: root/modules/unbound-ng.nix
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/unbound-ng.nix185
1 files changed, 185 insertions, 0 deletions
diff --git a/modules/unbound-ng.nix b/modules/unbound-ng.nix
new file mode 100644
index 0000000..3d3c6da
--- /dev/null
+++ b/modules/unbound-ng.nix
@@ -0,0 +1,185 @@
+{
+  config,
+  inputs,
+  lib,
+  pkgs,
+  this,
+  ...
+}:
+with lib;
+let
+  cfg = config.nixfiles.modules.unbound-ng;
+in
+{
+  options.nixfiles.modules.unbound-ng = {
+    enable = mkEnableOption "Unbound";
+
+    domain = mkOption {
+      description = "Domain name sans protocol scheme.";
+      type = with types; str;
+      default = config.networking.domain;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    ark.directories = [ config.services.unbound.stateDir ];
+
+    nixfiles.modules.redis.enable = true;
+
+    services = {
+      unbound = {
+        enable = true;
+
+        package = pkgs.unbound-with-systemd.override {
+          withRedis = true;
+          withTFO = true;
+        };
+
+        checkconf = true;
+        settings = {
+          server = {
+            module-config = ''"respip validator iterator"'';
+
+            interface = with this.wireguard-ng; [
+              "127.0.0.1"
+              "::1"
+              ipv4.address
+              ipv6.address
+            ];
+
+            local-zone = concatLists (
+              mapAttrsToList (h: _: [ "\"${h}.${cfg.domain}\" redirect" ]) my.configurations
+            );
+            local-data = concatLists (
+              mapAttrsToList (
+                hostname:
+                let
+                  domain = "${hostname}.${cfg.domain}";
+                in
+                attr:
+                (optionals (hasAttr "wireguard-ng" attr) (
+                  with attr.wireguard-ng;
+                  [
+                    "\"${domain} 604800 IN A ${ipv4.address}\""
+                    "\"${domain} 604800 IN AAAA ${ipv6.address}\""
+                    "\"${domain}. A ${ipv4.address}\""
+                    "\"${domain}. AAAA ${ipv6.address}\""
+                  ]
+                  ++ (optionals (hasAttr "domains" attr) (
+                    concatMap (domain: [
+                      "\"${domain}. A ${ipv4.address}\""
+                      "\"${domain}. AAAA ${ipv6.address}\""
+                    ]) attr.domains
+                  ))
+                ))
+              ) my.configurations
+            );
+            local-data-ptr = concatLists (
+              mapAttrsToList (
+                hostname:
+                let
+                  domain = "${hostname}.${cfg.domain}";
+                in
+                attr:
+                (optionals (hasAttr "wireguard-ng" attr) (
+                  with attr.wireguard-ng;
+                  [
+                    "\"${ipv4.address} ${domain}\""
+                    "\"${ipv6.address} ${domain}\""
+                  ]
+                  ++ (optionals (hasAttr "domains" attr) (
+                    concatMap (domain: [
+                      "\"${ipv4.address} ${domain}\""
+                      "\"${ipv6.address} ${domain}\""
+                    ]) attr.domains
+                  ))
+                ))
+              ) my.configurations
+            );
+
+            private-domain = map (domain: "${domain}.") [
+              cfg.domain
+              "local"
+            ];
+            private-address = with config.nixfiles.modules.wireguard-ng; [
+              ipv4.subnet
+              ipv6.subnet
+            ];
+
+            access-control = with config.nixfiles.modules.wireguard-ng; [
+              "0.0.0.0/0 refuse"
+              "::/0 refuse"
+              "127.0.0.0/8 allow"
+              "::1/128 allow"
+              "${ipv4.subnet} allow"
+              "${ipv6.subnet} allow"
+            ];
+
+            cache-min-ttl = 0;
+
+            serve-expired = true;
+            serve-expired-reply-ttl = 0;
+
+            prefetch = true;
+            prefetch-key = true;
+
+            hide-identity = true;
+            hide-version = true;
+
+            extended-statistics = true;
+
+            log-replies = false;
+            log-tag-queryreply = false;
+            log-local-actions = false;
+
+            verbosity = 0;
+          };
+
+          forward-zone = [
+            {
+              name = ".";
+              forward-tls-upstream = true;
+              forward-addr = dns.mkDoT dns.const.quad9.ecs;
+            }
+          ];
+
+          cachedb = with config.services.redis.servers.default; {
+            backend = "redis";
+            redis-server-host = bind;
+            redis-server-port = port;
+          };
+
+          rpz = {
+            name = "hagezi.pro";
+            zonefile = "hagezi.pro";
+            url = "https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/rpz/pro.txt";
+          };
+        };
+
+        enableRootTrustAnchor = true;
+
+        localControlSocketPath = "/run/unbound/unbound.socket";
+      };
+
+      prometheus.exporters.unbound = {
+        enable = true;
+        listenAddress = mkDefault this.wireguard-ng.ipv4.address;
+        port = 9167;
+        inherit (config.services.unbound) group user;
+        unbound.host = "unix://${config.services.unbound.localControlSocketPath}";
+      };
+    };
+
+    boot.kernel.sysctl."net.ipv4.tcp_fastopen" = mkOverride 200 3;
+
+    topology = with cfg; {
+      nodes.${this.hostname}.services.unbound = {
+        name = "Unbound";
+        icon = "${inputs.homelab-svg-assets}/assets/unbound.svg";
+        details.listen.text = concatMapStringsSep "\n" (i: "${i}:53") (
+          filter (i: i != "127.0.0.1" && i != "::1") config.services.unbound.settings.server.interface
+        );
+      };
+    };
+  };
+}

Consider giving Nix/NixOS a try! <3