- Server overview (README.md) with services, storage, and network summary - Storage layout with disk/fstab/mount details (storage.md) - Service docs: Samba, NFS, Squid, Pi-hole (with DHCP/split-DNS notes) - Let's Encrypt cert via acme.sh + GoDaddy DNS-01 (ssl/) - nginx SSL reverse proxy config and virtual host guide (nginx/) - Pi-hole moved to port 8081; split DNS overrides documented for both Pi-hole and pfSense Unbound to avoid hairpin NAT issues Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
157 lines
5.2 KiB
Markdown
157 lines
5.2 KiB
Markdown
# Pi-hole — zet.home.arpa
|
|
|
|
Network-wide DNS ad blocker and DHCP server. Runs as a Docker container.
|
|
|
|
## Overview
|
|
|
|
| Field | Value |
|
|
|-------|-------|
|
|
| **Image** | `pihole/pihole:latest` |
|
|
| **Container name** | `pihole` |
|
|
| **Compose file** | `/home/kenjim/docker-pi-hole/docker-compose.yml` |
|
|
| **Config directory** | `/home/kenjim/docker-pi-hole/` |
|
|
| **Restart policy** | `always` |
|
|
| **Timezone** | `America/Chicago` |
|
|
|
|
## Versions (as of 2026-06-19)
|
|
|
|
| Component | Running | Latest |
|
|
|-----------|---------|--------|
|
|
| Core | v6.1.4 | v6.4.2 |
|
|
| Web | v6.2.1 | v6.5.1 |
|
|
| FTL | v6.2.3 | v6.6.2 |
|
|
|
|
**Updates are available** — see [Upgrading](#upgrading) below.
|
|
|
|
## Ports
|
|
|
|
| Port | Protocol | Purpose | Accessible from |
|
|
|------|----------|---------|-----------------|
|
|
| 53 | TCP + UDP | DNS | LAN (pfSense points clients here) |
|
|
| 67 | UDP | DHCP | LAN only (broadcast, not routable to WAN) |
|
|
| 8081 | TCP | Web admin UI | LAN only (pfSense does not forward this port) |
|
|
|
|
**Admin UI**: `http://172.27.0.35:8081/admin`
|
|
|
|
## Role: DHCP Server for Untrusted Devices
|
|
|
|
Pi-hole acts as the DHCP server for untrusted LAN devices — Alexa/Echo devices, IoT, and children's machines. By serving DHCP, Pi-hole automatically assigns itself as the DNS server for those clients, ensuring DNS-level ad/content blocking applies without any per-device configuration.
|
|
|
|
pfSense should have its own DHCP server **disabled** (or scoped to a different subnet/VLAN) for any segment where Pi-hole is authoritative for DHCP, to avoid conflicts.
|
|
|
|
### DHCP + Docker caveat
|
|
|
|
Pi-hole's own docs recommend `network_mode: host` for reliable DHCP from Docker (broadcast packets don't traverse Docker NAT cleanly). The current setup uses port mappings + `NET_ADMIN` capability instead, which works in practice. If DHCP stops responding after a container restart or image upgrade, switching to host networking is the fix:
|
|
|
|
```yaml
|
|
# Alternative compose config if DHCP becomes unreliable:
|
|
services:
|
|
pihole:
|
|
network_mode: host # replaces all port: mappings
|
|
# remove the ports: section entirely
|
|
# admin UI returns to port 80, but WAN can't reach it
|
|
# since pfSense won't forward port 80 to this host
|
|
```
|
|
|
|
## Volume Mounts
|
|
|
|
| Host path | Container path | Contents |
|
|
|-----------|----------------|----------|
|
|
| `./etc-pihole` | `/etc/pihole` | Pi-hole config, gravity DB, DHCP leases |
|
|
| `./etc-dnsmasq.d` | `/etc/dnsmasq.d` | Custom DNS/DHCP overrides |
|
|
|
|
Both paths are relative to `/home/kenjim/docker-pi-hole/`.
|
|
|
|
## docker-compose.yml
|
|
|
|
```yaml
|
|
version: "3"
|
|
|
|
services:
|
|
pihole:
|
|
container_name: pihole
|
|
image: pihole/pihole:latest
|
|
ports:
|
|
- "53:53/tcp"
|
|
- "53:53/udp"
|
|
- "67:67/udp"
|
|
- "8081:80/tcp"
|
|
environment:
|
|
TZ: 'America/Chicago'
|
|
FTLCONF_MAXCONCURRENTQUERIES: 300
|
|
volumes:
|
|
- './etc-pihole:/etc/pihole'
|
|
- './etc-dnsmasq.d:/etc/dnsmasq.d'
|
|
cap_add:
|
|
- NET_ADMIN
|
|
restart: always
|
|
```
|
|
|
|
## Service Management
|
|
|
|
```bash
|
|
cd ~/docker-pi-hole
|
|
|
|
docker compose up -d # start
|
|
docker compose down # stop
|
|
docker compose pull && docker compose up -d # update image
|
|
docker compose logs -f pihole # follow logs
|
|
|
|
# Run pihole commands inside container
|
|
docker exec pihole pihole status
|
|
docker exec pihole pihole -g # update gravity (blocklists)
|
|
docker exec pihole pihole version
|
|
```
|
|
|
|
## Upgrading
|
|
|
|
Pi-hole updates are released as new Docker image versions:
|
|
|
|
```bash
|
|
cd ~/docker-pi-hole
|
|
docker compose pull # pull latest image
|
|
docker compose up -d # recreate container
|
|
docker exec pihole pihole version # verify new version
|
|
```
|
|
|
|
The volumes (`etc-pihole/`, `etc-dnsmasq.d/`) persist config across upgrades.
|
|
|
|
## Migration Notes
|
|
|
|
To move Pi-hole to a new server:
|
|
|
|
1. Stop the container: `docker compose down`
|
|
2. Copy the entire `/home/kenjim/docker-pi-hole/` directory to the new host
|
|
3. Install Docker on the new host
|
|
4. Run `docker compose up -d` from the copied directory
|
|
5. Update pfSense DNS server setting to point to the new host IP
|
|
|
|
Key data to preserve:
|
|
- `etc-pihole/gravity.db` — blocklists
|
|
- `etc-pihole/dhcp.leases` — DHCP lease table
|
|
- `etc-pihole/pihole.toml` — main config (v6+ format)
|
|
- `etc-pihole/local.list` — local DNS overrides
|
|
- `etc-dnsmasq.d/` — custom dnsmasq config
|
|
|
|
## Network Integration
|
|
|
|
Pi-hole is one of two DNS resolvers on the LAN — some devices use Pi-hole (`172.27.0.35:53`), others use pfSense's built-in Unbound resolver directly.
|
|
|
|
## Split DNS — Local Overrides
|
|
|
|
To avoid hairpin NAT issues (LAN clients connecting to the public WAN IP for local services), DNS overrides are configured in **both** resolvers so that `kenjim.com` subdomains resolve directly to `172.27.0.35` from inside the LAN.
|
|
|
|
### Pi-hole (Local DNS → DNS Records)
|
|
|
|
| Domain | IP |
|
|
|--------|----|
|
|
| `git.kenjim.com` | `172.27.0.35` |
|
|
| `www.kenjim.com` | `172.27.0.35` |
|
|
| `kenji.kenjim.com` | `172.27.0.35` |
|
|
|
|
### pfSense DNS Resolver (Services → DNS Resolver → Host Overrides)
|
|
|
|
Same three entries as above — covers clients that use pfSense Unbound instead of Pi-hole.
|
|
|
|
Without these overrides, LAN clients resolving `git.kenjim.com` get the public WAN IP and connect to pfSense's own HTTPS interface rather than nginx on zet.
|