Sep 27, 2024 · Networking / Intermediate · ~3 MIN READ
Set Up a Reverse Proxy with Nginx Proxy Manager
Replace ugly IP-and-port URLs with clean hostnames and TLS certificates using Nginx Proxy Manager.
Who This Is For
Intermediate.
Think of it like a hotel concierge. Guests don’t need to know which floor or room number a service lives on, they just say the name and the concierge quietly sends them to the right door.
What You’ll Build
Access self-hosted services through a readable hostname instead of a raw IP and port number.
Prerequisites
- Docker host
- At least one internal service already running to proxy
What a Reverse Proxy Does
It routes incoming requests to internal services by hostname, issues and renews TLS certificates, and can apply access controls in one place, instead of every service handling its own TLS and exposure separately.
Local-Only vs. Public Reverse Proxy
Deciding to expose a service publicly should be an intentional, service-by-service decision, not a default. Most homelab services are better kept local-only or behind a VPN (see Tailscale vs. WireGuard).
Deploy Nginx Proxy Manager
$ services:
$ npm:
$ image: jc21/nginx-proxy-manager:latest
$ ports:
$ - "80:80"
$ - "81:81"
$ - "443:443"
$ volumes:
$ - ./data:/data
$ - ./letsencrypt:/etc/letsencrypt
Create a Shared Docker Network
Put NPM and the services it proxies on the same Docker network so it can reach them by container name.
$ docker network create proxy-net
Add a Proxy Host
In the NPM UI: Hosts → Proxy Hosts → Add. Set the domain name, forward hostname/IP (the container name on the shared network), and forward port. Enable WebSocket support for apps that need it (chat tools, some dashboards).
TLS Options
- Public domain + Let’s Encrypt for anything actually exposed to the internet
- Internal-only HTTPS with a self-signed or internal CA cert for LAN-only services
- Split DNS if the same hostname needs to resolve differently inside vs. outside your network
What Should Stay VPN-Only
- Portainer
- Proxmox
- NAS admin interfaces
- NetBox
- Router/firewall management
Security & Backup Notes
- Add an access list or basic auth on any admin-style interface you proxy
- Never proxy a service publicly just because it’s convenient, ask whether it actually needs to be internet-reachable
Troubleshooting
- 502 Bad Gateway, the forward hostname/port is wrong, or the target container isn’t on the shared network
- DNS resolves to the wrong IP, check both public DNS and any local DNS override you’ve set up
- Container can’t resolve another container by name, they need to be on the same Docker network
- WebSocket failures, enable the WebSocket support toggle on that proxy host
- Certificate request failure, Let’s Encrypt needs port 80 reachable from the internet for the initial challenge
Lab Finish Line
A local application accessible through a readable hostname rather than a raw IP and port.