{ ... }: # AdGuard Home — network DNS (adblock) + DHCP. # Forwards to the local unbound recursive resolver (services/unbound.nix). # # Password note: the AdGuard NixOS module has NO secret/passwordFile hook, and # its config must be writable at runtime — so a sops secret can't be injected # cleanly. Instead `mutableSettings = true`: the `settings` below are merged # into AdGuard's state on start, and the ADMIN PASSWORD is set once via the web # setup wizard on first boot (stored only in the Pi's runtime state — never in # the repo or nix store). Trade-off: UI edits to other fields also persist. # DHCP static leases likewise live in AdGuard's leases.json (add via UI). { services.adguardhome = { enable = true; openFirewall = true; # opens the web + DNS ports mutableSettings = true; # merge settings; keep UI-set password + leases # allowDHCP is implied by settings.dhcp.enabled (grants NET_RAW/NET_BIND). settings = { http.address = "0.0.0.0:3000"; # web UI; set the admin password here on first boot dns = { bind_hosts = [ "0.0.0.0" ]; port = 53; # Recursive resolution via local unbound — no public upstream. upstream_dns = [ "127.0.0.1:5335" ]; bootstrap_dns = [ "1.1.1.1" "9.9.9.9" ]; upstream_mode = "load_balance"; }; filtering.filtering_enabled = true; filters = [ { enabled = true; id = 1; name = "AdGuard DNS filter"; url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"; } { enabled = true; id = 2; name = "AdAway Default Blocklist"; url = "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt"; } ]; # ---- DHCP (replaces pihole's) ---- dhcp = { enabled = true; interface_name = "eth0"; local_domain_name = "sol"; # clients resolve as .sol dhcpv4 = { gateway_ip = "10.0.0.1"; subnet_mask = "255.255.255.0"; range_start = "10.0.0.50"; range_end = "10.0.0.200"; lease_duration = 86400; }; }; # Static lease: add jupiter (10.0.0.20) via the UI once — persists in # leases.json. Needs jupiter's eth MAC (`ip link` on jupiter). }; }; networking.firewall.allowedUDPPorts = [ 67 ]; # DHCP (DNS/web via openFirewall) }