Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257{ 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 ]; }; # DO NOT USE pkgs.writeText IN PRODUCTION. This put secrets in the nix store! tsigFile = pkgs.writeText "tsig.conf" '' key: - id: xfr_key algorithm: hmac-sha256 secret: zOYgOgnzx3TGe5J5I/0kxd7gTcxXhLYMEq3Ek3fY37s= '';in{ name = "knot"; meta = with pkgs.lib.maintainers; { maintainers = [ hexa ]; };
nodes = { primary = { lib, ... }: { imports = [ common ];
# trigger sched_setaffinity syscall virtualisation.cores = 2;
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.keyFiles = [ tsigFile ]; services.knot.settings = { server = { listen = [ "0.0.0.0@53" "::@53" ]; listen-quic = [ "0.0.0.0@853" "::@853" ]; automatic-acl = true; };
acl.secondary_acl = { address = "192.168.0.2"; key = "xfr_key"; action = "transfer"; };
remote.secondary.address = "192.168.0.2@53";
template.default = { storage = knotZonesEnv; notify = [ "secondary" ]; acl = [ "secondary_acl" ]; dnssec-signing = true; # 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"; };
zone = { "example.com".file = "example.com.zone"; "sub.example.com".file = "sub.example.com.zone"; };
log.syslog.any = "info"; }; };
secondary = { 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.keyFiles = [ tsigFile ]; services.knot.extraArgs = [ "-v" ]; services.knot.settings = { server = { automatic-acl = true; };
xdp = { listen = [ "eth1" ]; tcp = true; };
remote.primary = { address = "192.168.0.1@53"; key = "xfr_key"; };
remote.primary-quic = { address = "192.168.0.1@853"; key = "xfr_key"; quic = true; };
template.default = { # zonefileless setup # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-2 zonefile-sync = "-1"; zonefile-load = "none"; journal-content = "all"; };
zone = { "example.com" = { master = "primary"; file = "example.com.zone"; }; "sub.example.com" = { master = "primary-quic"; file = "sub.example.com.zone"; }; };
log.syslog.any = "debug"; }; }; 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 primary4 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv4.addresses).address; primary6 = (lib.head nodes.primary.config.networking.interfaces.eth1.ipv6.addresses).address;
secondary4 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv4.addresses).address; secondary6 = (lib.head nodes.secondary.config.networking.interfaces.eth1.ipv6.addresses).address; in '' import re
start_all()
client.wait_for_unit("network.target") primary.wait_for_unit("knot.service") secondary.wait_for_unit("knot.service")
for zone in ("example.com.", "sub.example.com."): secondary.wait_until_succeeds( f"knotc zone-status {zone} | grep -q 'serial: 2019031302'" )
def test(host, query_type, query, pattern): out = client.succeed(f"khost -t {query_type} {query} {host}").strip() client.log(f"{host} replied with: {out}") assert re.search(pattern, out), f'Did not match "{pattern}"'
for host in ("${primary4}", "${primary6}", "${secondary4}", "${secondary6}"): with subtest(f"Interrogate {host}"): test(host, "SOA", "example.com", r"start of authority.*noc\.example\.com\.") test(host, "A", "example.com", r"has no [^ ]+ record") test(host, "AAAA", "example.com", r"has no [^ ]+ record")
test(host, "A", "www.example.com", r"address 192.0.2.1$") test(host, "AAAA", "www.example.com", r"address 2001:db8::1$")
test(host, "NS", "sub.example.com", r"nameserver is ns\d\.example\.com.$") test(host, "A", "sub.example.com", r"address 192.0.2.2$") test(host, "AAAA", "sub.example.com", r"address 2001:db8::2$")
test(host, "RRSIG", "www.example.com", r"RR set signature is") test(host, "DNSKEY", "example.com", r"DNSSEC key is")
primary.log(primary.succeed("systemd-analyze security knot.service | grep -v '✓'")) '';}