diff --git a/Traefik.md b/Traefik.md index 90f75f1..cbf5b7d 100644 --- a/Traefik.md +++ b/Traefik.md @@ -5,14 +5,13 @@ Esta guía explica cómo integrar Portainer CE con **Traefik** como proxy invers - 🔒 **Certificados SSL/TLS automáticos** con Let's Encrypt - 🌐 **Acceso mediante dominio** en lugar de IP:puerto - 🔐 **Capa adicional de seguridad** con middlewares -- 📊 **Balanceo de carga** (si usas múltiples instancias) ## Requisitos Previos -- ✅ Traefik instalado y funcionando -- ✅ Red Docker compartida entre Traefik y Portainer -- ✅ Dominio apuntando a tu servidor (para Let's Encrypt) -- ✅ Puertos 80 y 443 accesibles desde Internet (para validación de Let's Encrypt) +- ✅ Traefik desplegado desde el repositorio `groales/traefik` +- ✅ Red Docker compartida `proxy` +- ✅ Dominio apuntando a tu servidor +- ✅ Puertos 80 y 443 accesibles desde Internet ## Arquitectura @@ -22,80 +21,219 @@ Internet → Traefik (80/443) → Portainer (9443) Let's Encrypt ``` -Traefik gestiona: -- Terminación SSL/TLS -- Renovación automática de certificados -- Redirección HTTP → HTTPS -- Headers de seguridad +## Configuración con docker-compose.override.yaml -## Configuración Básica +### 1. Verificar Red Compartida -### 1. Crear Red Compartida - -Si no existe, crear una red para que Traefik y Portainer se comuniquen: +Asegúrate de que la red `proxy` existe (creada por el repo de Traefik): ```bash -docker network create traefik_network +docker network ls | grep proxy ``` -### 2. Modificar docker-compose.yaml de Portainer +### 2. Crear docker-compose.override.yaml -Opción recomendada: usar `docker-compose.override.yaml` (ver abajo). +En el directorio de Portainer, copia el ejemplo: -O editar directamente `docker-compose.yaml`: +```bash +cd ~/portainer # O tu ruta local +cp docker-compose.override.yaml.example docker-compose.override.yaml +``` + +### 3. Editar docker-compose.override.yaml ```yaml services: portainer: - container_name: portainer - image: portainer/portainer-ce:lts - restart: always - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - portainer_data:/data - # NO exponer puertos directamente - # ports: - # - "9443:9443" networks: - - portainer_network - - traefik_network # Añadir red de Traefik + - proxy labels: # Habilitar Traefik - "traefik.enable=true" - # Router HTTP (redirección a HTTPS) - - "traefik.http.routers.portainer-http.rule=Host(`portainer.tudominio.com`)" - - "traefik.http.routers.portainer-http.entrypoints=web" - - "traefik.http.routers.portainer-http.middlewares=redirect-to-https" - # 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 + # Service backend - "traefik.http.services.portainer.loadbalancer.server.port=9443" - "traefik.http.services.portainer.loadbalancer.server.scheme=https" - # Middleware de redirección - - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" - -volumes: - portainer_data: - name: portainer_data + # Middlewares de seguridad (opcional) + - "traefik.http.routers.portainer.middlewares=security-headers@file" networks: - portainer_network: - name: portainer_network - traefik_network: + proxy: external: true ``` -### 3. Usar docker-compose.override.yaml (Recomendado) +**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 -En el repositorio ya existe `docker-compose.override.yaml.example`. Copiarlo: +### 4. Reiniciar Portainer + +```bash +docker compose down +docker compose up -d +``` + +### 5. Verificar + +```bash +# 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`: + +```yaml +# En docker-compose.override.yaml +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: + +```yaml +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: + +```bash +docker run --rm httpd:alpine htpasswd -nbB admin tu_password +``` + +### Restricción por IP + +Para acceso solo desde red local: + +```yaml +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**: + ```bash + docker network inspect proxy + ``` + +2. **Verificar puerto y scheme**: + ```yaml + - "traefik.http.services.portainer.loadbalancer.server.port=9443" + - "traefik.http.services.portainer.loadbalancer.server.scheme=https" + ``` + +3. **Ver logs**: + ```bash + docker logs portainer + docker logs traefik + ``` + +### Certificado No Se Genera + +1. **Verificar DNS**: + ```bash + nslookup portainer.tudominio.com + ``` + +2. **Ver logs de ACME en Traefik**: + ```bash + docker logs traefik | grep -i acme + ``` + +3. **Verificar email en traefik.yml**: + ```yaml + certificatesResolvers: + letsencrypt: + acme: + email: tu-email@tudominio.com # Debe estar configurado + ``` + +### Certificado Autofirmado en Logs + +Es normal. Traefik se comunica con Portainer por HTTPS (cert autofirmado interno), pero el usuario final ve el certificado de Let's Encrypt. + +## Ejemplo Completo + +### docker-compose.override.yaml Mínimo + +```yaml +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" + +networks: + proxy: + external: true +``` + +### docker-compose.override.yaml con Seguridad + +```yaml +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**: +- [Repositorio Traefik](https://git.ictiberia.com/groales/traefik) +- [Wiki Traefik](https://git.ictiberia.com/groales/traefik/wiki) + +**Volver a**: [Página Principal](Home) ```bash cp docker-compose.override.yaml.example docker-compose.override.yaml @@ -546,4 +684,4 @@ Para máxima seguridad, no exponer Portainer a Internet: - [Let's Encrypt Rate Limits](https://letsencrypt.org/docs/rate-limits/) - [Traefik Middlewares](https://doc.traefik.io/traefik/middlewares/overview/) -**Volver a**: [Página Principal](Home) | [Instalación Avanzada](Instalacion) +**Volver a**: [Página Principal](Home)