diff --git a/flake.lock b/flake.lock index 0b4f2dd..006069c 100644 --- a/flake.lock +++ b/flake.lock @@ -136,11 +136,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1711523803, - "narHash": "sha256-UKcYiHWHQynzj6CN/vTcix4yd1eCu1uFdsuarupdCQQ=", + "lastModified": 1711703276, + "narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2726f127c15a4cc9810843b96cad73c7eb39e443", + "rev": "d8fe5e6c92d0d190646fb9f1056741a229980089", "type": "github" }, "original": { @@ -165,11 +165,11 @@ }, "secrets": { "locked": { - "lastModified": 1711747594, - "narHash": "sha256-k8Ew/EDpcLJKs285SqEldFbiKSf9rsHz/g0btv8zFM8=", + "lastModified": 1711850702, + "narHash": "sha256-rEq1KLjjhHuhKgWuzcc5SoamFAGSiSz5c4ZBPpdH6mg=", "ref": "refs/heads/master", - "rev": "110dae44d26b6d973922b804213446d1c0165486", - "revCount": 7, + "rev": "51b1080c421c646e5a9fc6be04d21fe754e4050d", + "revCount": 10, "type": "git", "url": "ssh://git@git.caspervk.net/caspervk/nixos-secrets.git" }, diff --git a/hosts/alpha/default.nix b/hosts/alpha/default.nix index 3dfdbfa..67de664 100644 --- a/hosts/alpha/default.nix +++ b/hosts/alpha/default.nix @@ -4,6 +4,7 @@ ../../modules/base ../../modules/server ./hardware.nix + ./knot-dns.nix ./network.nix ]; diff --git a/hosts/alpha/knot-dns.nix b/hosts/alpha/knot-dns.nix new file mode 100644 index 0000000..cc81fa4 --- /dev/null +++ b/hosts/alpha/knot-dns.nix @@ -0,0 +1,117 @@ +{ + config, + secrets, + ... +}: { + # Knot DNS is a high-performance authoritative-only DNS server which supports + # all key features of the modern domain name system. + # https://www.knot-dns.cz/ + # https://knot.readthedocs.io/en/master/ + services.knot = { + enable = true; + keyFiles = [ + config.age.secrets.acme-knot-key-file.path + ]; + settings = { + server = { + listen = [ + "116.203.179.206@53" + "2a01:4f8:c2c:71c0::@53" + ]; + }; + policy = [ + { + id = "default"; + # Disallow zone enumeration by using NSEC3 instead of NSEC + # https://dnsinstitute.com/documentation/dnssec-guide/ch06s02.html + nsec3 = "on"; + } + ]; + acl = [ + { + # Allow zone updates using the 'acme' TSIG key + # https://knot.readthedocs.io/en/master/configuration.html#restricting-dynamic-updates + id = "acme"; + key = "acme"; + action = "update"; + # Dynamic updates are restricted to TXT records matching the given + # list of domain names. The list is considered relative to the zone + # name unless it is a FQDN (i.e. ends in a dot). + update-type = ["TXT"]; + update-owner = "name"; + update-owner-match = "equal"; + update-owner-name = [ + "_acme-challenge" + ]; + } + ]; + template = [ + { + id = "default"; + # Enable extra zone semantic error checks + semantic-checks = "on"; + # Enable ACME ACL on all zones + acl = ["acme"]; + # Enable automatic DNSSEC signing on all zones. The KSK must be + # configured in the parent zone. Use the following command to get the + # required record(s): + # > nix shell nixpkgs#knot-dns -c sudo keymgr caspervk.net ds + # [ ] + # https://knot.readthedocs.io/en/master/configuration.html#automatic-dnssec-signing + dnssec-signing = "on"; + dnssec-policy = "default"; + # Knot overwrites the zonefiles with auto-generated DNSSEC records by + # default. Configure it to never overwrite, and store changes in the + # journal (database) instead. This also allows Knot to handle the SOA + # serial for us automatically, so we no longer need to update it. + # https://knot.readthedocs.io/en/master/operation.html#handling-zone-file-journal-changes-serials + zonefile-sync = -1; + zonefile-load = "difference-no-serial"; + journal-content = "all"; + } + ]; + zone = [ + { + domain = "caspervk.net"; + file = "${secrets}/hosts/alpha/knot/caspervk.net.zone"; + } + { + domain = "spervk.com"; + file = "${secrets}/hosts/alpha/knot/spervk.com.zone"; + } + { + domain = "sudomail.org"; + file = "${secrets}/hosts/alpha/knot/sudomail.org.zone"; + } + { + domain = "vkristensen.dk"; + file = "${secrets}/hosts/alpha/knot/vkristensen.dk.zone"; + } + ]; + }; + }; + + networking.firewall = { + allowedTCPPorts = [53]; + allowedUDPPorts = [53]; + }; + + # Persist state + environment.persistence."/nix/persist" = { + directories = [ + { + directory = "/var/lib/knot"; + user = "knot"; + group = "knot"; + mode = "0700"; + } + ]; + }; + + age.secrets.acme-knot-key-file = { + file = "${secrets}/secrets/acme-knot-key-file.age"; + mode = "400"; + owner = "knot"; + group = "knot"; + }; +}