commit 7a8c098ac403521930ac8986f32ec5160f1a492a Author: groales Date: Sat Nov 29 13:39:12 2025 +0100 Documentación completa del wiki en español diff --git a/Backup.md b/Backup.md new file mode 100644 index 0000000..4a555d1 --- /dev/null +++ b/Backup.md @@ -0,0 +1,520 @@ +# Backup y Restauración + +Esta guía explica cómo realizar copias de seguridad y restaurar los datos de Portainer CE. + +## ¿Qué se Respalda? + +Portainer almacena todos sus datos en el volumen Docker **`portainer_data`**, que incluye: + +- 🔐 **Configuración de usuarios y autenticación** +- 🌐 **Entornos (endpoints) configurados** +- 📦 **Stacks, plantillas y configuraciones** +- 🔑 **Secretos, configs, y credenciales** +- 📊 **Configuraciones de roles y permisos** +- 🎨 **Personalizaciones de UI y configuraciones** + +⚠️ **Importante**: El volumen `portainer_data` contiene información sensible. Protege los backups adecuadamente. + +## Estrategias de Backup + +### Opción 1: Backup Manual del Volumen + +#### Crear Backup + +```bash +# Detener Portainer (recomendado para consistencia) +docker compose down + +# Crear backup del volumen usando contenedor temporal +docker run --rm \ + -v portainer_data:/data \ + -v $(pwd):/backup \ + alpine \ + tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data . + +# Reiniciar Portainer +docker compose up -d +``` + +**Resultado**: Archivo `portainer-backup-YYYYMMDD-HHMMSS.tar.gz` en el directorio actual. + +#### Backup sin Detener Portainer (En Caliente) + +```bash +# Crear backup sin detener el servicio +docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data . +``` + +⚠️ **Nota**: Los backups en caliente pueden tener inconsistencias si hay cambios durante la copia. Para backups críticos, detén Portainer primero. + +#### Restaurar Backup + +```bash +# 1. Detener Portainer +docker compose down + +# 2. Eliminar volumen existente (⚠️ cuidado!) +docker volume rm portainer_data + +# 3. Crear nuevo volumen +docker volume create portainer_data + +# 4. Restaurar datos desde backup +docker run --rm \ + -v portainer_data:/data \ + -v $(pwd):/backup \ + alpine \ + tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data + +# 5. Verificar permisos +docker run --rm \ + -v portainer_data:/data \ + alpine \ + chown -R root:root /data + +# 6. Reiniciar Portainer +docker compose up -d +``` + +### Opción 2: Backup con Script Automatizado + +Crear script `backup-portainer.sh`: + +```bash +#!/bin/bash + +# Configuración +BACKUP_DIR="/var/backups/portainer" +RETENTION_DAYS=30 +VOLUME_NAME="portainer_data" +COMPOSE_PATH="/ruta/a/tu/portainer" + +# Crear directorio de backups si no existe +mkdir -p "$BACKUP_DIR" + +# Timestamp +TIMESTAMP=$(date +%Y%m%d-%H%M%S) +BACKUP_FILE="$BACKUP_DIR/portainer-backup-$TIMESTAMP.tar.gz" + +echo "[$(date)] Iniciando backup de Portainer..." + +# Opción 1: Backup en caliente (servicio corriendo) +docker run --rm \ + -v "$VOLUME_NAME":/data:ro \ + -v "$BACKUP_DIR":/backup \ + alpine \ + tar czf "/backup/portainer-backup-$TIMESTAMP.tar.gz" -C /data . + +# Opción 2: Backup con detención (más seguro, comentar la opción 1 si usas esta) +# cd "$COMPOSE_PATH" +# docker compose down +# docker run --rm \ +# -v "$VOLUME_NAME":/data \ +# -v "$BACKUP_DIR":/backup \ +# alpine \ +# tar czf "/backup/portainer-backup-$TIMESTAMP.tar.gz" -C /data . +# docker compose up -d + +# Verificar que el backup se creó +if [ -f "$BACKUP_FILE" ]; then + SIZE=$(du -h "$BACKUP_FILE" | cut -f1) + echo "[$(date)] Backup completado: $BACKUP_FILE ($SIZE)" +else + echo "[$(date)] ERROR: Backup falló" + exit 1 +fi + +# Limpiar backups antiguos +echo "[$(date)] Limpiando backups antiguos (>$RETENTION_DAYS días)..." +find "$BACKUP_DIR" -name "portainer-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete + +echo "[$(date)] Proceso completado" +``` + +Hacer ejecutable y probar: + +```bash +chmod +x backup-portainer.sh +./backup-portainer.sh +``` + +### Opción 3: Backup Automatizado con Cron + +Programar backups diarios a las 2:00 AM: + +```bash +# Editar crontab +crontab -e + +# Añadir línea: +0 2 * * * /ruta/a/backup-portainer.sh >> /var/log/portainer-backup.log 2>&1 +``` + +Verificar cron: + +```bash +# Ver crontab actual +crontab -l + +# Ver logs de backup +tail -f /var/log/portainer-backup.log +``` + +### Opción 4: Backup a Almacenamiento Remoto + +#### Backup a NFS/CIFS + +```bash +# Montar share remoto +mount -t nfs servidor.local:/backups /mnt/backups + +# Crear backup directamente en share +docker run --rm \ + -v portainer_data:/data:ro \ + -v /mnt/backups:/backup \ + alpine \ + tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data . +``` + +#### Backup a S3/MinIO + +Usando `rclone`: + +```bash +# Configurar rclone primero +rclone config + +# Crear backup y subir a S3 +BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz" + +docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf "/backup/$BACKUP_FILE" -C /data . + +rclone copy "$BACKUP_FILE" s3-remote:bucket-name/portainer-backups/ +rm "$BACKUP_FILE" +``` + +#### Backup con rsync + +```bash +# Crear backup local +BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz" + +docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf "/backup/$BACKUP_FILE" -C /data . + +# Copiar a servidor remoto +rsync -avz --progress "$BACKUP_FILE" usuario@servidor-backup:/backups/portainer/ + +# Opcional: eliminar backup local +rm "$BACKUP_FILE" +``` + +## Restauración de Emergencia + +### Escenario 1: Corrupción de Datos + +```bash +# 1. Detener Portainer inmediatamente +docker compose down + +# 2. Renombrar volumen corrupto (por si acaso) +docker volume create portainer_data_corrupted +docker run --rm \ + -v portainer_data:/source \ + -v portainer_data_corrupted:/dest \ + alpine \ + sh -c "cp -a /source/. /dest/" + +# 3. Limpiar volumen original +docker volume rm portainer_data +docker volume create portainer_data + +# 4. Restaurar desde último backup válido +docker run --rm \ + -v portainer_data:/data \ + -v $(pwd):/backup \ + alpine \ + tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data + +# 5. Reiniciar +docker compose up -d +``` + +### Escenario 2: Migración a Nuevo Servidor + +En el **servidor antiguo**: + +```bash +# Crear backup +docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf /backup/portainer-migration.tar.gz -C /data . + +# Copiar a nuevo servidor +scp portainer-migration.tar.gz usuario@nuevo-servidor:/tmp/ +``` + +En el **servidor nuevo**: + +```bash +# 1. Clonar repositorio o copiar docker-compose.yaml +git clone https://git.ictiberia.com/groales/portainer +cd portainer + +# 2. Crear volumen +docker volume create portainer_data + +# 3. Restaurar datos +docker run --rm \ + -v portainer_data:/data \ + -v /tmp:/backup \ + alpine \ + tar xzf /backup/portainer-migration.tar.gz -C /data + +# 4. Iniciar Portainer +docker compose up -d + +# 5. Verificar +docker logs portainer +``` + +### Escenario 3: Rollback a Versión Anterior + +Si una actualización de Portainer causa problemas: + +```bash +# 1. Detener versión actual +docker compose down + +# 2. Editar docker-compose.yaml y cambiar tag +# De: portainer/portainer-ce:lts +# A: portainer/portainer-ce:2.19.4 (versión específica) + +# 3. Restaurar backup de antes de la actualización +docker volume rm portainer_data +docker volume create portainer_data + +docker run --rm \ + -v portainer_data:/data \ + -v $(pwd):/backup \ + alpine \ + tar xzf /backup/portainer-backup-pre-update.tar.gz -C /data + +# 4. Iniciar versión anterior +docker compose up -d +``` + +## Verificación de Backups + +### Test de Restauración + +Es crítico **probar tus backups regularmente**: + +```bash +# 1. Crear volumen de test +docker volume create portainer_data_test + +# 2. Restaurar backup en volumen de test +docker run --rm \ + -v portainer_data_test:/data \ + -v $(pwd):/backup \ + alpine \ + tar xzf /backup/portainer-backup-YYYYMMDD-HHMMSS.tar.gz -C /data + +# 3. Iniciar Portainer temporal en otro puerto +docker run -d \ + -p 19443:9443 \ + --name portainer-test \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v portainer_data_test:/data \ + portainer/portainer-ce:lts + +# 4. Verificar en https://localhost:19443 +# Login y verificar que los datos son correctos + +# 5. Limpiar +docker stop portainer-test +docker rm portainer-test +docker volume rm portainer_data_test +``` + +### Validar Integridad de Backup + +```bash +# Verificar que el tar.gz no está corrupto +tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz > /dev/null +echo $? # Debe devolver 0 si OK + +# Ver contenido del backup +tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz | head -20 + +# Ver tamaño +du -h portainer-backup-YYYYMMDD-HHMMSS.tar.gz +``` + +## Best Practices + +### 1. Estrategia 3-2-1 + +- ✅ **3 copias** de tus datos (original + 2 backups) +- ✅ **2 medios diferentes** (ej: disco local + NAS) +- ✅ **1 copia offsite** (ej: cloud, otro datacenter) + +### 2. Frecuencia de Backups + +Según criticidad: + +| Entorno | Frecuencia Recomendada | +|---------|------------------------| +| Producción crítica | Cada 6-12 horas | +| Producción estándar | Diario | +| Desarrollo/Testing | Semanal | + +### 3. Retención + +Ejemplo de política: + +- **Diarios**: 7 días +- **Semanales**: 4 semanas +- **Mensuales**: 12 meses +- **Anuales**: 3 años + +Script de retención: + +```bash +# Diarios (últimos 7) +find /backups -name "portainer-backup-*.tar.gz" -mtime +7 -mtime -30 -delete + +# Mantener un backup semanal (domingos) +# Mantener un backup mensual (día 1) +# (implementar lógica adicional según necesidades) +``` + +### 4. Encriptación de Backups + +Para backups con datos sensibles: + +```bash +# Crear backup encriptado con GPG +BACKUP_FILE="portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz" + +docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf "/backup/$BACKUP_FILE" -C /data . + +# Encriptar +gpg --symmetric --cipher-algo AES256 "$BACKUP_FILE" + +# Resultado: portainer-backup-YYYYMMDD-HHMMSS.tar.gz.gpg +rm "$BACKUP_FILE" # Eliminar versión sin encriptar +``` + +Restaurar encriptado: + +```bash +# Desencriptar +gpg --decrypt portainer-backup-YYYYMMDD-HHMMSS.tar.gz.gpg > portainer-backup.tar.gz + +# Restaurar normalmente +docker run --rm \ + -v portainer_data:/data \ + -v $(pwd):/backup \ + alpine \ + tar xzf /backup/portainer-backup.tar.gz -C /data +``` + +### 5. Monitorización de Backups + +Script con notificaciones: + +```bash +#!/bin/bash +# backup-portainer-monitored.sh + +BACKUP_DIR="/var/backups/portainer" +WEBHOOK_URL="https://hooks.slack.com/services/TU_WEBHOOK" # O email, etc. + +# ... (lógica de backup) ... + +# Notificar resultado +if [ $? -eq 0 ]; then + curl -X POST "$WEBHOOK_URL" \ + -H 'Content-Type: application/json' \ + -d "{\"text\":\"✅ Backup Portainer completado: $BACKUP_FILE\"}" +else + curl -X POST "$WEBHOOK_URL" \ + -H 'Content-Type: application/json' \ + -d "{\"text\":\"❌ ERROR: Backup Portainer falló\"}" +fi +``` + +## Troubleshooting + +### Error: "Permission denied" + +```bash +# Ejecutar backup con sudo +sudo docker run --rm \ + -v portainer_data:/data:ro \ + -v $(pwd):/backup \ + alpine \ + tar czf /backup/portainer-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data . +``` + +### Backup Muy Grande + +```bash +# Ver tamaño del volumen +docker run --rm \ + -v portainer_data:/data \ + alpine \ + du -sh /data + +# Limpiar logs/cache dentro del volumen si es necesario +docker run --rm \ + -v portainer_data:/data \ + alpine \ + sh -c "find /data -name '*.log' -delete" +``` + +### Restauración No Funciona + +```bash +# Verificar contenido del backup +tar tzf portainer-backup-YYYYMMDD-HHMMSS.tar.gz | less + +# Listar contenido del volumen restaurado +docker run --rm \ + -v portainer_data:/data \ + alpine \ + ls -laR /data + +# Verificar permisos +docker run --rm \ + -v portainer_data:/data \ + alpine \ + chown -R root:root /data +``` + +--- + +**Recursos adicionales**: +- [Documentación oficial de Portainer](https://docs.portainer.io/) +- [Docker Volume Backup Strategies](https://docs.docker.com/storage/volumes/) + +**Volver a**: [Página Principal](Home) | [Instalación Avanzada](Instalacion) diff --git a/Edge-Agents.md b/Edge-Agents.md new file mode 100644 index 0000000..689243b --- /dev/null +++ b/Edge-Agents.md @@ -0,0 +1,385 @@ +# Edge Agents + +Los **Edge Agents** permiten gestionar entornos Docker remotos que no tienen conectividad directa bidireccional con Portainer Server. Son ideales para: + +- Hosts detrás de firewalls o NAT +- Dispositivos IoT en ubicaciones remotas +- Entornos edge computing +- Sitios con conectividad limitada o intermitente + +## ¿Cómo Funcionan? + +A diferencia del Portainer Agent estándar (que requiere puerto 9001 accesible), el Edge Agent: + +1. **Inicia la conexión** hacia Portainer Server (puerto 8000) +2. **Mantiene un túnel** para comunicación bidireccional +3. **Polling periódico** cuando la conexión se pierde +4. **Modo async** para operaciones cuando está offline + +## Requisitos + +### En Portainer Server + +- ✅ Puerto **8000** expuesto y accesible desde Internet/red remota +- ✅ Dominio o IP pública (recomendado) +- ✅ Certificado SSL válido (recomendado para producción) + +### En el Host Remoto + +- ✅ Docker instalado +- ✅ Conectividad saliente a Portainer Server (puerto 8000) +- ✅ NO requiere puertos abiertos hacia el host remoto + +## Habilitar Edge en Portainer Server + +### 1. Exponer Puerto 8000 + +Edita `docker-compose.yaml` y descomenta el puerto 8000: + +```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 + ports: + - "9443:9443" + - "8000:8000" # ← Descomentar para Edge Agents + networks: + - portainer_network +``` + +### 2. Reiniciar Portainer + +```bash +docker compose down +docker compose up -d +``` + +### 3. Verificar Puerto + +```bash +# Verificar que el puerto está escuchando +sudo netstat -tulpn | grep :8000 +# o con ss +ss -tulpn | grep :8000 +``` + +### 4. Configurar Firewall + +```bash +# UFW (Ubuntu/Debian) +sudo ufw allow 8000/tcp + +# firewall-cmd (RHEL/CentOS/Fedora) +sudo firewall-cmd --permanent --add-port=8000/tcp +sudo firewall-cmd --reload + +# iptables +sudo iptables -A INPUT -p tcp --dport 8000 -j ACCEPT +sudo iptables-save > /etc/iptables/rules.v4 +``` + +## Desplegar Edge Agent en Host Remoto + +### Desde la Interfaz de Portainer + +1. **Ir a Environments**: + - Click en **Environments** en el menú lateral + - Click en **Add environment** + +2. **Seleccionar Tipo**: + - Selecciona **Docker Standalone** + - Click en **Start Wizard** + +3. **Elegir Edge Agent**: + - Selecciona la opción **Edge Agent** + - Elige tu sistema operativo (Linux / Windows WSL / Windows WCS) + +4. **Configurar Opciones**: + - **Name**: Nombre descriptivo del entorno (ej: `produccion-server1`) + - **Portainer server URL**: `https://portainer.tudominio.com` o `https://IP:9443` + - **Edge ID**: Se genera automáticamente + - **Polling interval**: Frecuencia de sincronización (por defecto 5 segundos) + +5. **Copiar Comando**: + + Portainer generará un comando similar a este: + + **Linux / WSL**: + ```bash + docker run -d \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /var/lib/docker/volumes:/var/lib/docker/volumes \ + -v /:/host \ + -v portainer_agent_data:/data \ + --restart always \ + -e EDGE=1 \ + -e EDGE_ID= \ + -e EDGE_KEY= \ + -e EDGE_INSECURE_POLL=0 \ + --name portainer_edge_agent \ + portainer/agent:latest + ``` + + **Windows WCS**: + ```powershell + docker run -d ` + -v \\.\pipe\docker_engine:\\.\pipe\docker_engine ` + -v portainer_agent_data:C:\ProgramData\Portainer ` + --restart always ` + -e EDGE=1 ` + -e EDGE_ID= ` + -e EDGE_KEY= ` + --name portainer_edge_agent ` + portainer/agent:latest + ``` + +6. **Ejecutar en Host Remoto**: + - Conéctate por SSH al host remoto + - Pega y ejecuta el comando + - Espera a que el contenedor se descargue e inicie + +### Verificar Conexión + +En el host remoto: + +```bash +# Ver logs del Edge Agent +docker logs portainer_edge_agent + +# Deberías ver mensajes como: +# [INFO] Edge agent started +# [INFO] Polling Portainer server +# [INFO] Successfully connected to Portainer server +``` + +En Portainer Server: + +1. Ve a **Environments** +2. El nuevo entorno debería aparecer con estado **Connected** (punto verde) +3. Click en el entorno para gestionarlo + +## Configuración Avanzada + +### Intervalo de Polling Personalizado + +```bash +docker run -d \ + # ... resto de opciones ... + -e EDGE_POLL_INTERVAL=10s \ # Cambiar intervalo (default: 5s) + portainer/agent:latest +``` + +⚠️ **Nota**: Intervalos muy cortos aumentan el tráfico de red. + +### Edge Agent con Host Management + +Para habilitar funciones de gestión del host (CPU, memoria, procesos): + +```bash +docker run -d \ + # ... resto de opciones ... + -v /:/host \ # Montar filesystem del host + portainer/agent:latest +``` + +### Modo Inseguro (Solo para Desarrollo) + +Si usas certificados autofirmados o HTTP: + +```bash +docker run -d \ + # ... resto de opciones ... + -e EDGE_INSECURE_POLL=1 \ # ⚠️ NO usar en producción + portainer/agent:latest +``` + +### Edge Agent con Docker Compose + +Crear `docker-compose.yaml` en el host remoto: + +```yaml +version: '3.8' + +services: + portainer_edge_agent: + image: portainer/agent:latest + container_name: portainer_edge_agent + restart: always + environment: + EDGE: "1" + EDGE_ID: "" + EDGE_KEY: "" + EDGE_INSECURE_POLL: "0" + EDGE_POLL_INTERVAL: "5s" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker/volumes:/var/lib/docker/volumes + - /:/host + - portainer_agent_data:/data + +volumes: + portainer_agent_data: +``` + +Desplegar: + +```bash +docker compose up -d +``` + +## Edge Groups y Tags + +### Crear Edge Group + +Los Edge Groups permiten agrupar múltiples entornos edge para gestión centralizada: + +1. **Ir a Edge Groups**: + - Menú lateral → **Edge Groups** + - Click **Add edge group** + +2. **Configurar Grupo**: + - **Name**: Nombre del grupo (ej: `iot-devices`) + - **Endpoints**: Seleccionar entornos edge a incluir + - **Tags**: Opcional, para filtrado avanzado + +3. **Deploy Stack a Grupo**: + - Puedes desplegar stacks en todos los entornos del grupo simultáneamente + - Los cambios se sincronizan automáticamente + +## Edge Stacks + +Los **Edge Stacks** son stacks Docker Compose que se despliegan en múltiples entornos edge: + +1. **Crear Edge Stack**: + - **Edge Compute** → **Edge Stacks** → **Add stack** + +2. **Configurar Stack**: + - **Name**: Nombre del stack + - **Edge groups**: Seleccionar grupos target + - **Compose file**: Pegar tu docker-compose.yaml + +3. **Deployment type**: + - **Static**: Se despliega una vez + - **Git**: Se sincroniza desde un repo Git + +4. **Pre-pull images**: Descargar imágenes antes de desplegar (recomendado) + +## Edge Jobs + +Ejecutar comandos en múltiples entornos edge: + +1. **Crear Edge Job**: + - **Edge Compute** → **Edge Jobs** → **Add edge job** + +2. **Opciones**: + - **Basic**: Comando simple + - **Advanced**: Scripts complejos + +3. **Scheduling**: + - **One-off**: Se ejecuta una vez + - **Recurring**: Programado (cron-like) + +Ejemplo: + +```bash +# Actualizar todos los contenedores en entornos edge +docker compose pull +docker compose up -d +``` + +## Troubleshooting + +### Edge Agent No Conecta + +1. **Verificar firewall en servidor**: + ```bash + sudo ufw status | grep 8000 + ``` + +2. **Verificar puerto 8000 accesible**: + Desde el host remoto: + ```bash + telnet 8000 + # o + nc -zv 8000 + ``` + +3. **Revisar logs**: + ```bash + docker logs portainer_edge_agent --tail 50 + ``` + +### Certificado SSL Inválido + +Si usas certificados autofirmados, usa `EDGE_INSECURE_POLL=1` (solo desarrollo): + +```bash +docker run -d \ + # ... resto de opciones ... + -e EDGE_INSECURE_POLL=1 \ + portainer/agent:latest +``` + +### Edge Agent Se Desconecta Frecuentemente + +1. **Aumentar timeout**: + ```bash + -e EDGE_POLL_TIMEOUT=30s + ``` + +2. **Verificar estabilidad de red**: + ```bash + ping -c 100 + ``` + +3. **Revisar recursos del host**: + ```bash + docker stats portainer_edge_agent + ``` + +### Actualizar Edge Agent + +```bash +# Detener y eliminar contenedor actual +docker stop portainer_edge_agent +docker rm portainer_edge_agent + +# Pull nueva imagen +docker pull portainer/agent:latest + +# Re-ejecutar comando de despliegue con las mismas variables EDGE_ID y EDGE_KEY +``` + +⚠️ **Importante**: No cambies `EDGE_ID` o `EDGE_KEY`, o necesitarás re-agregar el entorno en Portainer. + +## Seguridad + +### Recomendaciones + +1. ✅ **Usar HTTPS** con certificados válidos +2. ✅ **NO usar** `EDGE_INSECURE_POLL=1` en producción +3. ✅ **Limitar acceso** al puerto 8000 con firewall +4. ✅ **Rotar Edge Keys** periódicamente (re-deploy agent) +5. ✅ **Monitorizar logs** de conexiones sospechosas + +### Exponer Solo con VPN (Alternativa Segura) + +Si no quieres exponer el puerto 8000 a Internet: + +1. **Configurar VPN** (WireGuard, OpenVPN, Tailscale) +2. **Conectar hosts remotos** a la VPN +3. **Configurar Portainer Server URL** con IP privada de VPN +4. **Edge Agents** conectan a través del túnel VPN + +--- + +**Recursos adicionales**: +- [Documentación oficial Edge Compute](https://docs.portainer.io/admin/edge-compute) +- [Edge Agent en GitHub](https://github.com/portainer/agent) + +**Volver a**: [Página Principal](Home) | [Instalación Avanzada](Instalacion) diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..b66b802 --- /dev/null +++ b/Home.md @@ -0,0 +1,104 @@ +# Portainer CE - Documentación + +Bienvenido a la documentación del despliegue de **Portainer Community Edition** usando Docker Compose. + +## ¿Qué es Portainer? + +Portainer es una plataforma de gestión de contenedores ligera y fácil de usar que te permite administrar tus entornos Docker, Kubernetes, y más a través de una interfaz web intuitiva. + +## Componentes del Stack + +Este repositorio despliega **Portainer Server** con la siguiente configuración: + +### Servicio Principal +- **Imagen**: `portainer/portainer-ce:lts` +- **Contenedor**: `portainer` +- **Reinicio**: Automático (`always`) + +### Puertos Expuestos +- **9443**: Interfaz web HTTPS de Portainer (obligatorio) +- **8000**: Túnel TCP para Edge Agents (opcional, no incluido por defecto) + +### Volúmenes +- `/var/run/docker.sock:/var/run/docker.sock` - Socket Docker para gestión del host +- `portainer_data:/data` - Almacenamiento persistente de configuración y datos + +### Red +- `portainer_network` - Red dedicada para el stack + +## Requisitos Previos + +Antes de desplegar Portainer, asegúrate de tener: + +- ✅ Docker Engine instalado (versión compatible según [requisitos oficiales](https://docs.portainer.io/start/requirements-and-prerequisites)) +- ✅ Docker Compose instalado +- ✅ Usuario con permisos para acceder a `/var/run/docker.sock` +- ✅ Puertos 9443 (y opcionalmente 8000) disponibles +- ✅ SELinux deshabilitado (Linux) o usar flag `--privileged` si es necesario + +## Despliegue Rápido + +### 1. Clonar el Repositorio + +```bash +git clone https://git.ictiberia.com/groales/portainer +cd portainer +``` + +### 2. Revisar Configuración (Opcional) + +Edita `docker-compose.yaml` si necesitas personalizar puertos, redes o volúmenes. + +### 3. Levantar el Stack + +```bash +docker compose up -d +``` + +### 4. Verificar el Estado + +```bash +docker ps --filter name=portainer +``` + +Deberías ver el contenedor `portainer` en estado `Up`. + +### 5. Acceder a la Interfaz Web + +Abre tu navegador en: + +``` +https://:9443 +``` + +🔐 **Primera vez**: Portainer te pedirá crear un usuario administrador. + +⚠️ **Certificado SSL**: Por defecto, Portainer usa un certificado autofirmado. Tu navegador mostrará una advertencia de seguridad. Para producción, configura certificados válidos (ver [Configuración SSL](#)). + +## Próximos Pasos + +- 📖 [Instalación Avanzada](Instalacion) - Configuración de TLS, variables de entorno y opciones avanzadas +- 💾 [Backup y Restauración](Backup) - Cómo respaldar y restaurar datos de Portainer +- 🌐 [Integración con Traefik](Traefik) - Configurar proxy inverso con TLS automático +- 🔌 [Edge Agents](Edge-Agents) - Gestionar entornos remotos con agentes Edge + +## Solución Rápida de Problemas + +| Problema | Solución | +|----------|----------| +| Puerto 9443 ocupado | Cambia el puerto en `docker-compose.yaml`: `- "XXXX:9443"` | +| Contenedor no arranca | Revisa logs: `docker logs portainer` | +| No se puede conectar | Verifica firewall y que Docker esté corriendo | +| Error de permisos socket | Añade tu usuario al grupo `docker`: `sudo usermod -aG docker $USER` | + +## Recursos Oficiales + +- 📘 [Documentación Oficial](https://docs.portainer.io/) +- 🏠 [Sitio Web Portainer](https://www.portainer.io/) +- 💬 [Comunidad](https://www.portainer.io/community) +- 🐛 [Reportar Issues](https://github.com/portainer/portainer/issues) + +--- + +**Versión**: Portainer CE LTS +**Última actualización**: Noviembre 2025 diff --git a/Instalacion.md b/Instalacion.md new file mode 100644 index 0000000..7cdd6d1 --- /dev/null +++ b/Instalacion.md @@ -0,0 +1,263 @@ +# Instalación Avanzada + +Esta página cubre opciones avanzadas de instalación y configuración para Portainer CE. + +## Configuración con Variables de Entorno + +Puedes usar un archivo `.env` para gestionar variables de configuración. Crea el archivo en la raíz del proyecto: + +```bash +# .env +PORTAINER_HTTPS_PORT=9443 +PORTAINER_EDGE_PORT=8000 +PORTAINER_DATA_VOLUME=portainer_data +PORTAINER_NETWORK=portainer_network +``` + +Luego referencia estas variables en `docker-compose.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_VOLUME:-portainer_data}:/data + ports: + - "${PORTAINER_HTTPS_PORT:-9443}:9443" + # - "${PORTAINER_EDGE_PORT:-8000}:8000" # Descomenta para Edge Agents + networks: + - ${PORTAINER_NETWORK:-portainer_network} +``` + +## Configuración de Certificados SSL/TLS + +### Opción 1: Certificado Autofirmado (Por Defecto) + +Portainer genera automáticamente un certificado autofirmado al iniciar. No requiere configuración adicional, pero los navegadores mostrarán advertencias de seguridad. + +### Opción 2: Certificados Propios + +Para usar tus propios certificados SSL: + +1. **Prepara tus certificados**: + - `cert.pem` - Certificado público + - `key.pem` - Clave privada + +2. **Crea una carpeta para certificados**: + ```bash + mkdir -p ./certs + cp /ruta/a/tu/cert.pem ./certs/ + cp /ruta/a/tu/key.pem ./certs/ + chmod 600 ./certs/*.pem + ``` + +3. **Modifica docker-compose.yaml**: + ```yaml + services: + portainer: + # ... configuración existente ... + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + - ./certs:/certs:ro + command: --sslcert /certs/cert.pem --sslkey /certs/key.pem + ``` + +4. **Reinicia Portainer**: + ```bash + docker compose down + docker compose up -d + ``` + +### Opción 3: Proxy Inverso con Let's Encrypt + +La forma más profesional es usar un proxy inverso como Traefik o Nginx con certificados Let's Encrypt. Ver [Integración con Traefik](Traefik). + +## Habilitar Edge Agents + +Los Edge Agents permiten gestionar entornos Docker remotos que no tienen conectividad directa con Portainer Server. + +### 1. Exponer Puerto 8000 + +Edita `docker-compose.yaml` y descomenta la línea del puerto 8000: + +```yaml +ports: + - "9443:9443" + - "8000:8000" # ← Descomentar esta línea +``` + +### 2. Configurar Firewall + +Asegúrate de que el puerto 8000 esté accesible desde tus agentes remotos: + +```bash +# Ejemplo con UFW (Ubuntu) +sudo ufw allow 8000/tcp + +# Ejemplo con firewall-cmd (RHEL/CentOS) +sudo firewall-cmd --permanent --add-port=8000/tcp +sudo firewall-cmd --reload +``` + +### 3. Desplegar Edge Agent + +Desde la interfaz de Portainer: +1. Ve a **Environments** → **Add environment** +2. Selecciona **Docker Standalone** +3. Elige **Edge Agent** +4. Copia el comando de instalación y ejecútalo en el host remoto + +📖 Más información: [Documentación oficial de Edge Agents](https://docs.portainer.io/admin/environments/add/docker/edge) + +## Configuración de SELinux + +Si usas SELinux en Linux, necesitas ejecutar Portainer con el flag `--privileged`: + +```yaml +services: + portainer: + # ... configuración existente ... + privileged: true +``` + +O configurar políticas SELinux específicas (recomendado para producción): + +```bash +sudo semanage fcontext -a -t svirt_sandbox_file_t "/var/lib/docker/volumes/portainer_data(/.*)?" +sudo restorecon -R /var/lib/docker/volumes/portainer_data +``` + +## Docker Rootless + +Portainer puede ejecutarse con Docker rootless, pero con algunas limitaciones: + +1. **Montar socket rootless**: + ```yaml + volumes: + - $XDG_RUNTIME_DIR/docker.sock:/var/run/docker.sock + ``` + +2. **Limitaciones conocidas**: + - No se puede gestionar el host (stats, eventos del sistema) + - Algunas funciones de networking pueden no funcionar + - Host management features deshabilitadas + +📖 Más información: [Docker Rootless](https://docs.docker.com/engine/security/rootless/) + +## Despliegue con Docker Run + +Si prefieres no usar Docker Compose: + +```bash +# Crear volumen +docker volume create portainer_data + +# Ejecutar Portainer +docker run -d \ + -p 9443:9443 \ + --name portainer \ + --restart=always \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v portainer_data:/data \ + portainer/portainer-ce:lts +``` + +## Configuración de Red Avanzada + +### Usar Red Externa + +Si ya tienes una red Docker existente: + +```yaml +networks: + portainer_network: + external: true + name: mi_red_existente +``` + +### IPv6 + +Para habilitar IPv6: + +```yaml +networks: + portainer_network: + enable_ipv6: true + ipam: + config: + - subnet: "fd00::/64" +``` + +## Limitar Recursos + +Para limitar CPU y memoria de Portainer: + +```yaml +services: + portainer: + # ... configuración existente ... + deploy: + resources: + limits: + cpus: '1.0' + memory: 512M + reservations: + cpus: '0.5' + memory: 256M +``` + +## Configuración de Logging + +Personalizar el driver de logs: + +```yaml +services: + portainer: + # ... configuración existente ... + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" +``` + +## Troubleshooting Avanzado + +### Logs Detallados + +Habilitar modo debug: + +```yaml +services: + portainer: + # ... configuración existente ... + command: --log-level=DEBUG +``` + +### Verificar Conectividad al Socket Docker + +```bash +# Desde dentro del contenedor +docker exec -it portainer ls -la /var/run/docker.sock + +# Verificar permisos +docker exec -it portainer stat -c '%a %U:%G' /var/run/docker.sock +``` + +### Reset de Admin Password + +Si olvidaste la contraseña del admin: + +```bash +docker stop portainer +docker run --rm -v portainer_data:/data portainer/helper-reset-password +docker start portainer +``` + +--- + +**Próximos pasos**: [Backup y Restauración](Backup) | [Integración con Traefik](Traefik) diff --git a/Traefik.md b/Traefik.md new file mode 100644 index 0000000..90f75f1 --- /dev/null +++ b/Traefik.md @@ -0,0 +1,549 @@ +# 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 +- 📊 **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) + +## Arquitectura + +``` +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 Básica + +### 1. Crear Red Compartida + +Si no existe, crear una red para que Traefik y Portainer se comuniquen: + +```bash +docker network create traefik_network +``` + +### 2. Modificar docker-compose.yaml de Portainer + +Opción recomendada: usar `docker-compose.override.yaml` (ver abajo). + +O editar directamente `docker-compose.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 + 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 + - "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 + +networks: + portainer_network: + name: portainer_network + traefik_network: + external: true +``` + +### 3. Usar docker-compose.override.yaml (Recomendado) + +En el repositorio ya existe `docker-compose.override.yaml.example`. Copiarlo: + +```bash +cp docker-compose.override.yaml.example docker-compose.override.yaml +``` + +Editar `docker-compose.override.yaml`: + +```yaml +services: + portainer: + networks: + - traefik_network + labels: + - "traefik.enable=true" + - "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" + - "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" + - "traefik.http.services.portainer.loadbalancer.server.port=9443" + - "traefik.http.services.portainer.loadbalancer.server.scheme=https" + - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" + - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" + +networks: + traefik_network: + external: true +``` + +**Ventaja**: El `docker-compose.yaml` base permanece sin cambios, y los overrides se aplican automáticamente. + +### 4. Reiniciar Portainer + +```bash +docker compose down +docker compose up -d +``` + +### 5. Verificar + +```bash +# Ver logs de Traefik +docker logs traefik + +# Verificar que Portainer está en la red de Traefik +docker network inspect traefik_network +``` + +Acceder a: `https://portainer.tudominio.com` + +## Configuración de Traefik + +### traefik.yml Mínimo + +Si aún no tienes Traefik configurado, aquí un ejemplo básico: + +```yaml +# traefik.yml +api: + dashboard: true + insecure: false + +entryPoints: + web: + address: ":80" + http: + redirections: + entryPoint: + to: websecure + scheme: https + websecure: + address: ":443" + +providers: + docker: + endpoint: "unix:///var/run/docker.sock" + exposedByDefault: false + network: traefik_network + +certificatesResolvers: + letsencrypt: + acme: + email: admin@tudominio.com + storage: /letsencrypt/acme.json + httpChallenge: + entryPoint: web +``` + +### docker-compose.yml de Traefik + +```yaml +version: '3.8' + +services: + traefik: + image: traefik:latest + container_name: traefik + restart: always + ports: + - "80:80" + - "443:443" + - "8080:8080" # Dashboard (proteger en producción) + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./traefik.yml:/traefik.yml:ro + - ./letsencrypt:/letsencrypt + networks: + - traefik_network + labels: + # Dashboard (opcional, configurar autenticación) + - "traefik.enable=true" + - "traefik.http.routers.traefik.rule=Host(`traefik.tudominio.com`)" + - "traefik.http.routers.traefik.entrypoints=websecure" + - "traefik.http.routers.traefik.tls=true" + - "traefik.http.routers.traefik.tls.certresolver=letsencrypt" + - "traefik.http.routers.traefik.service=api@internal" + +networks: + traefik_network: + external: true +``` + +Iniciar Traefik: + +```bash +docker network create traefik_network +mkdir letsencrypt +touch letsencrypt/acme.json +chmod 600 letsencrypt/acme.json + +docker compose up -d +``` + +## Configuración Avanzada + +### Autenticación Básica (Opcional) + +Proteger Portainer con autenticación HTTP básica: + +```bash +# Generar password hash +echo $(htpasswd -nb admin tu_password) | sed -e s/\\$/\\$\\$/g +# Resultado: admin:$$apr1$$... +``` + +Añadir labels: + +```yaml +labels: + # ... labels existentes ... + - "traefik.http.routers.portainer.middlewares=portainer-auth" + - "traefik.http.middlewares.portainer-auth.basicauth.users=admin:$$apr1$$..." +``` + +### Headers de Seguridad + +```yaml +labels: + # ... labels existentes ... + - "traefik.http.routers.portainer.middlewares=security-headers" + - "traefik.http.middlewares.security-headers.headers.stsSeconds=31536000" + - "traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true" + - "traefik.http.middlewares.security-headers.headers.stsPreload=true" + - "traefik.http.middlewares.security-headers.headers.forceSTSHeader=true" + - "traefik.http.middlewares.security-headers.headers.frameDeny=true" + - "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true" + - "traefik.http.middlewares.security-headers.headers.browserXssFilter=true" +``` + +### Rate Limiting + +Limitar peticiones para prevenir abusos: + +```yaml +labels: + # ... labels existentes ... + - "traefik.http.routers.portainer.middlewares=rate-limit" + - "traefik.http.middlewares.rate-limit.ratelimit.average=100" + - "traefik.http.middlewares.rate-limit.ratelimit.burst=50" +``` + +### IP Whitelist + +Restringir acceso solo desde IPs específicas: + +```yaml +labels: + # ... labels existentes ... + - "traefik.http.routers.portainer.middlewares=ip-whitelist" + - "traefik.http.middlewares.ip-whitelist.ipwhitelist.sourcerange=192.168.1.0/24,10.0.0.0/8" +``` + +### Múltiples Dominios + +Acceder a Portainer desde varios dominios: + +```yaml +labels: + - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`) || Host(`docker.tudominio.com`)" +``` + +### Configuración con Subdirectorio + +Acceder en `https://tudominio.com/portainer`: + +```yaml +labels: + - "traefik.http.routers.portainer.rule=Host(`tudominio.com`) && PathPrefix(`/portainer`)" + - "traefik.http.routers.portainer.middlewares=portainer-stripprefix" + - "traefik.http.middlewares.portainer-stripprefix.stripprefix.prefixes=/portainer" +``` + +⚠️ **Nota**: Portainer puede tener problemas con subdirectorios. Recomendamos usar subdominios. + +## Wildcard Certificates + +Para certificados wildcard con DNS challenge: + +```yaml +# traefik.yml +certificatesResolvers: + letsencrypt: + acme: + email: admin@tudominio.com + storage: /letsencrypt/acme.json + dnsChallenge: + provider: cloudflare # O tu proveedor DNS + delayBeforeCheck: 30 +``` + +Variables de entorno para Cloudflare: + +```yaml +# docker-compose.yml de Traefik +services: + traefik: + environment: + - CF_API_EMAIL=tu@email.com + - CF_API_KEY=tu_api_key +``` + +Labels en Portainer: + +```yaml +labels: + - "traefik.http.routers.portainer.tls.domains[0].main=tudominio.com" + - "traefik.http.routers.portainer.tls.domains[0].sans=*.tudominio.com" +``` + +## Docker Compose Completo + +### Portainer con Traefik + +Archivo completo `docker-compose.override.yaml`: + +```yaml +version: '3.8' + +services: + portainer: + networks: + - traefik_network + labels: + # Habilitar Traefik + - "traefik.enable=true" + + # Dominio + - "traefik.http.routers.portainer.rule=Host(`portainer.tudominio.com`)" + + # Entrypoints + - "traefik.http.routers.portainer.entrypoints=websecure" + + # TLS + - "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" + + # Middlewares (opcional) + - "traefik.http.routers.portainer.middlewares=security-headers" + - "traefik.http.middlewares.security-headers.headers.stsSeconds=31536000" + - "traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true" + - "traefik.http.middlewares.security-headers.headers.frameDeny=true" + - "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true" + - "traefik.http.middlewares.security-headers.headers.browserXssFilter=true" + +networks: + traefik_network: + external: true +``` + +## Troubleshooting + +### Certificado No Se Genera + +1. **Verificar logs de Traefik**: + ```bash + docker logs traefik | grep -i error + ``` + +2. **Revisar permisos de acme.json**: + ```bash + chmod 600 letsencrypt/acme.json + ``` + +3. **Verificar DNS**: + ```bash + nslookup portainer.tudominio.com + dig portainer.tudominio.com + ``` + +4. **Rate limits de Let's Encrypt**: + - Máximo 5 certificados por semana por dominio + - Usar staging durante pruebas: + ```yaml + certificatesResolvers: + letsencrypt: + acme: + caServer: https://acme-staging-v02.api.letsencrypt.org/directory + ``` + +### Error 502 Bad Gateway + +1. **Verificar que Portainer está corriendo**: + ```bash + docker ps | grep portainer + ``` + +2. **Verificar red compartida**: + ```bash + docker network inspect traefik_network | grep portainer + ``` + +3. **Revisar puerto del servicio**: + ```yaml + # Asegurarse de usar el puerto interno correcto + - "traefik.http.services.portainer.loadbalancer.server.port=9443" + ``` + +4. **Verificar scheme HTTPS**: + ```yaml + - "traefik.http.services.portainer.loadbalancer.server.scheme=https" + ``` + +### Redirección Infinita + +Si hay loop de redirecciones: + +```yaml +labels: + # Remover redirección HTTP si Traefik ya lo maneja globalmente + # Comentar estas líneas: + # - "traefik.http.routers.portainer-http.rule=..." + # - "traefik.http.routers.portainer-http.middlewares=redirect-to-https" +``` + +### Certificado Autofirmado Aún Se Muestra + +Portainer usa su propio certificado SSL. Traefik termina SSL antes de llegar a Portainer, por lo que: + +1. **Es normal** que Portainer siga usando su cert autofirmado internamente +2. El usuario final ve el certificado de Let's Encrypt de Traefik +3. Traefik se comunica con Portainer por HTTPS (con cert autofirmado) + +Si quieres evitar warnings en logs de Traefik: + +```yaml +labels: + - "traefik.http.services.portainer.loadbalancer.server.scheme=https" + - "traefik.http.services.portainer.loadbalancer.serversTransport=ignorecert" + + # En traefik.yml: + # http: + # serversTransports: + # ignorecert: + # insecureSkipVerify: true +``` + +## Monitorización + +### Logs de Traefik + +```bash +# Ver requests a Portainer +docker logs -f traefik | grep portainer + +# Ver errores TLS +docker logs traefik | grep -i "tls\|certificate" +``` + +### Verificar Certificado SSL + +```bash +# Ver información del certificado +echo | openssl s_client -servername portainer.tudominio.com -connect localhost:443 2>/dev/null | openssl x509 -noout -dates + +# Verificar desde exterior +curl -vI https://portainer.tudominio.com 2>&1 | grep -i "SSL\|certificate" +``` + +## Seguridad Adicional + +### 1. Fail2ban con Traefik + +Proteger contra brute-force: + +```bash +# /etc/fail2ban/filter.d/traefik-auth.conf +[Definition] +failregex = ^ - - .* "(GET|POST|HEAD).*HTTP.*" 401 .*$ +ignoreregex = +``` + +```ini +# /etc/fail2ban/jail.local +[traefik-auth] +enabled = true +port = http,https +logpath = /var/log/traefik/access.log +maxretry = 5 +bantime = 3600 +``` + +### 2. Autenticación de Dos Factores + +Portainer tiene 2FA integrado (no depende de Traefik): + +1. **Settings** → **Authentication** +2. Habilitar **OAuth** o **LDAP** con 2FA +3. O usar middleware de Traefik con OAuth2 Proxy + +### 3. VPN como Alternativa + +Para máxima seguridad, no exponer Portainer a Internet: + +1. Acceso solo via VPN (WireGuard, OpenVPN) +2. Traefik escucha solo en IP privada +3. Usuarios conectan primero a VPN + +--- + +**Recursos adicionales**: +- [Documentación Traefik](https://doc.traefik.io/traefik/) +- [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)