Configurar Traefik v2.11 como reverse proxy con Docker y HTTPS automático con Let’s Encrypt

Etiquetas:

Introducción

Después de meses usando nginx manualmente, decidí cambiar a Traefik. La razón es simple: gestionar certificados SSL para cada servicio nuevo es tedioso. Traefik automatiza todo eso con Let’s Encrypt integrado. Aquí está mi configuración real.

Por qué Traefik

Con Traefik no necesitas recargar nginx cada vez que añades un contenedor. Detecta automáticamente servicios Docker, genera certificados SSL bajo demanda y redirige el tráfico. Todo declarativo.

Estructura base

Creo una carpeta para Traefik:

mkdir -p /home/usuario/docker/traefik
cd /home/usuario/docker/traefik

Necesito tres archivos: docker-compose.yml, traefik.yml y acme.json.

Archivo acme.json

Este archivo almacena los certificados. Debe tener permisos restrictivos:

touch acme.json
chmod 600 acme.json

Configuración de Traefik (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: web

Cambio mi-email@example.com por mi correo real. Let’s Encrypt lo usa para notificaciones.

Docker Compose

Este es el archivo que levanta todo:

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: bridge

Cambio traefik.midominio.com por mi dominio real. El puerto 8080 es el del dashboard de Traefik.

Levantar Traefik

docker-compose up -d

Reviso logs:

docker-compose logs -f

Si todo va bien, el dashboard estará en https://traefik.midominio.com.

Añadir servicios

Aquí está lo bueno. Para añadir un servicio nuevo, solo necesito labels en Docker. Ejemplo con un contenedor simple:

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: true

No necesito tocar Traefik. El certificado se genera automáticamente.

Problemas comunes

El dominio no resuelve: Asegúrate de que tu DNS apunta a la IP correcta.

ACME challenge falla: Verifica que el puerto 80 está abierto y accesible desde internet. Let’s Encrypt lo necesita.

Dashboard lento: Es normal con muchos servicios. No es un problema.

Conclusión

Traefik me ahorró horas de configuración manual. Cada contenedor nuevo solo necesita cuatro labels. Los certificados se renuevan solos 30 días antes de expirar.

Si tienes un servidor doméstico con varios servicios, vale la pena migrarse. La curva de aprendizaje es corta y los beneficios son reales.


Equipamiento recomendado

Enlaces de afiliado. Sin coste extra para ti.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *