{ pkgs, lib, config, inputs, hostName, hosts, ... }:
let
  domain = "sourcephile.fr";
  domainID = lib.replaceStrings [ "." ] [ "_" ] domain;
  inherit (config) networking;
  inherit (config.services) knot;
in
{
  services.knot.zones."${domain}" = {
    conf = ''
      remote:
        - id: ns_iodine
          address: 127.0.0.1@1053
      acl:
        - id: acl_localhost_acme_${domainID}
          address: 127.0.0.1
          action: update
          update-owner: name
          update-owner-match: equal
          update-owner-name: [_acme-challenge]
          update-type: [TXT]
        - id: acl_tsig_acme_${domainID}
          key: acme_${domainID}
          action: update
          update-owner: name
          update-owner-match: equal
          update-owner-name: [_acme-challenge]
          update-type: [TXT]
        - id: acl_tsig_losurdo_${domainID}
          key: losurdo_${domainID}
          action: update
          update-owner: name
          update-owner-match: equal
          update-owner-name: [losurdo, lan.losurdo]
          update-type: [A, AAAA]

      mod-dnsproxy:
        - id: proxy_iodine
          remote: ns_iodine
          fallback: off

      zone:
        - domain: ${domain}
          file: ${domain}.zone
          serial-policy: increment
          semantic-checks: on
          notify: secondary_gandi
          acl: acl_gandi
          acl: acl_localhost_acme_${domainID}
          acl: acl_tsig_acme_${domainID}
          acl: acl_tsig_losurdo_${domainID}
          dnssec-signing: on
          dnssec-policy: rsa

        - domain: i.${domain}
          module: mod-dnsproxy/proxy_iodine

        - domain: whoami4.${domain}
          module: mod-whoami
          file: "${pkgs.writeText "whoami4.zone" ''
            $TTL 1
            @ SOA ns root.${domain}. (
              0     ; SERIAL
              86400 ; REFRESH
              86400 ; RETRY
              86400 ; EXPIRE
              1 ; MINIMUM
            )
            $TTL 86400
            @ NS ns
            ns A ${hosts.mermet._module.args.ipv4}
          ''}"
    '';
    # TODO: increase the TTL once things have settled down
    data = ''
      $ORIGIN ${domain}.
      $TTL 500

      ; SOA (Start Of Authority)
      @ SOA ns root (
        ${toString inputs.self.lastModified} ; Serial number
        24h   ; Refresh
        15m   ; Retry
        1000h ; Expire (1000h)
        1d    ; Negative caching
      )

      ; NS (Name Server)
      @ NS ns
      @ NS ns6.gandi.net.
      i NS ns
      whoami4 NS ns.whoami4
      ns.whoami4 A ${hosts.mermet._module.args.ipv4}

      ; A (DNS -> IPv4)
      @            A ${hosts.mermet._module.args.ipv4}
      mermet       A ${hosts.mermet._module.args.ipv4}
      autoconfig   A ${hosts.mermet._module.args.ipv4}
      doc          A ${hosts.mermet._module.args.ipv4}
      git          A ${hosts.mermet._module.args.ipv4}
      imap         A ${hosts.mermet._module.args.ipv4}
      mail         A ${hosts.mermet._module.args.ipv4}
      mails        A ${hosts.mermet._module.args.ipv4}
      news         A ${hosts.mermet._module.args.ipv4}
      public-inbox A ${hosts.mermet._module.args.ipv4}
      ns           A ${hosts.mermet._module.args.ipv4}
      pop          A ${hosts.mermet._module.args.ipv4}
      smtp         A ${hosts.mermet._module.args.ipv4}
      submission   A ${hosts.mermet._module.args.ipv4}
      www          A ${hosts.mermet._module.args.ipv4}
      lemoutona5pattes A ${hosts.mermet._module.args.ipv4}
      croc         A ${hosts.mermet._module.args.ipv4}
      stun         A ${hosts.mermet._module.args.ipv4}
      turn         A ${hosts.mermet._module.args.ipv4}
      whoami       A ${hosts.mermet._module.args.ipv4}
      code          A ${hosts.mermet._module.args.ipv4}
      miniflux      A ${hosts.mermet._module.args.ipv4}

      ; CNAME (Canonical Name)
      openconcerto     CNAME losurdo
      xmpp             CNAME mermet
      tmp              CNAME mermet
      proxy65          CNAME mermet
      cryptpad         CNAME losurdo
      cryptpad-api     CNAME losurdo
      cryptpad-files   CNAME losurdo
      cryptpad-sandbox CNAME losurdo
      mumble           CNAME mermet
      freeciv          CNAME losurdo
      nix-serve        CNAME losurdo
      nix-extracache   CNAME losurdo
      nix-localcache   CNAME lan.losurdo
      sftp             CNAME losurdo

      ; DMARC (Domain-based Message Authentication, Reporting and Conformance)
      _dmarc 3600 IN TXT "v=DMARC1; p=none; pct=100; rua=mailto:root+dmarc+aggregate@sourcephile.fr; ruf=mailto:root+dmarc+forensic@sourcephile.fr"

      ; SPF (Sender Policy Framework)
      @ 3600 IN TXT "v=spf1 mx ip4:${hosts.mermet._module.args.ipv4} -all"

      ; SRV (SeRVice)
      _git._tcp.git             18000 IN SRV 0 0 9418 git
      _stun._udp                18000 IN SRV 0 5 3478 stun
      _xmpp-client._tcp         18000 IN SRV 0 5 5222 xmpp
      _xmpp-server._tcp         18000 IN SRV 0 5 5269 xmpp
      _xmpp-server._tcp.salons  18000 IN SRV 0 5 5269 xmpp

      ; CAA (Certificate Authority Authorization)
      ; DOC: https://blog.qualys.com/ssllabs/2017/03/13/caa-mandated-by-cabrowser-forum
      @ CAA 128 issue "letsencrypt.org"
    '';
  };
  services.knot = {
    keyFiles = [
      "/run/credentials/knot.service/${domain}.acme.conf"
      # Generated with: keymgr -t losurdo_${domainID}
      "/run/credentials/knot.service/losurdo.conf"
    ];
  };
  systemd.services.knot = {
    serviceConfig = {
      LoadCredentialEncrypted = [
        "${domain}.acme.conf:${inputs.self}/hosts/${hostName}/knot/${domain}/acme.conf.cred"
        "losurdo.conf:${inputs.self}/hosts/${hostName}/knot/${domain}/losurdo.conf.cred"
      ];
    };
  };
  networking.nftables.ruleset = ''
    table inet filter {
      # Gandi DNS
      set output-net-knot-ipv4 {
        type ipv4_addr
        elements = { 217.70.177.40 }
      }
      set output-net-knot-ipv6 {
        type ipv6_addr
        elements = { 2001:4b98:d:1::40 }
      }
    }
  '';
  /* Useless since the zone is public
    services.unbound.settings = {
    stub-zone = {
    name = domain;
    stub-addr = "127.0.0.1@5353";
    };
    };
    '';
  */
}