Reverse Proxy with Docker
What this article covers
- How a reverse proxy works.
- Running Nginx and Traefik as Docker containers.
- TLS, certificates, and Let’s Encrypt.
- Routing to other containers.
- Authentication and security.
Introduction: Reverse Proxy with Docker
A reverse proxy receives external requests and forwards them to the appropriate internal services. In Docker setups, this is especially useful because many applications run on different ports. Instead of exposing each port individually to the network, you expose only the reverse proxy on ports 80 or 443 and let it decide which service handles each request based on domain names or paths.
This article walks through running Nginx Proxy Manager and Traefik in Docker and covers the security settings that matter.
Key terms
- Reverse Proxy: Intermediary between client and backend.
- Upstream: Target service behind the proxy.
- TLS: Encryption for the connection.
- Certificate: Digital credential for TLS identity.
- Let’s Encrypt: Free certificate authority.
- NPM: Nginx Proxy Manager.
- Traefik: Cloud-native reverse proxy with auto-discovery.
- Authentication: Access verification.
Why use a reverse proxy?
- Single entry point for all services.
- TLS encryption in one place.
- Simpler subdomain management.
- Authentication and rate-limiting support.
- Internal ports stay hidden.
Nginx Proxy Manager
Nginx Proxy Manager provides a web UI for Nginx. It’s ideal for homelabs.
Docker Compose example
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- npm-data:/data
- npm-letsencrypt:/etc/letsencrypt
restart: unless-stopped
volumes:
npm-data:
npm-letsencrypt:
Setup
- Start the container.
- Open
http://host:81in your browser. - Default login:
admin@example.com/changeme. - Create proxy hosts for your internal services.
- Optionally add SSL certificates.
Traefik
Traefik automatically detects Docker containers and creates routes dynamically. Better for advanced setups.
Docker Compose example
services:
traefik:
image: traefik:v3.0
container_name: traefik
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=mail@example.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
restart: unless-stopped
Labels for a service
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
labels:
- "traefik.enable=true"
- "traefik.http.routers.webui.rule=Host(`webui.home.local`)"
- "traefik.http.routers.webui.entrypoints=web"
TLS in local networks
For internal domains without public DNS, use self-signed certificates or mkcert:
mkcert home.local
The certificate gets accepted in your local trust store.
Authentication
Nginx Proxy Manager includes built-in access lists. Traefik can use ForwardAuth with Authelia, Authentik, or oauth2-proxy:
labels:
- "traefik.http.routers.webui.middlewares=authelia@docker"
Routing to Ollama and Open WebUI
| Service | Internal port | Example domain |
|---|---|---|
| Open WebUI | 8080 | webui.home.local |
| Ollama API | 11434 | ollama.home.local |
| Grafana | 3000 | grafana.home.local |
Important: Ollama should not be publicly accessible. Restrict it to internal networks or VPN access only.
Security
- Bind the reverse proxy to ports 80/443; keep services internal only.
- Use TLS for all external access.
- Require authentication for admin interfaces.
- Enable rate-limiting.
- Review logs regularly.
- Never expose services to the internet without protection.
Common pitfalls
- DNS not resolving: Your local domain must be registered in your router or Pi-hole.
- Port 80 already in use: Another service is blocking HTTP.
- Certificate expired: Let’s Encrypt renewal failed.
- Traefik labels incorrect: The service isn’t discovered.
- Path routing not working: Check regex or StripPrefix rules.
- WebSocket missing: Enable WebSocket support for Open WebUI.
Further resources
- BotServ.de Ollama Security
- BotServ.de Docker Compose
- BotServ.de Docker Volumes
- BotServ.de Tailscale Basics
FAQ: Reverse Proxy with Docker
Do I need a reverse proxy? Yes, once you want multiple services accessible via domains or TLS.
Is Nginx or Traefik better? Nginx is simpler; Traefik is more dynamic and cloud-native.
Can I use local domains without internet? Yes, with local DNS or mkcert certificates.
Should I expose Ollama behind a reverse proxy? Only with authentication and VPN, never publicly.
How do I get free certificates? Let’s Encrypt for public domains, or mkcert for local networks.
Sources and further reading
- Nginx Proxy Manager: https://nginxproxymanager.com/
- Traefik: https://traefik.io/
- Let’s Encrypt: https://letsencrypt.org/
- mkcert: https://github.com/FiloSottile/mkcert
Summary: Reverse Proxy with Docker
A reverse proxy in Docker simplifies managing many services and centralizes TLS and authentication. Nginx Proxy Manager works well for simple homelabs, while Traefik suits dynamic and larger deployments. Correct DNS entries, secure certificates, authentication, and protecting sensitive services like Ollama are essential. Set these up properly, and you have a clean, secure infrastructure for local AI services.


