summaryrefslogtreecommitdiff
path: root/modules/nixos/unbound.nix
diff options
context:
space:
mode:
authorAzat Bahawi <azat@bahawi.net>2022-12-17 16:39:09 +0300
committerAzat Bahawi <azat@bahawi.net>2022-12-17 16:39:09 +0300
commit8f137c28230623259a964484adcf31fe00756594 (patch)
tree82bce6a13fda125087cf6d9dc80aa91d9230d6c4 /modules/nixos/unbound.nix
parent3229e56e0d3620ddc735edcfbbefb167efa3b23f (diff)
2022-12-17
Diffstat (limited to 'modules/nixos/unbound.nix')
-rw-r--r--modules/nixos/unbound.nix197
1 files changed, 197 insertions, 0 deletions
diff --git a/modules/nixos/unbound.nix b/modules/nixos/unbound.nix
new file mode 100644
index 0000000..8c40291
--- /dev/null
+++ b/modules/nixos/unbound.nix
@@ -0,0 +1,197 @@
+{
+ 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"];
+ };
+ };
+ };
+}