summary refs log tree commit diff
path: root/nixos/modules/services/networking/kresd.nix
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2020-02-05 19:27:16 +0100
committerFrederik Rietdijk <fridh@fridh.nl>2020-02-05 19:41:25 +0100
commit419bc0a4cdc0f577062f6c439809f4bf6e3b0c63 (patch)
tree0f39c63fcddea75c562825d53a3f36bbba8b7930 /nixos/modules/services/networking/kresd.nix
parent873e6a4e65451be32e8dcd6151e1f26262ef35f2 (diff)
downloadnixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar.gz
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar.bz2
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar.lz
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar.xz
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.tar.zst
nixpkgs-419bc0a4cdc0f577062f6c439809f4bf6e3b0c63.zip
Revert "Revert "Merge master into staging-next""
In 87a19e9048773d5a363679617406ad148d36c3b8 I merged staging-next into master using the GitHub gui as intended.
In ac241fb7a570d6cf81d229ad22a8889602639160 I merged master into staging-next for the next staging cycle, however, I accidentally pushed it to master.
Thinking this may cause trouble, I reverted it in 0be87c79797a5fa384fbc356c74ed54f9f7829ea. This was however wrong, as it "removed" master.

This reverts commit 0be87c79797a5fa384fbc356c74ed54f9f7829ea.
Diffstat (limited to 'nixos/modules/services/networking/kresd.nix')
-rw-r--r--nixos/modules/services/networking/kresd.nix146
1 files changed, 63 insertions, 83 deletions
diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix
index bb941e93e15..a2f91a4200b 100644
--- a/nixos/modules/services/networking/kresd.nix
+++ b/nixos/modules/services/networking/kresd.nix
@@ -3,12 +3,34 @@
 with lib;
 
 let
-
   cfg = config.services.kresd;
-  configFile = pkgs.writeText "kresd.conf" ''
-    ${optionalString (cfg.listenDoH != []) "modules.load('http')"}
-    ${cfg.extraConfig};
-  '';
+
+  # Convert systemd-style address specification to kresd config line(s).
+  # On Nix level we don't attempt to precisely validate the address specifications.
+  mkListen = kind: addr: let
+    al_v4 = builtins.match "([0-9.]\+):([0-9]\+)" addr;
+    al_v6 = builtins.match "\\[(.\+)]:([0-9]\+)" addr;
+    al_portOnly = builtins.match "()([0-9]\+)" addr;
+    al = findFirst (a: a != null)
+      (throw "services.kresd.*: incorrect address specification '${addr}'")
+      [ al_v4 al_v6 al_portOnly ];
+    port = last al;
+    addrSpec = if al_portOnly == null then "'${head al}'" else "{'::', '127.0.0.1'}";
+    in # freebind is set for compatibility with earlier kresd services;
+       # it could be configurable, for example.
+      ''
+        net.listen(${addrSpec}, ${port}, { kind = '${kind}', freebind = true })
+      '';
+
+  configFile = pkgs.writeText "kresd.conf" (
+    optionalString (cfg.listenDoH != []) ''
+      modules.load('http')
+    ''
+    + concatMapStrings (mkListen "dns") cfg.listenPlain
+    + concatMapStrings (mkListen "tls") cfg.listenTLS
+    + concatMapStrings (mkListen "doh") cfg.listenDoH
+    + cfg.extraConfig
+  );
 
   package = pkgs.knot-resolver.override {
     extraFeatures = cfg.listenDoH != [];
@@ -25,6 +47,7 @@ in {
           value
       )
     )
+    (mkRemovedOptionModule [ "services" "kresd" "cacheDir" ] "Please use (bind-)mounting instead.")
   ];
 
   ###### interface
@@ -35,8 +58,8 @@ in {
       description = ''
         Whether to enable knot-resolver domain name server.
         DNSSEC validation is turned on by default.
-        You can run <literal>sudo nc -U /run/kresd/control</literal>
-        and give commands interactively to kresd.
+        You can run <literal>sudo nc -U /run/knot-resolver/control/1</literal>
+        and give commands interactively to kresd@1.service.
       '';
     };
     extraConfig = mkOption {
@@ -46,16 +69,10 @@ in {
         Extra lines to be added verbatim to the generated configuration file.
       '';
     };
-    cacheDir = mkOption {
-      type = types.path;
-      default = "/var/cache/kresd";
-      description = ''
-        Directory for caches.  They are intended to survive reboots.
-      '';
-    };
     listenPlain = mkOption {
       type = with types; listOf str;
       default = [ "[::1]:53" "127.0.0.1:53" ];
+      example = [ "53" ];
       description = ''
         What addresses and ports the server should listen on.
         For detailed syntax see ListenStream in man systemd.socket.
@@ -75,91 +92,54 @@ in {
       default = [];
       example = [ "198.51.100.1:443" "[2001:db8::1]:443" "443" ];
       description = ''
-        Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 7858).
+        Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 8484).
         For detailed syntax see ListenStream in man systemd.socket.
       '';
     };
