Introduction#
After months of using nginx manually, I decided to switch to Traefik. The reason is simple: managing SSL certificates for each new service is tedious. Traefik automates all of that with integrated Let’s Encrypt. Here’s my actual configuration.
Why Traefik#
With Traefik you don’t need to reload nginx every time you add a container. It automatically detects Docker services, generates SSL certificates on demand, and redirects traffic. All declarative.
Base structure#
I create a folder for Traefik:
mkdir -p /home/usuario/docker/traefik
cd /home/usuario/docker/traefikI need three files: docker-compose.yml, traefik.yml and acme.json.
acme.json file#
This file stores the certificates. It must have restrictive permissions:
touch acme.json
chmod 600 acme.jsonTraefik configuration (traefik.yml)#
api:
insecure: true
dashboard: true
entryPoints:
web:
address: ":80"
http:
redirections:
entrypoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /traefik/traefik.yml
watch: true
certificatesResolvers:
letsencrypt:
acme:
email: mi-email@example.com
storage: acme.json
httpChallenge:
entryPoint: webI change mi-email@example.com to my actual email. Let’s Encrypt uses it for notifications.
Docker Compose#
This is the file that starts everything:
version: '3.8'
services:
traefik:
image: traefik:v2.11
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- "80:80"
- "443:443"
environment:
- TZ=Europe/Madrid
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik/traefik.yml:ro
- ./acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.midominio.com`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
networks:
proxy:
driver: bridgeI change traefik.midominio.com to my actual domain. Port 8080 is the Traefik dashboard port.
Starting Traefik#
docker-compose up -dI check the logs:
docker-compose logs -fIf everything goes well, the dashboard will be at https://traefik.midominio.com.
Adding services#
Here’s the good part. To add a new service, I only need labels in Docker. Example with a simple container:
services:
mi-app:
image: mi-imagen:latest
container_name: mi-app
restart: unless-stopped
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.mi-app.rule=Host(`app.midominio.com`)"
- "traefik.http.routers.mi-app.entrypoints=websecure"
- "traefik.http.routers.mi-app.tls.certresolver=letsencrypt"
- "traefik.http.services.mi-app.loadbalancer.server.port=3000"
networks:
proxy:
external: trueI don’t need to touch Traefik. The certificate is generated automatically.
Common issues#
The domain doesn’t resolve: Make sure your DNS points to the correct IP address.
ACME challenge fails: Verify that port 80 is open and accessible from the internet. Let’s Encrypt needs it.
Dashboard slow: It’s normal with many services. It’s not a problem.
Conclusion#
Traefik saved me hours of manual configuration. Each new container only needs four labels. The certificates renew themselves 30 days before they expire.
If you have a home server with several services, it’s worth migrating. The learning curve is short and the benefits are real.
Recommended equipment#
- Raspberry Pi 3 B+ — Lightweight, low-power server to start your homelab
- Raspberry Pi 4 (4GB) — The perfect foundation for homelab, Docker, and monitoring
Affiliate links. No extra cost to you.