{ config, lib, pkgs, ... }: let acmeChallenge = { domain , nameserver , adminEmail , serial ? 0 , refresh ? 3600 , retry ? 900 , expire ? 604800 , minimum ? 180 }: pkgs.writeText "${domain}.zone" /* bindzone */ '' $TTL 60 @ IN SOA ${lib.concatStringsSep " " [ "${nameserver}." "${lib.replaceStrings ["@"] ["."] adminEmail}." (toString serial) (toString refresh) (toString retry) (toString expire) (toString minimum) ]} @ IN NS ${nameserver}. ''; in { networking.firewall.allowedTCPPorts = [ 53 # domain for AXFR ]; networking.firewall.allowedUDPPorts = [ 53 # domain ]; krebs.systemd.services.knot.restartIfCredentialsChange = true; systemd.services.knot.serviceConfig.LoadCredential = [ "keys.conf:/var/src/secrets/knot-keys.conf" ]; services.knot = { enable = true; keyFiles = [ "/run/credentials/knot.service/keys.conf" ]; extraConfig = /* yaml */ '' server: udp-max-payload: 4096 listen: [ 127.0.0.53@2, ${ lib.concatMapStringsSep ", " (addr: "${addr}@53") ( config.krebs.build.host.nets.internet.addrs or [] ++ # This is required for hosts at OCI because the default route # provided by DHCP is using the private address. config.krebs.build.host.nets.intranet.addrs or [] ) } ] log: - target: syslog any: debug remote: - id: henet_ns1 address: 216.218.130.2 - id: hostingde_ns1 address: 134.0.30.178 - id: krebscode_ni address: ${config.krebs.hosts.ni.nets.internet.ip4.addr} key: krebs_transfer_notify_key acl: - id: acme_acl key: acme action: update - id: dane_acl key: dane action: update - id: transfer_to_henet_secondary key: henet_transfer_key address: [ 216.218.133.2, 2001:470:600::2 ] action: transfer # https://www.hosting.de/helpdesk/produkte/dns/dns-master-ips/ - id: transfer_to_hostingde_secondary address: [ 134.0.30.178, 194.126.196.2, 2a03:2900:3:1::2, 2a03:2902:3:1::2 ] action: transfer - id: transfer_to_krebscode_secondary key: krebs_transfer_notify_key action: transfer mod-rrl: - id: default rate-limit: 200 # Allow 200 resp/s for each flow slip: 2 # Every other response slips policy: - id: rsa2k algorithm: rsasha256 ksk-size: 4096 zsk-size: 2048 template: - id: default global-module: mod-rrl/default semantic-checks: on zonefile-sync: -1 zonefile-load: difference-no-serial journal-content: all zone: - domain: krebsco.de file: ${pkgs.krebs.zones."krebsco.de"} dnssec-signing: on dnssec-policy: rsa2k notify: henet_ns1 notify: hostingde_ns1 notify: krebscode_ni acl: transfer_to_henet_secondary acl: transfer_to_hostingde_secondary acl: transfer_to_krebscode_secondary acl: dane_acl - domain: _acme-challenge.krebsco.de file: ${acmeChallenge { domain = "_acme-challenge.krebsco.de"; nameserver = "ns1.krebsco.de"; adminEmail = "spam@krebsco.de"; }} acl: acme_acl - domain: r file: ${pkgs.krebs.zones.r} - domain: w file: ${pkgs.krebs.zones.w} ''; }; systemd.services."knsupdate-krebsco.de" = { serviceConfig = { Type = "oneshot"; SyslogIdentifier = "knsupdate-krebsco.de"; ExecStart = pkgs.writeDash "knsupdate-krebsco.de" /* sh */ '' set -efu mk_certificate_association_data() { ${pkgs.openssl}/bin/openssl x509 -noout -fingerprint -sha256 < "$1" | ${pkgs.coreutils}/bin/cut -d= -f2 | ${pkgs.coreutils}/bin/tr -d : } certfile=/var/lib/acme/krebsco.de/cert.pem certificate_association_data=$(mk_certificate_association_data "$certfile") keyfile=/var/src/secrets/dane.tsig script=$(${pkgs.coreutils}/bin/mktemp -t knsupdate.XXXXXXXX) trap 'rm "$script"' EXIT ( exec >"$script" echo server krebsco.de. echo zone krebsco.de. echo origin krebsco.de. echo add _25._tcp.ni 60 IN TLSA 3 0 1 $certificate_association_data echo add _443._tcp.ni 60 IN TLSA 3 0 1 $certificate_association_data echo show echo send echo answer echo quit ) ${pkgs.knot-dns}/bin/knsupdate -k "$keyfile" "$script" ''; }; }; }