Merge #286596: nixos/knot: add support for XDP setups
This commit is contained in:
commit
aaca7a186f
@ -1,8 +1,36 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, utils, ... }:
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let
|
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;
|
cfg = config.services.knot;
|
||||||
|
|
||||||
yamlConfig = let
|
yamlConfig = let
|
||||||
@ -113,8 +141,7 @@ let
|
|||||||
mkConfigFile = configString: pkgs.writeTextFile {
|
mkConfigFile = configString: pkgs.writeTextFile {
|
||||||
name = "knot.conf";
|
name = "knot.conf";
|
||||||
text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" + configString;
|
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.checkConfig ''
|
||||||
checkPhase = lib.optionalString (cfg.keyFiles == []) ''
|
|
||||||
${cfg.package}/bin/knotc --config=$out conf-check
|
${cfg.package}/bin/knotc --config=$out conf-check
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -142,12 +169,45 @@ let
|
|||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
services.knot = {
|
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 {
|
extraArgs = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
description = lib.mdDoc ''
|
description = ''
|
||||||
List of additional command line parameters for knotd
|
List of additional command line parameters for knotd
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -155,7 +215,7 @@ in {
|
|||||||
keyFiles = mkOption {
|
keyFiles = mkOption {
|
||||||
type = types.listOf types.path;
|
type = types.listOf types.path;
|
||||||
default = [];
|
default = [];
|
||||||
description = lib.mdDoc ''
|
description = ''
|
||||||
A list of files containing additional configuration
|
A list of files containing additional configuration
|
||||||
to be included using the include directive. This option
|
to be included using the include directive. This option
|
||||||
allows to include configuration like TSIG keys without
|
allows to include configuration like TSIG keys without
|
||||||
@ -168,7 +228,7 @@ in {
|
|||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = {};
|
default = {};
|
||||||
description = lib.mdDoc ''
|
description = ''
|
||||||
Extra configuration as nix values.
|
Extra configuration as nix values.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -176,7 +236,7 @@ in {
|
|||||||
settingsFile = mkOption {
|
settingsFile = mkOption {
|
||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
default = null;
|
default = null;
|
||||||
description = lib.mdDoc ''
|
description = ''
|
||||||
As alternative to ``settings``, you can provide whole configuration
|
As alternative to ``settings``, you can provide whole configuration
|
||||||
directly in the almost-YAML format of Knot DNS.
|
directly in the almost-YAML format of Knot DNS.
|
||||||
You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this.
|
You might want to utilize ``pkgs.writeText "knot.conf" "longConfigString"`` for this.
|
||||||
@ -210,19 +270,35 @@ in {
|
|||||||
wants = [ "network.target" ];
|
wants = [ "network.target" ];
|
||||||
after = ["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";
|
Type = "notify";
|
||||||
ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
|
ExecStart = escapeSystemdExecArgs ([
|
||||||
ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
|
(lib.getExe cfg.package)
|
||||||
|
"--config=${configFile}"
|
||||||
|
"--socket=${socketFile}"
|
||||||
|
] ++ cfg.extraArgs);
|
||||||
|
ExecReload = escapeSystemdExecArgs [
|
||||||
|
"${knot-cli-wrappers}/bin/knotc" "reload"
|
||||||
|
];
|
||||||
User = "knot";
|
User = "knot";
|
||||||
Group = "knot";
|
Group = "knot";
|
||||||
|
|
||||||
AmbientCapabilities = [
|
AmbientCapabilities = [
|
||||||
"CAP_NET_BIND_SERVICE"
|
"CAP_NET_BIND_SERVICE"
|
||||||
];
|
] ++ xdpCapabilities;
|
||||||
CapabilityBoundingSet = [
|
CapabilityBoundingSet = [
|
||||||
"CAP_NET_BIND_SERVICE"
|
"CAP_NET_BIND_SERVICE"
|
||||||
];
|
] ++ xdpCapabilities;
|
||||||
DeviceAllow = "";
|
DeviceAllow = "";
|
||||||
DevicePolicy = "closed";
|
DevicePolicy = "closed";
|
||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
@ -247,6 +323,9 @@ in {
|
|||||||
"AF_INET"
|
"AF_INET"
|
||||||
"AF_INET6"
|
"AF_INET6"
|
||||||
"AF_UNIX"
|
"AF_UNIX"
|
||||||
|
] ++ optionals (cfg.enableXDP) [
|
||||||
|
"AF_NETLINK"
|
||||||
|
"AF_XDP"
|
||||||
];
|
];
|
||||||
RestrictNamespaces = true;
|
RestrictNamespaces = true;
|
||||||
RestrictRealtime =true;
|
RestrictRealtime =true;
|
||||||
@ -258,6 +337,8 @@ in {
|
|||||||
SystemCallFilter = [
|
SystemCallFilter = [
|
||||||
"@system-service"
|
"@system-service"
|
||||||
"~@privileged"
|
"~@privileged"
|
||||||
|
] ++ optionals (cfg.enableXDP) [
|
||||||
|
"bpf"
|
||||||
];
|
];
|
||||||
UMask = "0077";
|
UMask = "0077";
|
||||||
};
|
};
|
||||||
|
@ -114,13 +114,16 @@ in {
|
|||||||
services.knot.extraArgs = [ "-v" ];
|
services.knot.extraArgs = [ "-v" ];
|
||||||
services.knot.settings = {
|
services.knot.settings = {
|
||||||
server = {
|
server = {
|
||||||
listen = [
|
|
||||||
"0.0.0.0@53"
|
|
||||||
"::@53"
|
|
||||||
];
|
|
||||||
automatic-acl = true;
|
automatic-acl = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
xdp = {
|
||||||
|
listen = [
|
||||||
|
"eth1"
|
||||||
|
];
|
||||||
|
tcp = true;
|
||||||
|
};
|
||||||
|
|
||||||
remote.primary = {
|
remote.primary = {
|
||||||
address = "192.168.0.1@53";
|
address = "192.168.0.1@53";
|
||||||
key = "xfr_key";
|
key = "xfr_key";
|
||||||
@ -140,7 +143,7 @@ in {
|
|||||||
"sub.example.com".file = "sub.example.com.zone";
|
"sub.example.com".file = "sub.example.com.zone";
|
||||||
};
|
};
|
||||||
|
|
||||||
log.syslog.any = "info";
|
log.syslog.any = "debug";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
client = { lib, nodes, ... }: {
|
client = { lib, nodes, ... }: {
|
||||||
|
Loading…
Reference in New Issue
Block a user