about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorColin <colin@uninsane.org>2023-07-13 09:27:37 +0000
committerYt <happysalada@tuta.io>2023-07-16 15:24:10 +0800
commite7059632c66003bc12d81559e471519a24481585 (patch)
tree45fe0a1f1e68992b4d30427cf4f64234b49b0614 /nixos
parent90b1aa3e4d12b073dc32af59a4fdf0944df1e86c (diff)
nixos/trust-dns: init
Co-authored-by: Yt <happysalada@tuta.io>
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-2311.section.md2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/networking/trust-dns.nix177
3 files changed, 180 insertions, 0 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md
index abcfe1efee8d8..5ccaa92914e17 100644
--- a/nixos/doc/manual/release-notes/rl-2311.section.md
+++ b/nixos/doc/manual/release-notes/rl-2311.section.md
@@ -24,6 +24,8 @@
 
 - [Apache Guacamole](https://guacamole.apache.org/), a cross-platform, clientless remote desktop gateway. Available as [services.guacamole-server](#opt-services.guacamole-server.enable) and [services.guacamole-client](#opt-services.guacamole-client.enable) services.
 
+- [trust-dns](https://trust-dns.org/), a Rust based DNS server built to be safe and secure from the ground up. Available as [services.trust-dns](#opt-services.trust-dns.enable).
+
 ## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
 
 - The `boot.loader.raspberryPi` options have been marked deprecated, with intent for removal for NixOS 24.11. They had a limited use-case, and do not work like people expect. They required either very old installs ([before mid-2019](https://github.com/NixOS/nixpkgs/pull/62462)) or customized builds out of scope of the standard and generic AArch64 support. That option set never supported the Raspberry Pi 4 family of devices.
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index a20fbd69a2cb3..97abbe2191165 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -1059,6 +1059,7 @@
   ./services/networking/tox-node.nix
   ./services/networking/toxvpn.nix
   ./services/networking/trickster.nix
+  ./services/networking/trust-dns.nix
   ./services/networking/tvheadend.nix
   ./services/networking/twingate.nix
   ./services/networking/ucarp.nix
diff --git a/nixos/modules/services/networking/trust-dns.nix b/nixos/modules/services/networking/trust-dns.nix
new file mode 100644
index 0000000000000..a3b4d12479b4e
--- /dev/null
+++ b/nixos/modules/services/networking/trust-dns.nix
@@ -0,0 +1,177 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.services.trust-dns;
+  toml = pkgs.formats.toml { };
+
+  configFile = toml.generate "trust-dns.toml" (
+    lib.filterAttrsRecursive (_: v: v != null) cfg.settings
+  );
+
+  zoneType = lib.types.submodule ({ config, ... }: {
+    options = with lib; {
+      zone = mkOption {
+        type = types.str;
+        description = mdDoc ''
+          Zone name, like "example.com", "localhost", or "0.0.127.in-addr.arpa".
+        '';
+      };
+      zone_type = mkOption {
+        type = types.enum [ "Primary" "Secondary" "Hint" "Forward" ];
+        default = "Primary";
+        description = mdDoc ''
+          One of:
+          - "Primary" (the master, authority for the zone).
+          - "Secondary" (the slave, replicated from the primary).
+          - "Hint" (a cached zone with recursive resolver abilities).
+          - "Forward" (a cached zone where all requests are forwarded to another resolver).
+
+          For more details about these zone types, consult the documentation for BIND,
+          though note that trust-dns supports only a subset of BIND's zone types:
+          <https://bind9.readthedocs.io/en/v9_18_4/reference.html#type>
+        '';
+      };
+      file = mkOption {
+        type = types.either types.path types.str;
+        default = "${config.zone}.zone";
+        defaultText = literalExpression ''"''${config.zone}.zone"'';
+        description = mdDoc ''
+          Path to the .zone file.
+          If not fully-qualified, this path will be interpreted relative to the `directory` option.
+          If omitted, defaults to the value of the `zone` option suffixed with ".zone".
+        '';
+      };
+    };
+  });
+in
+{
+  meta.maintainers = with lib.maintainers; [ colinsane ];
+  options = {
+    services.trust-dns = with lib; {
+      enable = mkEnableOption (lib.mdDoc "trust-dns");
+      package = mkOption {
+        type = types.package;
+        default = pkgs.trust-dns;
+        defaultText = "pkgs.trust-dns";
+        description = mdDoc ''
+          Trust-dns package to use.
+          Only `bin/named` need be provided: the other trust-dns utilities (client and resolver) are not needed.
+        '';
+      };
+      quiet = mkOption {
+        type = types.bool;
+        default = false;
+        description = mdDoc ''
+          Log ERROR level messages only.
+          This option is mutually exclusive with the `debug` option.
+          If neither `quiet` nor `debug` are enabled, logging defaults to the INFO level.
+        '';
+      };
+      debug = mkOption {
+        type = types.bool;
+        default = false;
+        description = mdDoc ''
+          Log DEBUG, INFO, WARN and ERROR messages.
+          This option is mutually exclusive with the `debug` option.
+          If neither `quiet` nor `debug` are enabled, logging defaults to the INFO level.
+        '';
+      };
+      settings = mkOption {
+        description = lib.mdDoc ''
+          Settings for trust-dns. The options enumerated here are not exhaustive.
+          Refer to upstream documentation for all available options:
+          - [Example settings](https://github.com/bluejekyll/trust-dns/blob/main/tests/test-data/test_configs/example.toml)
+        '';
+        type = types.submodule {
+          freeformType = toml.type;
+          options = {
+            listen_addrs_ipv4 = mkOption {
+              type = types.listOf types.str;
+              default = [ "0.0.0.0" ];
+              description = mdDoc ''
+              List of ipv4 addresses on which to listen for DNS queries.
+              '';
+            };
+            listen_addrs_ipv6 = mkOption {
+              type = types.listOf types.str;
+              default = lib.optional config.networking.enableIPv6 "::0";
+              defaultText = literalExpression ''lib.optional config.networking.enableIPv6 "::0"'';
+              description = mdDoc ''
+                List of ipv6 addresses on which to listen for DNS queries.
+              '';
+            };
+            listen_port = mkOption {
+              type = types.port;
+              default = 53;
+              description = mdDoc ''
+                Port to listen on (applies to all listen addresses).
+              '';
+            };
+            directory = mkOption {
+              type = types.str;
+              default = "/var/lib/trust-dns";
+              description = mdDoc ''
+                The directory in which trust-dns should look for .zone files,
+                whenever zones aren't specified by absolute path.
+              '';
+            };
+            zones = mkOption {
+              description = mdDoc "List of zones to serve.";
+              default = {};
+              type = types.listOf (types.coercedTo types.str (zone: { inherit zone; }) zoneType);
+            };
+          };
+        };
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.services.trust-dns = {
+      description = "trust-dns Domain Name Server";
+      unitConfig.Documentation = "https://trust-dns.org/";
+      serviceConfig = {
+        ExecStart =
+        let
+          flags =  (lib.optional cfg.debug "--debug") ++ (lib.optional cfg.quiet "--quiet");
+          flagsStr = builtins.concatStringsSep " " flags;
+        in ''
+          ${cfg.package}/bin/named --config ${configFile} ${flagsStr}
+        '';
+        Type = "simple";
+        Restart = "on-failure";
+        RestartSec = "10s";
+        DynamicUser = true;
+
+        StateDirectory = "trust-dns";
+        ReadWritePaths = [ cfg.settings.directory ];
+
+        AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+        CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateMounts = true;
+        PrivateTmp = true;
+        ProtectClock = true;
+        ProtectControlGroups = true;
+        ProtectHome = true;
+        ProtectHostname = true;
+        ProtectKernelLogs = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        ProtectProc = "invisible";
+        ProtectSystem = "full";
+        RemoveIPC = true;
+        RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
+        RestrictNamespaces = true;
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ];
+      };
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+    };
+  };
+}