+    instances = mkOption {
+      type = types.ints.unsigned;
+      default = 1;
+      description = ''
+        The number of instances to start.  They will be called kresd@{1,2,...}.service.
+        Knot Resolver uses no threads, so this is the way to scale.
+        You can dynamically start/stop them at will, so this is just system default.
+      '';
+    };
     # TODO: perhaps options for more common stuff like cache size or forwarding
   };
 
   ###### implementation
   config = mkIf cfg.enable {
-    environment.etc."kresd.conf".source = configFile; # not required
+    environment.etc."knot-resolver/kresd.conf".source = configFile; # not required
 
-    users.users.kresd =
-      { uid = config.ids.uids.kresd;
-        group = "kresd";
+    users.users.knot-resolver =
+      { isSystemUser = true;
+        group = "knot-resolver";
         description = "Knot-resolver daemon user";
       };
-    users.groups.kresd.gid = config.ids.gids.kresd;
-
-    systemd.sockets.kresd = rec {
-      wantedBy = [ "sockets.target" ];
-      before = wantedBy;
-      listenStreams = cfg.listenPlain;
-      socketConfig = {
-        ListenDatagram = listenStreams;
-        FreeBind = true;
-        FileDescriptorName = "dns";
-      };
-    };
+    users.groups.knot-resolver.gid = null;
 
-    systemd.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec {
-      wantedBy = [ "sockets.target" ];
-      before = wantedBy;
-      partOf = [ "kresd.socket" ];
-      listenStreams = cfg.listenTLS;
-      socketConfig = {
-        FileDescriptorName = "tls";
-        FreeBind = true;
-        Service = "kresd.service";
-      };
-    };
+    systemd.packages = [ package ]; # the units are patched inside the package a bit
 
-    systemd.sockets.kresd-doh = mkIf (cfg.listenDoH != []) rec {
-      wantedBy = [ "sockets.target" ];
-      before = wantedBy;
-      partOf = [ "kresd.socket" ];
-      listenStreams = cfg.listenDoH;
-      socketConfig = {
-        FileDescriptorName = "doh";
-        FreeBind = true;
-        Service = "kresd.service";
-      };
+    systemd.targets.kresd = { # configure units started by default
+      wantedBy = [ "multi-user.target" ];
+      wants = [ "kres-cache-gc.service" ]
+        ++ map (i: "kresd@${toString i}.service") (range 1 cfg.instances);
     };
-
-    systemd.sockets.kresd-control = rec {
-      wantedBy = [ "sockets.target" ];
-      before = wantedBy;
-      partOf = [ "kresd.socket" ];
-      listenStreams = [ "/run/kresd/control" ];
-      socketConfig = {
-        FileDescriptorName = "control";
-        Service = "kresd.service";
-        SocketMode = "0660"; # only root user/group may connect and control kresd
-      };
+    systemd.services."kresd@".serviceConfig = {
+      ExecStart = "${package}/bin/kresd --noninteractive "
+        + "-c ${package}/lib/knot-resolver/distro-preconfig.lua -c ${configFile}";
+      # Ensure correct ownership in case UID or GID changes.
+      CacheDirectory = "knot-resolver";
+      CacheDirectoryMode = "0750";
     };
 
-    systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ];
+    environment.etc."tmpfiles.d/knot-resolver.conf".source =
+      "${package}/lib/tmpfiles.d/knot-resolver.conf";
 
-    systemd.services.kresd = {
-      description = "Knot-resolver daemon";
-
-      serviceConfig = {
-        User = "kresd";
-        Type = "notify";
-        WorkingDirectory = cfg.cacheDir;
-        Restart = "on-failure";
-        Sockets = [ "kresd.socket" "kresd-control.socket" ]
-          ++ optional (cfg.listenTLS != []) "kresd-tls.socket";
-      };
-
-      # Trust anchor goes from dns-root-data by default.
-      script = ''
-        exec '${package}/bin/kresd' --config '${configFile}' --forks=1
-      '';
-
-      requires = [ "kresd.socket" ];
-    };
+    # Try cleaning up the previously default location of cache file.
+    # Note that /var/cache/* should always be safe to remove.
+    # TODO: remove later, probably between 20.09 and 21.03
+    systemd.tmpfiles.rules = [ "R /var/cache/kresd" ];
   };
 }