(nixos/)knot-resolver: 4.3.0 -> 5.0.0

Minor incompatibilities due to moving to upstream defaults:
  - capabilities are used instead of systemd.socket units
  - the control socket moved:
    /run/kresd/control -> /run/knot-resolver/control/1
  - cacheDir moved and isn't configurable anymore
  - different user+group names, without static IDs

Thanks Mic92 for multiple ideas.
This commit is contained in:
Vladimír Čunát 2020-01-26 21:15:20 +01:00
parent 0a8fb01b80
commit ae74a0e27c
No known key found for this signature in database
GPG key ID: E747DF1F9575A3AA
3 changed files with 91 additions and 94 deletions

View file

@ -299,7 +299,7 @@ in
couchpotato = 267; couchpotato = 267;
gogs = 268; gogs = 268;
pdns-recursor = 269; pdns-recursor = 269;
kresd = 270; #kresd = 270; # switched to "knot-resolver" with dynamic ID
rpc = 271; rpc = 271;
geoip = 272; geoip = 272;
fcron = 273; fcron = 273;
@ -600,7 +600,7 @@ in
headphones = 266; headphones = 266;
couchpotato = 267; couchpotato = 267;
gogs = 268; gogs = 268;
kresd = 270; #kresd = 270; # switched to "knot-resolver" with dynamic ID
#rpc = 271; # unused #rpc = 271; # unused
#geoip = 272; # unused #geoip = 272; # unused
fcron = 273; fcron = 273;

View file

