# 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 Serenity and RPi4 replicas still need their own deployment steps. ## 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 ```bash 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: ```bash /usr/bin/bash bin/prepare_pd.sh --up ``` ## 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`. - `keepalived.conf` is generated and should stay local/untracked.