about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/services/networking/unbound.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/networking/unbound.nix')
-rw-r--r--nixpkgs/nixos/modules/services/networking/unbound.nix139
1 files changed, 139 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/networking/unbound.nix b/nixpkgs/nixos/modules/services/networking/unbound.nix
new file mode 100644
index 000000000000..1a35979ad44c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/unbound.nix
@@ -0,0 +1,139 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.unbound;
+
+  stateDir = "/var/lib/unbound";
+
+  access = concatMapStringsSep "\n  " (x: "access-control: ${x} allow") cfg.allowedAccess;
+
+  interfaces = concatMapStringsSep "\n  " (x: "interface: ${x}") cfg.interfaces;
+
+  isLocalAddress = x: substring 0 3 x == "::1" || substring 0 9 x == "127.0.0.1";
+
+  forward =
+    optionalString (any isLocalAddress cfg.forwardAddresses) ''
+      do-not-query-localhost: no
+    '' +
+    optionalString (cfg.forwardAddresses != []) ''
+      forward-zone:
+        name: .
+    '' +
+    concatMapStringsSep "\n" (x: "    forward-addr: ${x}") cfg.forwardAddresses;
+
+  rootTrustAnchorFile = "${stateDir}/root.key";
+
+  trustAnchor = optionalString cfg.enableRootTrustAnchor
+    "auto-trust-anchor-file: ${rootTrustAnchorFile}";
+
+  confFile = pkgs.writeText "unbound.conf" ''
+    server:
+      directory: "${stateDir}"
+      username: unbound
+      chroot: "${stateDir}"
+      pidfile: ""
+      ${interfaces}
+      ${access}
+      ${trustAnchor}
+    ${cfg.extraConfig}
+    ${forward}
+  '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+    services.unbound = {
+
+      enable = mkEnableOption "Unbound domain name server";
+
+      allowedAccess = mkOption {
+        default = [ "127.0.0.0/24" ];
+        type = types.listOf types.str;
+        description = "What networks are allowed to use unbound as a resolver.";
+      };
+
+      interfaces = mkOption {
+        default = [ "127.0.0.1" ] ++ optional config.networking.enableIPv6 "::1";
+        type = types.listOf types.str;
+        description = "What addresses the server should listen on.";
+      };
+
+      forwardAddresses = mkOption {
+        default = [ ];
+        type = types.listOf types.str;
+        description = "What servers to forward queries to.";
+      };
+
+      enableRootTrustAnchor = mkOption {
+        default = true;
+        type = types.bool;
+        description = "Use and update root trust anchor for DNSSEC validation.";
+      };
+
+      extraConfig = mkOption {
+        default = "";
+        type = types.lines;
+        description = ''
+          Extra unbound config. See
+          <citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8
+          </manvolnum></citerefentry>.
+        '';
+      };
+
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.unbound ];
+
+    users.users.unbound = {
+      description = "unbound daemon user";
+      isSystemUser = true;
+    };
+
+    systemd.services.unbound = {
+      description = "Unbound recursive Domain Name Server";
+      after = [ "network.target" ];
+      before = [ "nss-lookup.target" ];
+      wants = [ "nss-lookup.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        mkdir -m 0755 -p ${stateDir}/dev/
+        cp ${confFile} ${stateDir}/unbound.conf
+        ${optionalString cfg.enableRootTrustAnchor ''
+          ${pkgs.unbound}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
+          chown unbound ${stateDir} ${rootTrustAnchorFile}
+        ''}
+        touch ${stateDir}/dev/random
+        ${pkgs.utillinux}/bin/mount --bind -n /dev/urandom ${stateDir}/dev/random
+      '';
+
+      serviceConfig = {
+        ExecStart = "${pkgs.unbound}/bin/unbound -d -c ${stateDir}/unbound.conf";
+        ExecStopPost="${pkgs.utillinux}/bin/umount ${stateDir}/dev/random";
+
+        ProtectSystem = true;
+        ProtectHome = true;
+        PrivateDevices = true;
+        Restart = "always";
+        RestartSec = "5s";
+      };
+    };
+
+    # If networkmanager is enabled, ask it to interface with unbound.
+    networking.networkmanager.dns = "unbound";
+
+  };
+
+}