01Why Traefik Changed How I Deploy Services
Before Traefik, adding a new service to my home lab meant editing Nginx configuration files, reloading the web server, and manually setting up SSL certificates. It worked, but it was tedious and error-prone. One misplaced semicolon in an Nginx config could take down every service behind the proxy.
Traefik changed everything. It automatically discovers Docker containers, routes traffic based on labels you add to your compose files, and handles SSL certificates from Let's Encrypt without any manual intervention. Adding a new service is as simple as adding three labels to your docker-compose.yml.
I've been running Traefik in production for three years across personal projects and small business deployments. This guide covers the practical setup I use, including the gotchas that the official docs don't always make clear.
02How Traefik Works with Docker
Traefik has a concept of "providers" — sources of truth for routing configuration. The Docker provider watches the Docker socket for container events. When a container starts with Traefik labels, Traefik automatically creates a route for it. When the container stops, the route is removed.
This means zero-downtime deployments work out of the box. Start the new container, Traefik picks it up, stop the old one, Traefik removes it. No configuration reloads needed.
The key concepts are:
- Entrypoints: The ports Traefik listens on (typically 80 and 443)
- Routers: Rules that match incoming requests (usually by hostname)
- Services: The backend containers that handle the requests
- Middleware: Transformations applied to requests (authentication, redirects, rate limiting)
All of these are configured via Docker labels on your service containers.
03Basic Traefik Setup
First, create a Docker network that Traefik and your services will share:
[terminal]
1# Create the shared network2docker network create proxy34# Create directory for Traefik5mkdir -p ~/docker/traefik6touch ~/docker/traefik/acme.json7chmod 600 ~/docker/traefik/acme.json04Traefik Docker Compose Configuration
Here's a production-ready Traefik configuration with automatic SSL:
[docker-compose.yml]
1# ~/docker/traefik/docker-compose.yml2services: 3 traefik: 4 image: traefik:v3.15 container_name: traefik6 restart: unless-stopped7 ports: 8 - "80:80"9 - "443:443"10 volumes: 11 - /var/run/docker.sock:/var/run/docker.sock:ro12 - ./acme.json:/acme.json13 command: 14 - "--api.dashboard=true"15 - "--providers.docker=true"16 - "--providers.docker.exposedbydefault=false"17 - "--entrypoints.web.address=:80"18 - "--entrypoints.websecure.address=:443"19 - "--entrypoints.web.http.redirections.entrypoint.to=websecure"20 - "--certificatesresolvers.letsencrypt.acme.email=you@example.com"21 - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"22 - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"23 labels: 24 - "traefik.enable=true"25 - "traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)"26 - "traefik.http.routers.dashboard.service=api@internal"27 - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"28 networks: 29 - proxy3031networks: 32 proxy: 33 external: trueThe Docker socket gives Traefik full access to your Docker daemon. In high-security environments, use a Docker socket proxy like tecnativa/docker-socket-proxy to limit access.
05Adding Services Behind Traefik
Once Traefik is running, expose any service by adding labels to its compose file. Here's Nextcloud as an example:
[docker-compose.yml]
1# ~/docker/nextcloud/docker-compose.yml2services: 3 nextcloud: 4 image: nextcloud:295 container_name: nextcloud6 restart: unless-stopped7 volumes: 8 - nextcloud_data:/var/www/html9 labels: 10 - "traefik.enable=true"11 - "traefik.http.routers.nextcloud.rule=Host(`cloud.yourdomain.com`)"12 - "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"13 - "traefik.http.services.nextcloud.loadbalancer.server.port=80"14 networks: 15 - proxy16 - internal1718 db: 19 image: postgres:16-alpine20 networks: 21 - internal # Database NOT on proxy network2223volumes: 24 nextcloud_data: 2526networks: 27 proxy: 28 external: true29 internal: Set exposedbydefault=false in Traefik config and explicitly enable services with traefik.enable=true. This prevents accidentally exposing internal services.
06Useful Middleware
Traefik middleware lets you add authentication, rate limiting, and security headers to any service. Here are the ones I use most:
Basic authentication for admin panels — don't expose dashboards without auth. Generate a password hash with: echo $(htpasswd -nB user) | sed -e s/\$/\$\$/g
Security headers that improve your score on securityheaders.com and protect against common web attacks.
Rate limiting to prevent brute-force attacks on login pages.
All middleware is configured via Docker labels, keeping everything in your compose files. Browse our web-servers category for complete Traefik configurations with various middleware combinations.