@ -3,12 +3,34 @@
with lib; with lib;
let let
cfg = config.services.kresd; cfg = config.services.kresd;
configFile = pkgs.writeText "kresd.conf" ''
${optionalString (cfg.listenDoH != []) "modules.load('http')"} # Convert systemd-style address specification to kresd config line(s).
${cfg.extraConfig}; # 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 { package = pkgs.knot-resolver.override {
extraFeatures = cfg.listenDoH != []; extraFeatures = cfg.listenDoH != [];
@ -25,6 +47,7 @@ in {
value value
) )
) )
(mkRemovedOptionModule [ "services" "kresd" "cacheDir" ] "Please use (bind-)mounting instead.")
]; ];
###### interface ###### interface
@ -35,8 +58,8 @@ in {
description = '' description = ''
Whether to enable knot-resolver domain name server. Whether to enable knot-resolver domain name server.
DNSSEC validation is turned on by default. DNSSEC validation is turned on by default.
You can run <literal>sudo nc -U /run/kresd/control</literal> You can run <literal>sudo nc -U /run/knot-resolver/control/1</literal>
and give commands interactively to kresd. and give commands interactively to kresd@1.service.
''; '';
}; };
extraConfig = mkOption { extraConfig = mkOption {
@ -46,16 +69,10 @@ in {
Extra lines to be added verbatim to the generated configuration file. 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 { listenPlain = mkOption {
type = with types; listOf str; type = with types; listOf str;
default = [ "[::1]:53" "127.0.0.1:53" ]; default = [ "[::1]:53" "127.0.0.1:53" ];
example = [ "53" ];
description = '' description = ''
What addresses and ports the server should listen on. What addresses and ports the server should listen on.
For detailed syntax see ListenStream in man systemd.socket. For detailed syntax see ListenStream in man systemd.socket.
@ -84,82 +101,35 @@ in {
###### implementation ###### implementation
config = mkIf cfg.enable { 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 = users.users.knot-resolver =
{ uid = config.ids.uids.kresd; { isSystemUser = true;
group = "kresd"; group = "knot-resolver";
description = "Knot-resolver daemon user"; description = "Knot-resolver daemon user";
}; };
users.groups.kresd.gid = config.ids.gids.kresd; users.groups.knot-resolver.gid = null;
systemd.sockets.kresd = rec { systemd.packages = [ package ]; # the units are patched inside the package a bit
wantedBy = [ "sockets.target" ];
before = wantedBy; systemd.targets.kresd = {
listenStreams = cfg.listenPlain; wantedBy = [ "multi-user.target" ];
socketConfig = { wants = [ "kres-cache-gc.service" "kresd@1.service" ];
ListenDatagram = listenStreams; };
FreeBind = true; systemd.services."kresd@".serviceConfig = {
FileDescriptorName = "dns"; 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.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec { environment.etc."tmpfiles.d/knot-resolver.conf".source =
wantedBy = [ "sockets.target" ]; "${package}/lib/tmpfiles.d/knot-resolver.conf";
before = wantedBy;
partOf = [ "kresd.socket" ];
listenStreams = cfg.listenTLS;
socketConfig = {
FileDescriptorName = "tls";
FreeBind = true;
Service = "kresd.service";
};
};
systemd.sockets.kresd-doh = mkIf (cfg.listenDoH != []) rec { # Try cleaning up the previously default location of cache file.
wantedBy = [ "sockets.target" ]; # Note that /var/cache/* should always be safe to remove.
before = wantedBy; # TODO: remove later, probably between 20.09 and 21.03
partOf = [ "kresd.socket" ]; systemd.tmpfiles.rules = [ "R /var/cache/kresd" ];
listenStreams = cfg.listenDoH;
socketConfig = {
FileDescriptorName = "doh";
FreeBind = true;
Service = "kresd.service";
};
};
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.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ];
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" ];
};
}; };
} }

View file

@ -1,4 +1,4 @@
{ stdenv, fetchurl { stdenv, fetchurl, fetchpatch
# native deps. # native deps.
, runCommand, pkgconfig, meson, ninja, makeWrapper , runCommand, pkgconfig, meson, ninja, makeWrapper
# build+runtime deps. # build+runtime deps.
@ -16,15 +16,38 @@ lua = luajitPackages;
unwrapped = stdenv.mkDerivation rec { unwrapped = stdenv.mkDerivation rec {
pname = "knot-resolver"; pname = "knot-resolver";
version = "4.3.0"; version = "5.0.0";
src = fetchurl { src = fetchurl {
url = "https://secure.nic.cz/files/knot-resolver/${pname}-${version}.tar.xz"; url = "https://secure.nic.cz/files/knot-resolver/${pname}-${version}.tar.xz";
sha256 = "0ca0f171ae2b2d76830967a5150eb0fa496b48b2a48f41b2be65d3743aaece25"; sha256 = "ca6023cd0c18b11f4a0cff0c8e882c7f3a5ad6653e9aa95acdbedafc5a53a5ed";
}; };
outputs = [ "out" "dev" ]; outputs = [ "out" "dev" ];
patches = [
(fetchpatch { # TODO: included in the next release.
name = "fix-GC-path.patch";
url = "https://gitlab.labs.nic.cz/knot/knot-resolver/commit/b723dbbe0.diff";
sha256 = "1hrwbv9vjybnwm083jxcinzw3fmwlsf1dgxrly7mhjs8d3jhqc4z";
})
];
# Path fixups for the NixOS service.
postPatch = ''
patch meson.build <<EOF
@@ -50,2 +50,2 @@
-systemd_work_dir = join_paths(prefix, get_option('localstatedir'), 'lib', 'knot-resolver')
-systemd_cache_dir = join_paths(prefix, get_option('localstatedir'), 'cache', 'knot-resolver')
+systemd_work_dir = '/var/lib/knot-resolver'
+systemd_cache_dir = '/var/cache/knot-resolver'
EOF
# ExecStart can't be overwritten in overrides.
# We need that to use wrapped executable and correct config file.
sed '/^ExecStart=/d' -i systemd/kresd@.service.in
'';
preConfigure = '' preConfigure = ''
patchShebangs scripts/ patchShebangs scripts/
''; '';
@ -45,11 +68,13 @@ unwrapped = stdenv.mkDerivation rec {
] ]
++ optional doInstallCheck "-Dunit_tests=enabled" ++ optional doInstallCheck "-Dunit_tests=enabled"
++ optional (doInstallCheck && !stdenv.isDarwin) "-Dconfig_tests=enabled" ++ optional (doInstallCheck && !stdenv.isDarwin) "-Dconfig_tests=enabled"
++ optional stdenv.isLinux "-Dsystemd_files=enabled" # used by NixOS service
#"-Dextra_tests=enabled" # not suitable as in-distro tests; many deps, too. #"-Dextra_tests=enabled" # not suitable as in-distro tests; many deps, too.
; ;
postInstall = '' postInstall = ''
rm "$out"/lib/libkres.a rm "$out"/lib/libkres.a
rm "$out"/lib/knot-resolver/upgrade-4-to-5.lua # not meaningful on NixOS
''; '';
doInstallCheck = with stdenv; hostPlatform == buildPlatform; doInstallCheck = with stdenv; hostPlatform == buildPlatform;
@ -71,20 +96,22 @@ wrapped-full = runCommand unwrapped.name
{ {
nativeBuildInputs = [ makeWrapper ]; nativeBuildInputs = [ makeWrapper ];
buildInputs = with luajitPackages; [ buildInputs = with luajitPackages; [
luasec luasocket # trust anchor bootstrap, prefill module # For http module, prefill module, trust anchor bootstrap.
luafilesystem # prefill module # It brings lots of deps; some are useful elsewhere (e.g. cqueues).
http # for http module; brings lots of deps; some are useful elsewhere http
# psl isn't in nixpkgs yet, but policy.slice_randomize_psl() seems not important.
]; ];
preferLocalBuild = true; preferLocalBuild = true;
allowSubstitutes = false; allowSubstitutes = false;
} }
'' ''
mkdir -p "$out"/{bin,share} mkdir -p "$out"/bin
makeWrapper '${unwrapped}/bin/kresd' "$out"/bin/kresd \ makeWrapper '${unwrapped}/bin/kresd' "$out"/bin/kresd \
--set LUA_PATH "$LUA_PATH" \ --set LUA_PATH "$LUA_PATH" \
--set LUA_CPATH "$LUA_CPATH" --set LUA_CPATH "$LUA_CPATH"
ln -sr '${unwrapped}/share/man' "$out"/share/ ln -sr '${unwrapped}/share' "$out"/
ln -sr '${unwrapped}/lib' "$out"/ # useful in NixOS service
ln -sr "$out"/{bin,sbin} ln -sr "$out"/{bin,sbin}
echo "Checking that 'http' module loads, i.e. lua search paths work:" echo "Checking that 'http' module loads, i.e. lua search paths work:"