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

View file

@ -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.
@ -84,82 +101,35 @@ in {
###### 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;
users.groups.knot-resolver.gid = null;
systemd.sockets.kresd = rec {
wantedBy = [ "sockets.target" ];
before = wantedBy;
listenStreams = cfg.listenPlain;
socketConfig = {
ListenDatagram = listenStreams;
FreeBind = true;
FileDescriptorName = "dns";
};
systemd.packages = [ package ]; # the units are patched inside the package a bit
systemd.targets.kresd = {
wantedBy = [ "multi-user.target" ];
wants = [ "kres-cache-gc.service" "kresd@1.service" ];
};
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.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";
};
};
environment.etc."tmpfiles.d/knot-resolver.conf".source =
"${package}/lib/tmpfiles.d/knot-resolver.conf";
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.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" ];
};
# 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" ];
};
}

View file

@ -1,4 +1,4 @@
{ stdenv, fetchurl
{ stdenv, fetchurl, fetchpatch
# native deps.
, runCommand, pkgconfig, meson, ninja, makeWrapper
# build+runtime deps.
@ -16,15 +16,38 @@ lua = luajitPackages;
unwrapped = stdenv.mkDerivation rec {
pname = "knot-resolver";
version = "4.3.0";
version = "5.0.0";
src = fetchurl {
url = "https://secure.nic.cz/files/knot-resolver/${pname}-${version}.tar.xz";
sha256 = "0ca0f171ae2b2d76830967a5150eb0fa496b48b2a48f41b2be65d3743aaece25";
sha256 = "ca6023cd0c18b11f4a0cff0c8e882c7f3a5ad6653e9aa95acdbedafc5a53a5ed";
};
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 = ''
patchShebangs scripts/
'';
@ -45,11 +68,13 @@ unwrapped = stdenv.mkDerivation rec {
]
++ optional doInstallCheck "-Dunit_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.
;
postInstall = ''
rm "$out"/lib/libkres.a
rm "$out"/lib/knot-resolver/upgrade-4-to-5.lua # not meaningful on NixOS
'';
doInstallCheck = with stdenv; hostPlatform == buildPlatform;
@ -71,20 +96,22 @@ wrapped-full = runCommand unwrapped.name
{
nativeBuildInputs = [ makeWrapper ];
buildInputs = with luajitPackages; [
luasec luasocket # trust anchor bootstrap, prefill module
luafilesystem # prefill module
http # for http module; brings lots of deps; some are useful elsewhere
# For http module, prefill module, trust anchor bootstrap.
# It brings lots of deps; some are useful elsewhere (e.g. cqueues).
http
# psl isn't in nixpkgs yet, but policy.slice_randomize_psl() seems not important.
];
preferLocalBuild = true;
allowSubstitutes = false;
}
''
mkdir -p "$out"/{bin,share}
mkdir -p "$out"/bin
makeWrapper '${unwrapped}/bin/kresd' "$out"/bin/kresd \
--set LUA_PATH "$LUA_PATH" \
--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}
echo "Checking that 'http' module loads, i.e. lua search paths work:"