Merge #286596: nixos/knot: add support for XDP setups
This commit is contained in:
commit
aaca7a186f
2 changed files with 103 additions and 19 deletions
|
@ -1,8 +1,36 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
attrNames
|
||||
concatMapStrings
|
||||
concatMapStringsSep
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
elem
|
||||
filter
|
||||
flip
|
||||
hasAttr
|
||||
hasPrefix
|
||||
isAttrs
|
||||
isBool
|
||||
isDerivation
|
||||
isList
|
||||
mapAttrsToList
|
||||
mkChangedOptionModule
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
optionals
|
||||
types
|
||||
;
|
||||
|
||||
inherit (utils)
|
||||
escapeSystemdExecArgs
|
||||
;
|
||||
|
||||
cfg = config.services.knot;
|
||||
|
||||
yamlConfig = let
|
||||
|
@ -113,8 +141,7 @@ let
|
|||
mkConfigFile = configString: pkgs.writeTextFile {
|
||||
name = "knot.conf";
|
||||
text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + configString;
|
||||
# TODO: maybe we could do some checks even when private keys complicate this?
|
||||
checkPhase = lib.optionalString (cfg.keyFiles == []) ''
|
||||
checkPhase = lib.optionalString cfg.checkConfig ''
|
||||
${cfg.package}/bin/knotc --config=$out conf-check
|
||||
'';
|
||||
};
|
||||
|
@ -142,12 +169,45 @@ let
|
|||
in {
|
||||
options = {
|
||||
services.knot = {
|
||||
enable = mkEnableOption (lib.mdDoc "Knot authoritative-only DNS server");
|
||||
enable = mkEnableOption "Knot authoritative-only DNS server";
|
||||
|
||||
enableXDP = mkOption {
|
||||
type = types.bool;
|
||||
default = lib.hasAttrByPath [ "xdp" "listen" ] cfg.settings;
|
||||
defaultText = ''
|
||||
Enabled when the `xdp.listen` setting is configured through `settings`.
|
||||
'';
|
||||
example = true;
|
||||
description = ''
|
||||
Extends the systemd unit with permissions to allow for the use of
|
||||
the eXpress Data Path (XDP).
|
||||
|
||||
::: {.note}
|
||||
Make sure to read up on functional [limitations](https://www.knot-dns.cz/docs/latest/singlehtml/index.html#mode-xdp-limitations)
|
||||
when running in XDP mode.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
checkConfig = mkOption {
|
||||
type = types.bool;
|
||||
# TODO: maybe we could do some checks even when private keys complicate this?
|
||||
# conf-check fails hard on missing IPs/devices with XDP
|
||||
default = cfg.keyFiles == [] && !cfg.enableXDP;
|
||||
defaultText = ''
|
||||
Disabled when the config uses `keyFiles` or `enableXDP`.
|
||||
'';
|
||||
example = false;
|
||||
description = ''
|
||||
Toggles the configuration test at build time. It runs in a
|
||||
sandbox, and therefore cannot be used in all scenarios.
|
||||
'';
|
||||
};
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
description = ''
|
||||
List of additional command line parameters for knotd
|
||||
'';
|
||||
};
|
||||
|
@ -155,7 +215,7 @@ in {
|
|||
keyFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
description = ''
|
||||
A list of files containing additional configuration
|
||||
to be included using the include directive. This option
|
||||
allows to include configuration like TSIG keys without
|
||||
|
@ -168,7 +228,7 @@ in {
|
|||
settings = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
description = lib.mdDoc ''
|
||||
description = ''
|
||||
Extra configuration as nix values.
|
||||
'';
|
||||
};
|
||||
|
@ -176,7 +236,7 @@ in {
|
|||
settingsFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = lib.mdDoc ''
|
||||
description = ''
|
||||
As alternative to ``settings``, you can provide whole configuration
|
||||
directly in the almost-YAML format of Knot DNS.
|
||||
You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this.
|
||||
|
@ -210,19 +270,35 @@ in {
|
|||
wants = [ "network.target" ];
|
||||
after = ["network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
serviceConfig = let
|
||||
# https://www.knot-dns.cz/docs/3.3/singlehtml/index.html#pre-requisites
|
||||
xdpCapabilities = lib.optionals (cfg.enableXDP) [
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_RAW"
|
||||
"CAP_SYS_ADMIN"
|
||||
"CAP_IPC_LOCK"
|
||||
] ++ lib.optionals (lib.versionOlder config.boot.kernelPackages.kernel.version "5.11") [
|
||||
"CAP_SYS_RESOURCE"
|
||||
];
|
||||
in {
|
||||
Type = "notify";
|
||||
ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
|
||||
ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
|
||||
ExecStart = escapeSystemdExecArgs ([
|
||||
(lib.getExe cfg.package)
|
||||
"--config=${configFile}"
|
||||
"--socket=${socketFile}"
|
||||
] ++ cfg.extraArgs);
|
||||
ExecReload = escapeSystemdExecArgs [
|
||||
"${knot-cli-wrappers}/bin/knotc" "reload"
|
||||
];
|
||||
User = "knot";
|
||||
Group = "knot";
|
||||
|
||||
AmbientCapabilities = [
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
];
|
||||
] ++ xdpCapabilities;
|
||||
CapabilityBoundingSet = [
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
];
|
||||
] ++ xdpCapabilities;
|
||||
DeviceAllow = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
|
@ -247,6 +323,9 @@ in {
|
|||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
] ++ optionals (cfg.enableXDP) [
|
||||
"AF_NETLINK"
|
||||
"AF_XDP"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime =true;
|
||||
|
@ -258,6 +337,8 @@ in {
|
|||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
] ++ optionals (cfg.enableXDP) [
|
||||
"bpf"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
|
|
|
@ -114,13 +114,16 @@ in {
|
|||
services.knot.extraArgs = [ "-v" ];
|
||||
services.knot.settings = {
|
||||
server = {
|
||||
listen = [
|
||||
"0.0.0.0@53"
|
||||
"::@53"
|
||||
];
|
||||
automatic-acl = true;
|
||||
};
|
||||
|
||||
xdp = {
|
||||
listen = [
|
||||
"eth1"
|
||||
];
|
||||
tcp = true;
|
||||
};
|
||||
|
||||
remote.primary = {
|
||||
address = "192.168.0.1@53";
|
||||
key = "xfr_key";
|
||||
|
@ -140,7 +143,7 @@ in {
|
|||
"sub.example.com".file = "sub.example.com.zone";
|
||||
};
|
||||
|
||||
log.syslog.any = "info";
|
||||
log.syslog.any = "debug";
|
||||
};
|
||||
};
|
||||
client = { lib, nodes, ... }: {
|
||||
|
|
Loading…
Reference in a new issue