Files
truenas-stacks/pihole/README.md
2026-05-15 17:00:07 +00:00

2.7 KiB

PD Pi-hole / Unbound / Keepalived Stack

Primary-node stack for the Pi-hole HA plan.

  • Repo stack path: /home/fizzlepoof/repos/truenas-stacks/pihole
  • Live PD stack path: /mnt/docker-ssd/docker/compose/pihole
  • Node role: PD primary / MASTER
  • VIP target: 10.5.1.53/24

This stack intentionally covers the PD primary plus PD-hosted sync:

  • Pi-hole
  • Unbound
  • Keepalived
  • Nebula Sync

NOMAD replica deployment is now documented and live; only the RPi4 replica remains future work.

Files

  • docker-compose.yaml — primary-node stack
  • .env.example — required variables
  • unbound.conf — shared recursive resolver config
  • keepalived.conf.template — rendered into keepalived.conf
  • bin/render_keepalived_conf.py — generates keepalived.conf from .env
  • bin/prepare_pd.sh — creates appdata dirs, downloads root hints, renders config, validates compose, optional --up

First-time setup on PD

cd /mnt/docker-ssd/docker/compose/pihole
cp .env.example .env
nano .env   # set real passwords + verify LAN_INTERFACE
/usr/bin/bash bin/prepare_pd.sh

If that validates cleanly, bring it up:

/usr/bin/bash bin/prepare_pd.sh --up

Current live topology

  • PD primary
    • service root: /mnt/docker-ssd/docker/compose/pihole
    • Pi-hole container: pihole-primary
    • Unbound container: unbound-pihole-primary
    • Keepalived container: keepalived-pihole-primary
    • Nebula Sync container: nebula-sync
    • LAN admin URL: http://10.5.1.6:8953/admin/
  • NOMAD backup
    • service root: /opt/pihole-nomad
    • Pi-hole container: pihole-nomad
    • Unbound container: unbound-pihole-nomad
    • Keepalived container: keepalived-pihole-nomad
    • LAN admin URL: http://10.5.1.16:8954/admin/
  • VIP for client DNS: 10.5.1.53
  • Shared Pi-hole admin password: stored in the local .env files; Nebula and both nodes use the same current value.

Important notes

  • KEEPALIVED_PASSWORD must be 8 chars or fewer because VRRP PASS auth is annoying and old.
  • Verify LAN_INTERFACE on PD before deployment (ip link show).
  • FTLCONF_dns_listeningMode=LOCAL is set because TrueNAS binds loopback on port 53.
  • Pi-hole NTP is explicitly disabled here because PD host chronyd already owns UDP 123.
  • Nebula Sync runs on PD and uses NEBULA_SYNC_PRIMARY / NEBULA_SYNC_REPLICAS from .env.
  • Current replica target is NOMAD at http://10.5.1.16:8954.
  • Nebula Sync is intentionally set to selective mode with gravity sync toggles enabled for groups, adlists, and domain lists so replica-specific runtime/network settings are not clobbered.
  • keepalived.conf is generated and should stay local/untracked.