Reverse Proxy and TLS
Nginx Proxy Manager vs Traefik vs Caddy, the real trade-offs between them, and automatic TLS with Let's Encrypt so you stop remembering port numbers.
A reverse proxy is the thing that turns
http://192.168.1.50:8096 into https://jellyfin.yourdomain.com - one
entry point that routes by hostname to the right service behind it,
and handles TLS certificates centrally instead of per-service.
The three real options, and their actual trade-offs
- Nginx Proxy Manager (NPM) - a web UI over Nginx. You add proxy hosts by clicking through a form: hostname, target IP:port, request a Let's Encrypt cert with a checkbox. Easiest to start with if you'd rather not touch config files, and genuinely fine long-term. Downside: configuration lives in a database behind the UI, which makes it harder to version-control or review as a diff compared to plain files, and it's one more thing running with a web login to secure.
- Traefik - configuration-as-code, with the standout feature of automatic service discovery from Docker labels: add a couple of labels to a container's compose file and Traefik picks it up and routes to it with no separate proxy-host step. Powerful once you have many services, but the label syntax and its routing/middleware concepts have a real learning curve, and its docs assume you already understand reverse proxy concepts fairly well.
- Caddy - configuration-as-code like Traefik, but with a much
simpler config format and automatic TLS by default - point it at
a hostname and it requests and renews the certificate without extra
steps. No web UI, no database, no Docker-label magic; you edit a
Caddyfile.
Recommendation: Caddy, if you're comfortable editing a text file and want automatic TLS with the least amount of clicking or label-syntax learning. Its config format is close to plain English, which makes it easy to read back later:
jellyfin.yourdomain.com {
reverse_proxy 192.168.20.10:8096
}
pihole.yourdomain.com {
reverse_proxy 192.168.20.11:80
}
Reach for Nginx Proxy Manager instead if you'd genuinely rather manage this by clicking than editing files - that's a legitimate preference, not a lesser choice. Reach for Traefik if you're already deep into Docker Compose across many services and want routing config to live alongside each service's own compose file rather than in one central place.
Automatic TLS with ACME / Let's Encrypt
ACME is the protocol your reverse proxy uses to request and automatically renew free certificates from Let's Encrypt (or alternatives like ZeroSSL) without you manually generating or installing anything. Two validation methods matter:
- HTTP challenge - Let's Encrypt requests a file over port 80 to confirm you control the domain. Requires port 80 reachable from the internet for that one request, which usually means this only works cleanly for services you're intentionally exposing publicly.
- DNS challenge - proves domain control by creating a TXT record via your DNS provider's API instead. Doesn't require any inbound port to be open, which makes it the better fit for internal-only services you still want real TLS certificates for (avoiding browser warnings on your LAN). Caddy and Traefik both support DNS challenges via provider-specific plugins/modules; check your DNS provider is supported before committing to this route.
Where the reverse proxy sits
Run it as its own dedicated VM or LXC container (per Proxmox VMs and Containers), on your homelab VLAN, with the compose files or Caddyfile for it kept separate from individual services. It becomes the one thing every other service's DNS record points to internally (via the local DNS setup from Networking Basics), and optionally the one thing that's actually reachable from outside if you choose to expose anything publicly.
⚠️ Risk: putting a reverse proxy in front of a service doesn't automatically make exposing it to the internet safe - it just centralizes TLS and adds a single, more auditable choke point. Only put services behind a public-facing hostname deliberately, and keep everything else reachable on your local network (or via VPN - next page) only.
Next: Local DNS for Your Homelab.