mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-12-28 14:22:50 +03:00
nixos/knot: init
This commit is contained in:
parent
5b0502dc85
commit
a978d3dcd2
@ -578,6 +578,7 @@
|
||||
./services/networking/keepalived/default.nix
|
||||
./services/networking/keybase.nix
|
||||
./services/networking/kippo.nix
|
||||
./services/networking/knot.nix
|
||||
./services/networking/kresd.nix
|
||||
./services/networking/lambdabot.nix
|
||||
./services/networking/libreswan.nix
|
||||
|
95
nixos/modules/services/networking/knot.nix
Normal file
95
nixos/modules/services/networking/knot.nix
Normal file
@ -0,0 +1,95 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.knot;
|
||||
|
||||
configFile = pkgs.writeText "knot.conf" cfg.extraConfig;
|
||||
socketFile = "/run/knot/knot.sock";
|
||||
|
||||
knotConfCheck = file: pkgs.runCommand "knot-config-checked"
|
||||
{ buildInputs = [ cfg.package ]; } ''
|
||||
ln -s ${configFile} $out
|
||||
knotc --config=${configFile} conf-check
|
||||
'';
|
||||
|
||||
knot-cli-wrappers = pkgs.stdenv.mkDerivation {
|
||||
name = "knot-cli-wrappers";
|
||||
buildInputs = [ pkgs.makeWrapper ];
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin
|
||||
makeWrapper ${cfg.package}/bin/knotc "$out/bin/knotc" \
|
||||
--add-flags "--config=${configFile}" \
|
||||
--add-flags "--socket=${socketFile}"
|
||||
makeWrapper ${cfg.package}/bin/keymgr "$out/bin/keymgr" \
|
||||
--add-flags "--config=${configFile}"
|
||||
for executable in kdig khost kjournalprint knsec3hash knsupdate kzonecheck
|
||||
do
|
||||
ln -s "${cfg.package}/bin/$executable" "$out/bin/$executable"
|
||||
done
|
||||
mkdir -p "$out/share"
|
||||
ln -s '${cfg.package}/share/man' "$out/share/"
|
||||
'';
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
services.knot = {
|
||||
enable = mkEnableOption "Knot authoritative-only DNS server";
|
||||
|
||||
extraArgs = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
List of additional command line paramters for knotd
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines to be added verbatim to knot.conf
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.knot-dns;
|
||||
description = ''
|
||||
Which Knot DNS package to use
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.services.knot.enable {
|
||||
systemd.services.knot = {
|
||||
unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
|
||||
description = cfg.package.meta.description;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network.target" ];
|
||||
after = ["network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
ExecStart = "${cfg.package}/bin/knotd --config=${knotConfCheck configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
|
||||
ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
|
||||
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
|
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
|
||||
NoNewPrivileges = true;
|
||||
DynamicUser = "yes";
|
||||
RuntimeDirectory = "knot";
|
||||
StateDirectory = "knot";
|
||||
StateDirectoryMode = "0700";
|
||||
PrivateDevices = true;
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
SystemCallArchitectures = "native";
|
||||
Restart = "on-abort";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [ knot-cli-wrappers ];
|
||||
};
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ in
|
||||
kernel-latest = handleTest ./kernel-latest.nix {};
|
||||
kernel-lts = handleTest ./kernel-lts.nix {};
|
||||
keymap = handleTest ./keymap.nix {};
|
||||
knot = handleTest ./knot.nix {};
|
||||
kubernetes.dns = handleTestOn ["x86_64-linux"] ./kubernetes/dns.nix {};
|
||||
# kubernetes.e2e should eventually replace kubernetes.rbac when it works
|
||||
#kubernetes.e2e = handleTestOn ["x86_64-linux"] ./kubernetes/e2e.nix {};
|
||||
|
197
nixos/tests/knot.nix
Normal file
197
nixos/tests/knot.nix
Normal file
@ -0,0 +1,197 @@
|
||||
import ./make-test.nix ({ pkgs, lib, ...} :
|
||||
let
|
||||
common = {
|
||||
networking.firewall.enable = false;
|
||||
networking.useDHCP = false;
|
||||
};
|
||||
exampleZone = pkgs.writeTextDir "example.com.zone" ''
|
||||
@ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800
|
||||
@ NS ns1
|
||||
@ NS ns2
|
||||
ns1 A 192.168.0.1
|
||||
ns1 AAAA fd00::1
|
||||
ns2 A 192.168.0.2
|
||||
ns2 AAAA fd00::2
|
||||
www A 192.0.2.1
|
||||
www AAAA 2001:DB8::1
|
||||
sub NS ns.example.com.
|
||||
'';
|
||||
delegatedZone = pkgs.writeTextDir "sub.example.com.zone" ''
|
||||
@ SOA ns.example.com. noc.example.com. 2019031301 86400 7200 3600000 172800
|
||||
@ NS ns1.example.com.
|
||||
@ NS ns2.example.com.
|
||||
@ A 192.0.2.2
|
||||
@ AAAA 2001:DB8::2
|
||||
'';
|
||||
|
||||
knotZonesEnv = pkgs.buildEnv {
|
||||
name = "knot-zones";
|
||||
paths = [ exampleZone delegatedZone ];
|
||||
};
|
||||
in {
|
||||
name = "knot";
|
||||
|
||||
nodes = {
|
||||
master = { lib, ... }: {
|
||||
imports = [ common ];
|
||||
networking.interfaces.eth1 = {
|
||||
ipv4.addresses = lib.mkForce [
|
||||
{ address = "192.168.0.1"; prefixLength = 24; }
|
||||
];
|
||||
ipv6.addresses = lib.mkForce [
|
||||
{ address = "fd00::1"; prefixLength = 64; }
|
||||
];
|
||||
};
|
||||
services.knot.enable = true;
|
||||
services.knot.extraArgs = [ "-v" ];
|
||||
services.knot.extraConfig = ''
|
||||
server:
|
||||
listen: 0.0.0.0@53
|
||||
listen: ::@53
|
||||
|
||||
acl:
|
||||
- id: slave_acl
|
||||
address: 192.168.0.2
|
||||
action: transfer
|
||||
|
||||
remote:
|
||||
- id: slave
|
||||
address: 192.168.0.2@53
|
||||
|
||||
template:
|
||||
- id: default
|
||||
storage: ${knotZonesEnv}
|
||||
notify: [slave]
|
||||
acl: [slave_acl]
|
||||
dnssec-signing: on
|
||||
# Input-only zone files
|
||||
# https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3
|
||||
# prevents modification of the zonefiles, since the zonefiles are immutable
|
||||
zonefile-sync: -1
|
||||
zonefile-load: difference
|
||||
journal-content: changes
|
||||
# move databases below the state directory, because they need to be writable
|
||||
journal-db: /var/lib/knot/journal
|
||||
kasp-db: /var/lib/knot/kasp
|
||||
timer-db: /var/lib/knot/timer
|
||||
|
||||
zone:
|
||||
- domain: example.com
|
||||
file: example.com.zone
|
||||
|
||||
- domain: sub.example.com
|
||||
file: sub.example.com.zone
|
||||
|
||||
log:
|
||||
- target: syslog
|
||||
any: info
|
||||
'';
|
||||
};
|
||||
|
||||
slave = { lib, ... }: {
|
||||
imports = [ common ];
|
||||
networking.interfaces.eth1 = {
|
||||
ipv4.addresses = lib.mkForce [
|
||||
{ address = "192.168.0.2"; prefixLength = 24; }
|
||||
];
|
||||
ipv6.addresses = lib.mkForce [
|
||||
{ address = "fd00::2"; prefixLength = 64; }
|
||||
];
|
||||
};
|
||||
services.knot.enable = true;
|
||||
services.knot.extraArgs = [ "-v" ];
|
||||
services.knot.extraConfig = ''
|
||||
server:
|
||||
listen: 0.0.0.0@53
|
||||
listen: ::@53
|
||||
|
||||
acl:
|
||||
- id: notify_from_master
|
||||
address: 192.168.0.1
|
||||
action: notify
|
||||
|
||||
remote:
|
||||
- id: master
|
||||
address: 192.168.0.1@53
|
||||
|
||||
template:
|
||||
- id: default
|
||||
master: master
|
||||
acl: [notify_from_master]
|
||||
# zonefileless setup
|
||||
# https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2
|
||||
zonefile-sync: -1
|
||||
zonefile-load: none
|
||||
journal-content: all
|
||||
# move databases below the state directory, because they need to be writable
|
||||
journal-db: /var/lib/knot/journal
|
||||
kasp-db: /var/lib/knot/kasp
|
||||
timer-db: /var/lib/knot/timer
|
||||
|
||||
zone:
|
||||
- domain: example.com
|
||||
file: example.com.zone
|
||||
|
||||
- domain: sub.example.com
|
||||
file: sub.example.com.zone
|
||||
|
||||
log:
|
||||
- target: syslog
|
||||
any: info
|
||||
'';
|
||||
};
|
||||
client = { lib, nodes, ... }: {
|
||||
imports = [ common ];
|
||||
networking.interfaces.eth1 = {
|
||||
ipv4.addresses = [
|
||||
{ address = "192.168.0.3"; prefixLength = 24; }
|
||||
];
|
||||
ipv6.addresses = [
|
||||
{ address = "fd00::3"; prefixLength = 64; }
|
||||
];
|
||||
};
|
||||
environment.systemPackages = [ pkgs.knot-dns ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }: let
|
||||
master4 = (lib.head nodes.master.config.networking.interfaces.eth1.ipv4.addresses).address;
|
||||
master6 = (lib.head nodes.master.config.networking.interfaces.eth1.ipv6.addresses).address;
|
||||
|
||||
slave4 = (lib.head nodes.slave.config.networking.interfaces.eth1.ipv4.addresses).address;
|
||||
slave6 = (lib.head nodes.slave.config.networking.interfaces.eth1.ipv6.addresses).address;
|
||||
in ''
|
||||
startAll;
|
||||
|
||||
$client->waitForUnit("network.target");
|
||||
$master->waitForUnit("knot.service");
|
||||
$slave->waitForUnit("knot.service");
|
||||
|
||||
sub assertResponse {
|
||||
my ($knot, $query_type, $query, $expected) = @_;
|
||||
my $out = $client->succeed("khost -t $query_type $query $knot");
|
||||
$client->log("$knot replies with: $out");
|
||||
chomp $out;
|
||||
die "DNS query for $query ($query_type) against $knot gave '$out' instead of '$expected'"
|
||||
if ($out !~ $expected);
|
||||
}
|
||||
|
||||
foreach ("${master4}", "${master6}", "${slave4}", "${slave6}") {
|
||||
subtest $_, sub {
|
||||
assertResponse($_, "SOA", "example.com", qr/start of authority.*?noc\.example\.com/);
|
||||
assertResponse($_, "A", "example.com", qr/has no [^ ]+ record/);
|
||||
assertResponse($_, "AAAA", "example.com", qr/has no [^ ]+ record/);
|
||||
|
||||
assertResponse($_, "A", "www.example.com", qr/address 192.0.2.1$/);
|
||||
assertResponse($_, "AAAA", "www.example.com", qr/address 2001:db8::1$/);
|
||||
|
||||
assertResponse($_, "NS", "sub.example.com", qr/nameserver is ns\d\.example\.com.$/);
|
||||
assertResponse($_, "A", "sub.example.com", qr/address 192.0.2.2$/);
|
||||
assertResponse($_, "AAAA", "sub.example.com", qr/address 2001:db8::2$/);
|
||||
|
||||
assertResponse($_, "RRSIG", "www.example.com", qr/RR set signature is/);
|
||||
assertResponse($_, "DNSKEY", "example.com", qr/DNSSEC key is/);
|
||||
};
|
||||
}
|
||||
'';
|
||||
})
|
Loading…
Reference in New Issue
Block a user