Traefik Reverse Proxy
Traefik is a reverse proxy and load balancer that watches the Docker socket and builds its routing table from container labels, instead of a config file someone has to keep in sync by hand. Add a couple of labels to a container’s docker-compose.yml, and Traefik notices it, requests an HTTPS certificate, and starts routing traffic to it automatically: no dashboard click, no manual proxy host needed. Point it at Docker once, and every labeled container that shows up afterward gets picked up on its own, a fundamentally different trade than Nginx Proxy Manager’s one-host-at-a-time form.
License: MIT License, confirmed directly from the LICENSE.md file in the traefik/traefik GitHub repo (Copyright (c) 2016-2020 Containous SAS; 2020-2025 Traefik Labs). Free for any use, including commercial; Traefik Labs separately sells commercial support and a Traefik Hub/Enterprise layer, neither required for self-hosting the core proxy.
Quick facts: official site traefik.io · source github.com/traefik/traefik (63,000+ stars) · Docker Official Image traefik on Docker Hub · latest stable v3.7 · multi-arch (amd64, arm64, armv6, plus ppc64le, riscv64, s390x, and Windows variants) · dashboard listens on port 8080 by default · name is pronounced “traffic.”
Why Traefik instead of a reverse proxy you configure by hand?
Nginx Proxy Manager and Caddy both work from something a person edits directly: a proxy host in a form, or a few lines in a Caddyfile. Traefik works from something Docker already has, the labels attached to each container. Add traefik.enable=true and a routing rule, and Traefik picks it up the moment the container starts, no dashboard step required. That saves real time once a homelab runs a dozen or more containers and a new one shows up every few weeks; for three or four services it’s genuinely more setup than filling in Nginx Proxy Manager‘s dashboard form, which is why NPM is usually the first reverse proxy people run. Traefik also has a reputation for confusing first-timers, well-earned: r/Traefik collects more “is there a simple guide” threads than most self-hosted tools ever do.
Setting up Traefik with Docker
This trimmed static configuration follows Traefik’s own Docker setup guide: HTTP and HTTPS entrypoints, the Docker provider enabled, and HTTP traffic redirected to HTTPS by default.
services:
traefik:
image: traefik:v3.7
container_name: traefik
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
- Install Docker if it isn’t already on the host, save the file above as docker-compose.yml, and run docker compose up -d.
- Mount the Docker socket read-only; exposedbydefault=false means only explicitly labeled containers get picked up, the safer default on a shared host.
- Forward ports 80 and 443 on your router to this machine; nothing else needs to be open yet.
- Add labels to any other container to bring it under Traefik’s routing, covered next.
docker compose up -d
docker compose logs -f traefik
Routing a container with Docker labels
This replaces Nginx Proxy Manager’s Add Proxy Host form: the routing rule lives directly on the container it belongs to, not in a dashboard. Add labels like these to Jellyfin, or any other container on the same Docker network as Traefik, and it’s reachable next time the stack starts.
labels:
- "traefik.enable=true"
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.yourdomain.com`)"
- "traefik.http.routers.jellyfin.entrypoints=websecure"
- "traefik.http.routers.jellyfin.tls.certresolver=letsencrypt"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
Tip: the loadbalancer.server.port line only needs setting when a container exposes more than one port, or the right one isn’t obvious. For a single-port container, Traefik often guesses correctly without it.
Turning on Let’s Encrypt
Traefik requests and renews certificates itself once a certificate resolver is configured, the same job Nginx Proxy Manager does from its SSL tab. Add this to the command block from the compose file above:
- "--certificatesresolvers.letsencrypt.acme.email=you@yourdomain.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
acme.json has to exist with 600 permissions before the first run, or certificate storage fails and Traefik logs it rather than crashing outright:
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json
docker compose up -d
Security notes: the Traefik dashboard listens on port 8080 by default, and some quick-start examples enable api.insecure to skip authentication entirely. Never forward that port to the internet, and never leave insecure mode on outside local testing. Put the dashboard behind its own router with basicauth or forwardauth, the same rule Nginx Proxy Manager’s admin port 81 follows. Mounting the Docker socket also gives Traefik effective root on the host, so pin the image to a specific minor version instead of :latest.
Traefik vs Nginx Proxy Manager vs Caddy
All three terminate HTTPS and forward traffic to the right container. The difference is entirely in how each one finds out where to send it.
| Traefik | Nginx Proxy Manager | Caddy | |
|---|---|---|---|
| Configuration | Docker labels, auto-discovered | Web dashboard, added by hand | Caddyfile, a few lines per site |
| Service discovery | Automatic via Docker, Kubernetes, Swarm | None, every host added manually | None, edited by hand |
| HTTPS | Automatic via Let’s Encrypt resolver | Automatic via the dashboard’s SSL tab | Automatic, on by default |
| Setup difficulty | Steepest of the three | Easiest, GUI-driven | Simple, text-based |
| Best for | Docker-heavy hosts with many containers | A first reverse proxy, GUI preference | Small setups, text config over UI |
| License | MIT | MIT | Apache 2.0 |
- Auto-discovers new containers via Docker labels, no dashboard step per service
- Native Kubernetes, Docker Swarm, and Consul support beyond plain Docker
- Automatic Let’s Encrypt with wildcard certificate support via DNS challenge
- MIT-licensed and actively maintained (63,000+ GitHub stars), no feature paywall
- No web UI for adding routes; everything lives in labels or config files
- Steeper learning curve than NPM’s form-based dashboard for a first reverse proxy
- Misconfigured labels tend to fail silently more often than a dashboard would flag
Hardware: Traefik is a single statically-linked Go binary, light enough for a Raspberry Pi or any low-power always-on box; our homelab setup guide for beginners covers picking that first machine. The real requirement is Docker socket access and, like any reverse proxy, ports 80 and 443 reachable from outside.
Reaching a self-hosted service like Jellyfin from outside the house is one of the most common reasons homelabbers reach for Traefik in the first place. Our Jellyfin remote access guide walks through that setup end to end, and weighs it against Tailscale and WireGuard, which expose a full private network instead of routing one HTTPS subdomain at a time.
FAQ
Is Traefik free and open source?
Yes. It’s MIT-licensed, free for any use including commercial, and maintained by Traefik Labs alongside a paid Traefik Hub/Enterprise layer built on top of the open-source proxy, not instead of it.
Is Traefik harder to learn than Nginx Proxy Manager?
For a first reverse proxy, yes. NPM’s dashboard form is faster to grasp than Traefik’s entrypoints-routers-services model and label syntax. That complexity pays for itself once there are enough containers that adding each one by hand becomes the slower option.
Does Traefik work with Kubernetes, or only Docker?
Both, plus Docker Swarm, Consul, Nomad, and a handful of other backends. Docker is the most common homelab case, but the same auto-discovery model applies to Kubernetes Ingress and CRDs.
Is the Traefik dashboard safe to expose to the internet?
Not without authentication in front of it. api.insecure mode is for local testing only; a production setup should put the dashboard behind a router with basicauth or forwardauth, the same way Nginx Proxy Manager’s admin port needs its own protection.
Can Traefik replace Nginx Proxy Manager entirely?
Functionally, yes; both terminate HTTPS and route to containers. The trade-off is setup style: NPM stays a dashboard and a form, Traefik stays labels and command flags. Plenty of homelabs run NPM first and move to Traefik later.
For a handful of containers, Nginx Proxy Manager’s dashboard is still the faster path to a working HTTPS address. Once labels and auto-discovery start saving more time than they cost to learn, that’s the point where Traefik earns the steeper setup this guide just walked through.