- services/pihole.nix: official pihole/pihole:2026.07.2 via podman, host net, caps NET_ADMIN/NET_RAW/SYS_NICE/CHOWN; FTLCONF_* env config (upstream unbound, DHCP 50-200, static lease jupiter, .sol domain, local records) - unbound: resolveLocalQueries=false (was hijacking resolv.conf to :53 -> boot DNS deadlock; the real root cause of the earlier failures too) - password via sops FTLCONF env file; /var/lib/pihole created via tmpfiles - VM-verified: mercury.sol/jupiter.sol/external all resolve, 0 restarts
39 lines
1.3 KiB
Nix
39 lines
1.3 KiB
Nix
{ ... }:
|
|
|
|
# Local recursive DNS resolver (privacy + DNSSEC). Your adblock DNS
|
|
# (pihole/AdGuard) forwards to this instead of a public upstream.
|
|
# Listens on 127.0.0.1:5335 — point the adblock engine's upstream there:
|
|
# AdGuard: dns.upstream_dns = [ "127.0.0.1:5335" ];
|
|
# pihole: upstream = "127.0.0.1#5335";
|
|
{
|
|
services.unbound = {
|
|
enable = true;
|
|
# Do NOT point the host's resolv.conf at unbound: it listens on :5335, not
|
|
# :53, so that would leave the host with no working resolver until pihole
|
|
# binds :53 (a boot-time deadlock — can't pull images / build lists). The
|
|
# host resolves via networking.nameservers (upstream) instead; pihole
|
|
# forwards to unbound explicitly at 127.0.0.1#5335.
|
|
resolveLocalQueries = false;
|
|
# NixOS manages the DNSSEC root trust anchor (unbound-anchor).
|
|
settings.server = {
|
|
interface = [ "127.0.0.1" ];
|
|
port = 5335;
|
|
access-control = [ "127.0.0.0/8 allow" ];
|
|
|
|
do-ip6 = "no"; # flip to yes if you resolve over IPv6
|
|
prefer-ip6 = "no";
|
|
|
|
# Privacy / hardening (standard pi-hole+unbound guide).
|
|
hide-identity = true;
|
|
hide-version = true;
|
|
harden-glue = true;
|
|
harden-dnssec-stripped = true;
|
|
use-caps-for-id = false;
|
|
qname-minimisation = true;
|
|
|
|
edns-buffer-size = 1232;
|
|
prefetch = true;
|
|
};
|
|
};
|
|
}
|