{ pkgs, lib, config, ... }:
let
  inherit (lib) types;
  inherit (config.services) knot;
  inherit (config.users) users groups;
in
{
imports = [
  knot/autogeree.net.nix
  knot/sourcephile.fr.nix
];
options.services.knot = {
  zones = lib.mkOption {
    default = {};
    type = types.attrsOf (types.submodule ({name, ...}: {
      #config.domain = lib.mkDefault name;
      options = {
        conf = lib.mkOption {
          type = types.lines;
        };
        data = lib.mkOption {
          type = types.nullOr types.lines;
        };
      };
    }));
  };
};
config = {
systemd.services.knot.preStart = lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: {data, ...}:
  lib.optionalString (data != null) ''
    install -D -o ${users."knot".name} -g ${groups."knot".name} -m 700 \
     ${pkgs.writeText "${domain}.zone" data} \
     /var/lib/knot/zones/${domain}.zone
  '') knot.zones);
/*
systemd.services.knot.postStart = lib.mkAfter ''
  PATH="/run/current-system/sw/bin:$PATH"
  knotc zone-freeze ${domain}.
  while ! knotc zone-status ${domain}. +freeze | grep -q 'freeze: yes'; do sleep 1; done
  knotc zone-flush ${domain}.
  install -o knot -g knot -m 700 ${zone} /var/lib/knot/signed/${domain}.zone
  knotc zone-reload ${domain}.
  knotc zone-thaw ${domain}.
'';
*/
networking.nftables.ruleset = ''
  # for knot to notify ns6.gandi.net
  add rule inet filter fw2net ip daddr 217.70.177.40 udp dport 53 counter accept comment "DNS"
  add rule inet filter fw2net ip daddr 217.70.177.40 tcp dport 53 counter accept comment "DNS"
  # for knot to notify ns0.muarf.org
  add rule inet filter fw2net ip daddr  78.192.65.63 udp dport 53 counter accept comment "DNS"
  add rule inet filter fw2net ip daddr  78.192.65.63 tcp dport 53 counter accept comment "DNS"
  # for knot to receive queries
  add rule inet filter net2fw udp dport 53 counter accept comment "DNS"
  add rule inet filter net2fw tcp dport 53 counter accept comment "DNS"
'';
services.knot = {
  enable = true;
  extraArgs = [ "-v" ];
  # https://www.knot-dns.cz/docs/2.6/html/reference.html
  extraConfig = ''
    server :
      # Listen on localhost to allow only there
      # dynamic updates for ACME challenges.
      listen: 127.0.0.1@5353

    mod-rrl:
      - id: default
        rate-limit: 200
        slip: 2

    template:
      - id: default
        dnssec-signing: off
        # move databases below the state directory, because they need to be writable
        storage: /var/lib/knot/zones
        # 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
        global-module: mod-rrl/default

    database:
        journal-db: /var/lib/knot/journal
        kasp-db: /var/lib/knot/kasp
        timer-db: /var/lib/knot/timer

    log:
      - target: syslog
        any: info

    remote:
      - id: local_resolver
        address: 127.0.0.1@53

      - id: secondary_gandi
        address: 217.70.177.40@53

      - id: secondary_muarf
        address: 78.192.65.63@53

    submission:
      - id: dnssec_validating_resolver
        parent: local_resolver

    policy:
      - id: rsa
        single-type-signing: false
        ksk-shared: false
        algorithm: RSASHA256
        ksk-size: 4096
        zsk-size: 2048
        zsk-lifetime: 30d
        ksk-lifetime: 365d
        ksk-submission: dnssec_validating_resolver

      - id: ed25519
        single-type-signing: false
        ksk-shared: false
        algorithm: ED25519
        ksk-size: 256
        zsk-size: 256
        zsk-lifetime: 30d
        ksk-lifetime: 365d
        cds-cdnskey-publish: always
        ksk-submission: dnssec_validating_resolver

    acl:
      # DOC: https://docs.gandi.net/en/domain_names/advanced_users/secondary_nameserver.html
      - id: acl_gandi
        address: 217.70.177.40
        action: transfer

      - id: acl_muarf
        address: 78.192.65.63
        action: transfer

  '' + lib.concatStringsSep "\n" (lib.mapAttrsToList (domain: {conf, ...}: conf) knot.zones);
};
};
}