Why Traefik Beats a Manual Nginx Setup
Running multiple services on a single server without a reverse proxy is a recipe for port chaos. Traefik solves that by acting as a smart traffic director – routing incoming requests to the right container, handling SSL certificates automatically, and doing it all without requiring you to restart anything when configuration changes.

What Traefik Actually Does and Why It Matters for Home Labs
Traefik is a cloud-native reverse proxy built specifically for containerized environments. Unlike Nginx or Apache, which require you to manually write server blocks and reload the process every time you add a new service, Traefik reads Docker labels directly from your containers and updates its routing table on the fly. Add a label to a new container, and Traefik picks it up within seconds – no config file editing, no service restarts.
The SSL story is where Traefik really pulls ahead. It integrates natively with Let’s Encrypt through the ACME protocol, meaning it can request, validate, and renew certificates without any third-party tooling or cron jobs. You configure your certificate resolver once, point it at your email address, and Traefik handles the rest. Wildcard certificates are also supported if you set up DNS challenge validation through a supported provider like Cloudflare.
Traefik runs as a Docker container itself, which keeps the installation clean and easy to update. Its dashboard – a built-in web UI – gives you a live view of all active routers, services, and middleware, which is genuinely useful when you’re debugging why traffic isn’t reaching a particular container. For anyone already running a home lab with Docker Compose stacks, it drops in without requiring infrastructure changes. If you’re also running a Proxmox hypervisor to manage your lab VMs, Traefik pairs well as a dedicated proxy container on one of those VMs.
Before you start, you need a domain name pointed at your server’s public IP, Docker and Docker Compose installed, and ports 80 and 443 open on your firewall or router. Traefik needs port 80 for HTTP challenge validation and port 443 for serving HTTPS traffic. If your ISP blocks those ports, DNS challenge is your only route to valid certificates.
Setting Up Traefik with Docker Compose and Let’s Encrypt
Start by creating a dedicated directory for Traefik and the files it needs. You’ll want at least two files at this stage: a docker-compose.yml and a traefik.yml static configuration file. You also need to create an empty acme.json file where Traefik stores certificate data, and you must set its permissions to 600 immediately – Traefik will refuse to start if that file has open permissions.
Your traefik.yml is where the core behavior is defined. Set the entry points for HTTP (port 80) and HTTPS (port 443), enable the Docker provider so Traefik can read container labels, and configure your certificate resolver. A minimal resolver block needs three things: the ACME email address, the storage path pointing to your acme.json, and the challenge type. For HTTP challenge, the block looks like this:
certificatesResolvers:
letsencrypt:
acme:
email: you@yourdomain.com
storage: /acme.json
httpChallenge:
entryPoint: web
The Docker Compose file for Traefik itself is straightforward but requires a few specific settings. Mount the Docker socket so Traefik can watch for container events, mount your traefik.yml and acme.json into the container, and expose ports 80 and 443 on the host. Create a dedicated external Docker network – call it something like traefik_proxy – and attach Traefik to it. Every other service that needs routing through Traefik must also join this network. The dashboard should be enabled for initial setup but protected with basic auth middleware before you expose it publicly.

Routing a service through Traefik works entirely through Docker labels on the service’s container. Four labels handle the basics: one to tell Traefik to watch the container, one to define the router rule (your hostname), one to attach the TLS certificate resolver, and one to specify which internal port your service listens on. For a service running on port 8080 at app.yourdomain.com, the labels look like this:
labels: - "traefik.enable=true" - "traefik.http.routers.myapp.rule=Host(`app.yourdomain.com`)" - "traefik.http.routers.myapp.entrypoints=websecure" - "traefik.http.routers.myapp.tls.certresolver=letsencrypt" - "traefik.http.services.myapp.loadbalancer.server.port=8080"
One detail that catches people off guard: if your service container doesn’t expose its port in the Dockerfile (which many official images do), you still need the loadbalancer.server.port label to tell Traefik where to forward traffic. Without it, Traefik guesses based on exposed ports, which works sometimes and fails silently other times. Adding the port label explicitly eliminates that ambiguity and is worth doing as a standard practice across all your services.
Middleware, Redirects, and Keeping Things Secure
A basic Traefik setup routes traffic and handles certificates, but middleware is what turns it into a proper production-grade proxy. Two middleware configurations belong in every setup: an HTTP-to-HTTPS redirect and a security headers block. The redirect is defined as a router on the web (port 80) entry point that catches all traffic and issues a permanent redirect to the websecure entry point. Security headers – including X-Content-Type-Options, X-Frame-Options, and Strict-Transport-Security – can be defined once as a reusable middleware and attached to any router with a single label.

Middleware can be defined either in your static traefik.yml, in a separate dynamic configuration file, or directly as Docker labels. The label approach keeps everything contained per service but gets verbose for complex middleware chains. For headers and redirects that apply globally, a dynamic config file mounted into the Traefik container is cleaner. Once you’re routing more than a handful of services – say, a password manager like Bitwarden alongside a media server and a monitoring stack – centralizing shared middleware saves you from repeating the same twenty labels across every Compose file. The distinction between what lives in labels versus config files is worth deciding early, because mixing both approaches without a consistent system gets confusing fast.
Frequently Asked Questions
Does Traefik work without a public domain name?
Traefik can run without a public domain for internal routing, but automatic Let’s Encrypt SSL certificates require a valid domain name and either HTTP or DNS challenge access.
What is the acme.json file in Traefik?
It is the file where Traefik stores your Let’s Encrypt certificate data. It must be created manually and have 600 file permissions before Traefik will start.





