{ config, lib, pkgs, this, ... }: with lib; let cfg = config.nixfiles.modules.unbound; in { options.nixfiles.modules.unbound = { enable = mkEnableOption "Unbound"; domain = mkOption { description = "Domain name sans protocol scheme."; type = with types; str; default = config.networking.domain; }; }; config = let adblock-conf = "${config.services.unbound.stateDir}/adblock.conf"; in mkIf cfg.enable { services = { unbound = { enable = true; package = pkgs.unbound-with-systemd.override { withRedis = true; withTFO = true; }; settings = { server = { interface = with this.wireguard; [ "127.0.0.1" "::1" ipv4.address ipv6.address ]; local-zone = concatLists (mapAttrsToList (h: _: [''"${h}.${cfg.domain}" redirect'']) my.configurations); local-data = concatLists (mapAttrsToList (hostname: let domain = "${hostname}.${cfg.domain}"; in attr: (optionals (hasAttr "wireguard" attr) (with attr.wireguard; [ ''"${domain} 604800 IN A ${ipv4.address}"'' ''"${domain} 604800 IN AAAA ${ipv6.address}"'' ''"${domain}. A ${ipv4.address}"'' ''"${domain}. AAAA ${ipv6.address}"'' ] ++ concatMap (domain: [ ''"${domain}. A ${ipv4.address}"'' ''"${domain}. AAAA ${ipv6.address}"'' ]) attr.domains))) my.configurations); local-data-ptr = concatLists (mapAttrsToList (hostname: let domain = "${hostname}.${cfg.domain}"; in attr: (optionals (hasAttr "wireguard" attr) (with attr.wireguard; [ ''"${ipv4.address} ${domain}"'' ''"${ipv6.address} ${domain}"'' ] ++ concatMap (domain: [ ''"${ipv4.address} ${domain}"'' ''"${ipv6.address} ${domain}"'' ]) attr.domains))) my.configurations); access-control = with config.nixfiles.modules.wireguard; [ "0.0.0.0/0 refuse" "::/0 refuse" "127.0.0.0/8 allow" "::1/128 allow" "${ipv4.subnet} allow" "${ipv6.subnet} allow" ]; private-domain = cfg.domain; private-address = with config.nixfiles.modules.wireguard; [ ipv4.subnet ipv6.subnet ]; domain-insecure = cfg.domain; prefetch = true; prefetch-key = true; hide-identity = true; hide-version = true; extended-statistics = true; include = ''"${adblock-conf}"''; }; forward-zone = [ { name = "."; forward-tls-upstream = true; forward-addr = let mkDnsOverTls = ips: auth: map (ip: concatStrings [ip "@" auth]) ips; in mkDnsOverTls dns.const.quad9.default "853#dns.quad9.net"; } ]; cachedb = with config.services.redis.servers.unbound; { backend = "redis"; redis-server-host = bind; redis-server-port = port; }; }; localControlSocketPath = "/run/unbound/unbound.socket"; }; redis = { servers.unbound = { enable = true; bind = "127.0.0.1"; port = 6379; }; vmOverCommit = mkForce true; }; prometheus.exporters = { unbound = { enable = true; listenAddress = mkDefault this.wireguard.ipv4.address; port = 9167; fetchType = "uds"; controlInterface = config.services.unbound.localControlSocketPath; inherit (config.services.unbound) group user; }; redis = { enable = true; listenAddress = mkDefault this.wireguard.ipv4.address; port = mkDefault 9121; extraFlags = with config.services.redis.servers.unbound; [ "--redis.addr=redis://${bind}:${toString port}" "--redis.user=${user}" ]; }; }; }; systemd = { services = { unbound.after = ["unbound-adblock-update.service"]; unbound-adblock-update = { serviceConfig = with config.services.unbound; { Type = "oneshot"; User = user; Group = group; ExecStart = let pkg = with pkgs; writeShellApplication { name = "unbound-adblock-update"; runtimeInputs = [curl package]; text = '' curl \ "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=0&mimetype=plaintext" \ >${adblock-conf} if [[ -f "${localControlSocketPath}" ]]; then unbound-control reload fi ''; }; in "${pkg}/bin/unbound-adblock-update"; }; }; }; timers.unbound-adblock-update = { requires = ["network-online.target"]; timerConfig = { OnUnitActiveSec = "1d"; Unit = "unbound-adblock-update.service"; }; wantedBy = ["timers.target"]; }; }; }; }