1 { pkgs, lib, config, info, ... }:
4 inherit (config.services) knot;
5 inherit (config.users) users groups;
6 settingsFormat = pkgs.formats.yaml { };
10 knot/autogeree.net.nix
11 knot/sourcephile.fr.nix
13 options.services.knot = {
14 # WARNING: multiple settings do not merge yet
15 # https://github.com/NixOS/nixpkgs/pull/81460#pullrequestreview-1793815097
16 settingsFreeform = lib.mkOption {
17 type = types.submodule {
18 freeformType = settingsFormat.type;
23 zones = lib.mkOption {
25 type = types.attrsOf (types.submodule ({ ... }: {
26 #config.domain = lib.mkDefault name;
29 type = types.nullOr types.lines;
36 systemd.services.knot.serviceConfig.ExecStartPre =
38 (domain: { data, ... }: ''
39 +${pkgs.coreutils}/bin/install -D -o ${users.knot.name} -g ${groups."knot".name} -m 700 \
40 ${pkgs.writeText "${domain}.zone" data} \
41 /var/lib/knot/zones/${domain}.zone
45 systemd.services.knot.postStart = lib.mkAfter ''
46 PATH="/run/current-system/sw/bin:$PATH"
47 knotc zone-freeze ${domain}.
48 while ! knotc zone-status ${domain}. +freeze | grep -q 'freeze: yes'; do sleep 1; done
49 knotc zone-flush ${domain}.
50 install -o knot -g knot -m 700 ${zone} /var/lib/knot/signed/${domain}.zone
51 knotc zone-reload ${domain}.
52 knotc zone-thaw ${domain}.
55 networking.nftables.ruleset = ''
58 meta l4proto { udp, tcp } th dport domain counter accept comment "knot: DNS"
60 set output-net-knot-ipv4 { type ipv4_addr; }
61 set output-net-knot-ipv6 { type ipv6_addr; }
63 skuid ${users.knot.name} \
64 meta l4proto { udp, tcp } th dport domain \
65 ip daddr @output-net-knot-ipv4 \
67 comment "knot: DNS notify"
68 skuid ${users.knot.name} \
69 meta l4proto { udp, tcp } th dport domain \
70 ip6 daddr @output-net-knot-ipv6 \
72 comment "knot: DNS notify"
79 # https://www.knot-dns.cz/docs/2.6/html/reference.html
82 # Listen on localhost to allow only there
83 # dynamic updates for ACME challenges.
87 dnssec-signing = false;
88 # move databases below the state directory, because they need to be writable
89 storage = "/var/lib/knot/zones";
90 # Input-only zone files
91 # https://www.knot-dns.cz/docs/2.8/html/operation.html#example-3
92 # prevents modification of the zonefiles, since the zonefiles are immutable
94 zonefile-load = "difference";
95 journal-content = "changes";
96 global-module = "mod-rrl/default";
103 journal-db = "/var/lib/knot/journal";
104 kasp-db = "/var/lib/knot/kasp";
105 timer-db = "/var/lib/knot/timer";
107 log.syslog.any = "info";
108 remote.local_resolver.address = "127.0.0.1@53";
109 remote.secondary_gandi.address = "${info.gandi.dns.secondary.axfr.ipv4}@53";
110 remote.secondary_muarf.address = "78.192.65.63@53";
111 submission.dnssec_validating_resolver = {
112 parent = "local_resolver";
115 single-type-signing = false;
117 algorithm = "RSASHA256";
120 zsk-lifetime = "30d";
121 ksk-lifetime = "365d";
122 ksk-submission = "dnssec_validating_resolver";
125 single-type-signing = false;
127 algorithm = "ED25519";
130 zsk-lifetime = "30d";
131 ksk-lifetime = "365d";
132 cds-cdnskey-publish = "always";
133 ksk-submission = "dnssec_validating_resolver";
136 address = info.gandi.dns.secondary.axfr.ipv4;
140 address = "78.192.65.63";
144 settings = knot.settingsFreeform;