at 18.03-beta 3.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.kresd; 8 package = pkgs.knot-resolver; 9 10 configFile = pkgs.writeText "kresd.conf" cfg.extraConfig; 11in 12 13{ 14 meta.maintainers = [ maintainers.vcunat /* upstream developer */ ]; 15 16 ###### interface 17 options.services.kresd = { 18 enable = mkOption { 19 type = types.bool; 20 default = false; 21 description = '' 22 Whether to enable knot-resolver domain name server. 23 DNSSEC validation is turned on by default. 24 You can run <literal>sudo nc -U /run/kresd/control</literal> 25 and give commands interactively to kresd. 26 ''; 27 }; 28 extraConfig = mkOption { 29 type = types.lines; 30 default = ""; 31 description = '' 32 Extra lines to be added verbatim to the generated configuration file. 33 ''; 34 }; 35 cacheDir = mkOption { 36 type = types.path; 37 default = "/var/cache/kresd"; 38 description = '' 39 Directory for caches. They are intended to survive reboots. 40 ''; 41 }; 42 interfaces = mkOption { 43 type = with types; listOf str; 44 default = [ "::1" "127.0.0.1" ]; 45 description = '' 46 What addresses the server should listen on. (UDP+TCP 53) 47 ''; 48 }; 49 listenTLS = mkOption { 50 type = with types; listOf str; 51 default = []; 52 example = [ "198.51.100.1:853" "[2001:db8::1]:853" "853" ]; 53 description = '' 54 Addresses on which kresd should provide DNS over TLS (see RFC 7858). 55 For detailed syntax see ListenStream in man systemd.socket. 56 ''; 57 }; 58 # TODO: perhaps options for more common stuff like cache size or forwarding 59 }; 60 61 ###### implementation 62 config = mkIf cfg.enable { 63 environment.etc."kresd.conf".source = configFile; # not required 64 65 users.extraUsers = singleton 66 { name = "kresd"; 67 uid = config.ids.uids.kresd; 68 group = "kresd"; 69 description = "Knot-resolver daemon user"; 70 }; 71 users.extraGroups = singleton 72 { name = "kresd"; 73 gid = config.ids.gids.kresd; 74 }; 75 76 systemd.sockets.kresd = rec { 77 wantedBy = [ "sockets.target" ]; 78 before = wantedBy; 79 listenStreams = map 80 # Syntax depends on being IPv6 or IPv4. 81 (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53") 82 cfg.interfaces; 83 socketConfig.ListenDatagram = listenStreams; 84 socketConfig.FreeBind = true; 85 }; 86 87 systemd.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec { 88 wantedBy = [ "sockets.target" ]; 89 before = wantedBy; 90 partOf = [ "kresd.socket" ]; 91 listenStreams = cfg.listenTLS; 92 socketConfig = { 93 FileDescriptorName = "tls"; 94 FreeBind = true; 95 Service = "kresd.service"; 96 }; 97 }; 98 99 systemd.sockets.kresd-control = rec { 100 wantedBy = [ "sockets.target" ]; 101 before = wantedBy; 102 partOf = [ "kresd.socket" ]; 103 listenStreams = [ "/run/kresd/control" ]; 104 socketConfig = { 105 FileDescriptorName = "control"; 106 Service = "kresd.service"; 107 SocketMode = "0660"; # only root user/group may connect and control kresd 108 }; 109 }; 110 111 systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ]; 112 113 systemd.services.kresd = { 114 description = "Knot-resolver daemon"; 115 116 serviceConfig = { 117 User = "kresd"; 118 Type = "notify"; 119 WorkingDirectory = cfg.cacheDir; 120 Restart = "on-failure"; 121 Sockets = [ "kresd.socket" "kresd-control.socket" ] 122 ++ optional (cfg.listenTLS != []) "kresd-tls.socket"; 123 }; 124 125 # Trust anchor goes from dns-root-data by default. 126 script = '' 127 exec '${package}/bin/kresd' --config '${configFile}' --forks=1 128 ''; 129 130 requires = [ "kresd.socket" ]; 131 }; 132 }; 133}