# SPDX-License-Identifier: Apache-2.0
{ config, pkgs, ... }:
let
  # https://github.com/StevenBlack/hosts/issues/451
  # https://github.com/ScriptTiger/Hosts-Conversions
  # https://github.com/ScriptTiger/scripttiger.github.io
  # https://scripttiger.github.io/alts/
  adblockLocalZones = pkgs.stdenv.mkDerivation {
    name = "adblock-rpz";
    src = (pkgs.fetchFromGitHub {
        owner = "ScriptTiger";
        repo = "scripttiger.github.io";
        # nix-prefetch-github ScriptTiger scripttiger.github.io
        rev = "04402a6726f97c5f0d30436a70ac1344dccb7cf1";
        sha256 = "iSTR7j7QEr5xYtImyntDlVLbnN2ipcLcTRr4sfdx078=";
      } + "/alts/rpz/blacklist.txt");
    phases = [ "installPhase" ];
    installPhase = "install -m 444 -D $src $out";
  };
  domain = "sealight.xyz";
  certdir = config.security.acme.certs.${domain}.directory;
in {
  networking.firewall.allowedTCPPorts = [ 853 ];
  networking.firewall.allowedUDPPorts = [ 853 ];

  # for acme certs, TODO: make a proper group
  users.users.knot-resolver.extraGroups = [ "nginx" ];

  # https://github.com/NixOS/nixpkgs/issues/81109
  nixpkgs.config.packageOverrides = pkgs: rec {
    knot-resolver = pkgs.knot-resolver.override { extraFeatures = true; };
  };
  services.kresd = {
    enable = true;
    # Plain DNS only from localhost.
    # You might want to add a LAN or VPN subnet, depending on deployment.
    #listenPlain = [ "127.0.0.1:53" "[::1]:53" ];
    listenTLS = [ "853" ];
    #listenDoH = [ "" "[::]:443" ];
    instances = 1;
    # TODO: chain.pem for stapling: https://gitlab.nic.cz/knot/knot-resolver/-/issues/517
      #policy.add(
      #    policy.rpz(
      #        policy.DENY_MSG('domain blocked by your resolver operator'),
      #        '${adblockLocalZones}',
      #        false))
    extraConfig = ''
      modules.load('predict')
      modules = { 'hints > iterate' }
      policy.add(
          policy.all(
              policy.TLS_FORWARD({
                  {'45.90.30.0', hostname='87b4e9.dns2.nextdns.io'},
		  {'45.90.28.0', hostname='87b4e9.dns1.nextdns.io'}
                  })))
      policy.add(policy.suffix(policy.FORWARD({'10.0.69.4', '172.16.11.240'}), {todname('mossnet.lan')}))

      net.tls("${certdir}/fullchain.pem", "${certdir}/key.pem")

      -- refresh certs when ACME updates them
      -- TODO: could probably do with systemd and a control socket?
      -- TODO: may fail on first boot if ACME isn't fast, add a systemd dep
      local notify = require('cqueues.notify')
      local watcher = notify.opendir('${certdir}')
      watcher:add('fullchain.pem')

      worker.coroutine(function ()
        for flags, name in watcher:changes() do
          for flag in notify.flags(flags) do
            print('file watcher:', name, notify[flag])
          end
          if name == 'fullchain.pem' then
            net.tls("${certdir}/fullchain.pem", "${certdir}/key.pem")
          end
        end
      end)

      -- Below we create a tmpfs FS for the cache -- use almost all of it:
      cache.size = cache.fssize() - 1*MB
    '';
  };
}
