Clone
5
Traefik
groales edited this page 2025-12-02 19:31:22 +01:00

Integración con Traefik

Esta guía explica cómo integrar Portainer CE con Traefik como proxy inverso para obtener:

  • 🔒 Certificados SSL/TLS automáticos con Let's Encrypt
  • 🌐 Acceso mediante dominio en lugar de IP:puerto
  • 🔐 Capa adicional de seguridad con middlewares

Requisitos Previos

  • Traefik desplegado desde el repositorio groales/traefik
  • Red Docker compartida proxy
  • Dominio apuntando a tu servidor
  • Puertos 80 y 443 accesibles desde Internet

Arquitectura

Internet → Traefik (80/443) → Portainer (9443)
              ↓
          Let's Encrypt

Configuración con docker-compose.override.yml

1. Verificar Red Compartida

Asegúrate de que la red proxy existe (creada por el repo de Traefik):

docker network ls | grep proxy

2. Crear docker-compose.override.yml

En el directorio de Portainer, copia el ejemplo:

cd ~/portainer  # O tu ruta local
cp docker-compose.override.traefik.yml.example docker-compose.override.yml

3. Editar docker-compose.override.yml

services:
  portainer:
    networks:
      - proxy
    labels:
      # Habilitar Traefik
      - "traefik.enable=true"
      
      # Router HTTPS
      - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`)"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls=true"
      - "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
      
      # Service backend
      - "traefik.http.services.portainer.loadbalancer.server.port=9443"
      - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
      - "traefik.http.services.portainer.loadbalancer.serversTransport=insecure@file"
      
      # Middlewares de seguridad (opcional)
      - "traefik.http.routers.portainer.middlewares=security-headers@file"

networks:
  proxy:
    external: true

Notas importantes:

  • Usa la red proxy (creada por el repo de Traefik)
  • El certresolver=letsencrypt debe coincidir con tu configuración en traefik.yml
  • server.scheme=https porque Portainer usa HTTPS internamente
  • El middleware security-headers@file viene del archivo dynamic/config.yml de Traefik

4. Reiniciar Portainer

docker compose down
docker compose up -d

5. Verificar

# Ver que Portainer está en la red proxy
docker network inspect proxy | grep portainer

# Ver logs de Traefik
docker logs traefik | grep portainer

Acceder a: https://portainer.tudominio.com

Middlewares Avanzados

Usar Middlewares del Repo Traefik

El repositorio de Traefik ya incluye middlewares en dynamic/config.yml:

# En docker-compose.override.yml
labels:
  # Combinar múltiples middlewares
  - "traefik.http.routers.portainer.middlewares=security-headers@file,rate-limit@file"

Middlewares disponibles:

  • security-headers@file: Headers de seguridad HTTP
  • rate-limit@file: Limitación de peticiones
  • ip-allowlist@file: Restricción por IP (ajustar rangos en Traefik)
  • auth-basic@file: Autenticación básica (ajustar password en Traefik)

Autenticación Básica Adicional

Si quieres añadir autenticación antes de llegar a Portainer:

labels:
  - "traefik.http.routers.portainer.middlewares=auth-basic@file,security-headers@file"

Luego edita dynamic/config.yml en el repo de Traefik y genera tu hash:

docker run --rm httpd:alpine htpasswd -nbB admin tu_password

Restricción por IP

Para acceso solo desde red local:

labels:
  - "traefik.http.routers.portainer.middlewares=ip-allowlist@file,security-headers@file"

El middleware ip-allowlist@file ya incluye rangos privados (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).

Troubleshooting

Error 502 Bad Gateway

  1. Verificar red compartida:

    docker network inspect proxy
    
  2. Verificar puerto y scheme:

    - "traefik.http.services.portainer.loadbalancer.server.port=9443"
    - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
    
  3. Ver logs:

    docker logs portainer
    docker logs traefik
    

Certificado No Se Genera

  1. Verificar DNS:

    nslookup portainer.tudominio.com
    
  2. Ver logs de ACME en Traefik:

    docker logs traefik | grep -i acme
    
  3. Verificar email en traefik.yml:

    certificatesResolvers:
      letsencrypt:
        acme:
          email: tu-email@tudominio.com  # Debe estar configurado
    

Certificado Autofirmado (Error 500)

Portainer usa certificado SSL autofirmado. Traefik necesita el serversTransport para aceptarlo:

labels:
  - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
  - "traefik.http.services.portainer.loadbalancer.serversTransport=insecure@file"

El transport insecure@file está definido en dynamic/config.yml del repositorio de Traefik.

Nota: El usuario final ve el certificado de Let's Encrypt, no el autofirmado de Portainer.

Ejemplo Completo

docker-compose.override.yml Mínimo

services:
  portainer:
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`)"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
      - "traefik.http.services.portainer.loadbalancer.server.port=9443"
      - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
      - "traefik.http.services.portainer.loadbalancer.serversTransport=insecure@file"

networks:
  proxy:
    external: true

docker-compose.override.yml con Seguridad

services:
  portainer:
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`)"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
      - "traefik.http.services.portainer.loadbalancer.server.port=9443"
      - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
      - "traefik.http.services.portainer.loadbalancer.serversTransport=insecure@file"
      - "traefik.http.routers.portainer.middlewares=security-headers@file,rate-limit@file"

networks:
  proxy:
    external: true
services:
  portainer:
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`)"
      - "traefik.http.routers.portainer.entrypoints=websecure"
      - "traefik.http.routers.portainer.tls.certresolver=letsencrypt"
      - "traefik.http.services.portainer.loadbalancer.server.port=9443"
      - "traefik.http.services.portainer.loadbalancer.server.scheme=https"
      - "traefik.http.routers.portainer.middlewares=security-headers@file,rate-limit@file,ip-allowlist@file"

networks:
  proxy:
    external: true

Recursos adicionales:

Volver a: Página Principal