Practical architecture for combining Pi-hole and Nginx Proxy Manager Overview: Roles of Each Component Pi-hole Runs local DNS (port 53) Serves as the DNS resolver for your network Provides local DNS records so devices resolve service names (e.g., home.lab, jellyfin.lab) Does not need to serve HTTP(80) or HTTPS(443) Nginx Proxy Manager (NPM) Handles all HTTP/HTTPS traffic for services Manages SSL certificates (Let’s Encrypt if you choose) Routes incoming application requests to internal services on different ports/IPs Key Principle Pi-hole handles DNS resolution only. NPM handles web traffic routing and HTTPS termination. This clear separation avoids conflicts and makes management scalable. ✔️ Best Architecture (Most Reliable) 1) Move Pi-hole’s Web UI off Port 80/443 By default Pi-hole binds its web UI to port 80/443. This collides with NPM. Change Pi-hole Admin UI to a different port (e.g., 8081, 8888): On Pi-hole host: change Lighttpd config so /admin listens on 8081 DNS on Pi-hole still runs on port 53 and is unaffected by this change This allows NPM to own 80/443 exclusively. (bolet.io) 2) Local DNS Records in Pi-hole for All Reverse-Proxied Hosts Create A records that point friendly domains to NPM’s IP. Example: pihole.lab.zn80.net → 192.168.10.105 jellyfin.lab.zn80.net → 192.168.10.105 bookstack.lab.zn80.net → 192.168.10.105 Reasoning: Devices query Pi-hole DNS and get your internal names NPM then routes based on Host header Pi-hole is the DNS source of truth for your LAN. (ReproDev) 3) Configure NPM Proxy Hosts for Each Service Inside NPM Proxy Hosts: Domain/Hostname Forward To Port Notes pihole.lab.zn80.net 192.168.10.105 8081 Pi-hole admin UI jellyfin.lab.zn80.net 192.168.10.xxx 8096 Jellyfin service bookstack.lab.zn80.net … … Other services Important details For Pi-hole you may need to forward /admin correct paths Enable SSL for all hosts (ideally) via Let’s Encrypt (even internal DNS) If Let’s Encrypt can’t validate via DNS challenge for internal domains, you can use a local CA or self-signed cert and manage trust in your clients. (Reddit) This makes everything clean to access via Hostnames exclusively: https://jellyfin.lab.zn80.net https://pihole.lab.zn80.net/admin 4) Maintain Internal DNS Instead of Wildcard DNS (Optional but safer) You could be tempted to use a wildcard ( *.lab.zn80.net → 192.168.10.105), but that is less safe and confusing for certificate validation and service discovery. Better pattern: Pi-hole local DNS → explicit A records per hostname Pi-hole → NPM IP NPM → internal service Explicit records help: TTL management SSL certificate issuance Troubleshooting 🧠 Why This Is the Best Way ✅ DNS + Reverse Proxy are cleanly separated Pi-hole isn’t serving HTTP, so there’s no port conflict. NPM can handle 80/443 without interference. ✅ You achieve real HTTPS for internal domains Every service can have a valid certificate via NPM. ✅ Easy, scalable, and future-proof Adding a new service is trivial: Add A record in Pi-hole Add Proxy Host in NPM Done ✅ Works with VPN / local DNS clients If your devices use Pi-hole’s DNS (wired/wireless/VPN), they resolve domain names that NPM can proxy. (Pi-hole Userspace) 🛠 Detailed Implementation A) Change Pi-hole web interface port Edit /etc/lighttpd/lighttpd.conf: server.port = 8081 Restart: sudo systemctl restart lighttpd B) Add DNS entries in Pi-hole In Pi-hole: Local DNS → DNS Records Examples: pihole.lab.zn80.net → 192.168.10.105 jellyfin.lab.zn80.net → 192.168.10.105 C) In NPM, add Proxy Hosts For each service: Domain names: your local domain Forward hostname: actual service IP/port (Pi-hole admin UI at 8081) SSL: Request new cert (if public domain or DNS challenge available) Or use local CA / self-signed trusted cert Set common options: Block exploits: enabled Expires headers: optional Websockets: if needed 🚫 What Not to Do ❌ Don’t proxy Pi-hole DNS-port Do not try to proxy port 53 through NPM. DNS must be direct. ❌ Don’t expose Pi-hole admin UI publicly Pi-hole should only be accessible from your LAN or VPN. ❌ Don’t use wildcards unless you know certificate chain Wildcard DNS can break HTTPS if certificates aren’t matching. 📌 Final Result You Should See After setup: nslookup pihole.lab.zn80.net # → 192.168.10.105 nslookup jellyfin.lab.zn80.net # → 192.168.10.105 Browser: https://pihole.lab.zn80.net/admin # SSL https://jellyfin.lab.zn80.net # SSL Pi-hole DNS works, NPM handles web access, and everything is secure, consistent, and manageable.