From 84a03ab386b083a15718e67ff9203b24cabf5b71 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Sun, 5 Oct 2025 04:01:15 -0600 Subject: [PATCH] que paso? --- .claude/settings.local.json | 0 .env.example | 0 .gitignore | 0 CLOUDFLARE.md | 291 ++++++++ README.md | 0 docker-compose.yml | 0 dynamic/middlewares.yml | 0 examples/existing-service.yml | 0 examples/whoami-service.yml | 0 planV1.md | 1274 +++++++++++++++++++++++++++++++++ traefik/traefik.yml | 0 11 files changed, 1565 insertions(+) mode change 100755 => 100644 .claude/settings.local.json mode change 100755 => 100644 .env.example mode change 100755 => 100644 .gitignore create mode 100644 CLOUDFLARE.md mode change 100755 => 100644 README.md mode change 100755 => 100644 docker-compose.yml mode change 100755 => 100644 dynamic/middlewares.yml mode change 100755 => 100644 examples/existing-service.yml mode change 100755 => 100644 examples/whoami-service.yml create mode 100644 planV1.md mode change 100755 => 100644 traefik/traefik.yml diff --git a/.claude/settings.local.json b/.claude/settings.local.json old mode 100755 new mode 100644 diff --git a/.env.example b/.env.example old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/CLOUDFLARE.md b/CLOUDFLARE.md new file mode 100644 index 0000000..d82186a --- /dev/null +++ b/CLOUDFLARE.md @@ -0,0 +1,291 @@ +# Traefik + Cloudflare Tunnel - Configuración + +Esta guía explica cómo funciona Traefik detrás de Cloudflare Tunnel y cómo obtener las IPs reales de los visitantes. + +## 🌐 Arquitectura + +``` +Internet → Cloudflare (SSL/DDoS) → Cloudflare Tunnel → Traefik (443) → Contenedores +``` + +## 📍 IPs Reales de Visitantes + +### ¿Cómo funciona? + +Cuando un usuario visita tu sitio: + +1. **Cloudflare recibe la conexión** y conoce la IP real del visitante +2. **Cloudflare envía la IP real en headers HTTP:** + - `CF-Connecting-IP`: IP real del cliente ✅ (más confiable) + - `X-Forwarded-For`: Cadena de proxies + - `X-Real-IP`: IP real (alternativa) +3. **Traefik lee estos headers** y los pasa a tus aplicaciones + +### Configuración aplicada + +Ya está configurado en `traefik/traefik.yml`: + +```yaml +entryPoints: + websecure: + forwardedHeaders: + trustedIPs: + - "173.245.48.0/20" # Rangos de IPs de Cloudflare + - "103.21.244.0/22" + # ... etc (23 rangos en total) +``` + +Esto le dice a Traefik: **"Confía en los headers de IPs que vienen de Cloudflare"** + +### ✅ Verificar que funciona + +1. **Inicia Traefik:** + ```bash + docker compose up -d + ``` + +2. **Verifica los logs de acceso:** + ```bash + docker compose logs traefik | grep "CF-Connecting-IP" + ``` + +3. **Deberías ver la IP real en los logs:** + ```json + { + "ClientAddr": "173.245.48.5:12345", // IP de Cloudflare + "headers": { + "CF-Connecting-IP": "187.123.45.67" // ← IP REAL del visitante + } + } + ``` + +## 🔍 Leer IP real desde tus aplicaciones + +### Node.js / Express + +```javascript +app.get('/', (req, res) => { + const realIP = req.headers['cf-connecting-ip'] + || req.headers['x-forwarded-for']?.split(',')[0] + || req.connection.remoteAddress; + + console.log('IP real del visitante:', realIP); +}); +``` + +### Python / Flask + +```python +from flask import Flask, request + +@app.route('/') +def index(): + real_ip = request.headers.get('CF-Connecting-IP') \ + or request.headers.get('X-Forwarded-For', '').split(',')[0] \ + or request.remote_addr + + print(f'IP real del visitante: {real_ip}') +``` + +### Go / Gin + +```go +func handler(c *gin.Context) { + realIP := c.GetHeader("CF-Connecting-IP") + if realIP == "" { + realIP = c.ClientIP() + } + + fmt.Printf("IP real del visitante: %s\n", realIP) +} +``` + +### PHP + +```php + /dev/null 2>&1 || { + echo "❌ Red 'principal' no existe" + exit 1 +} + +# Verificar contenedores backend +echo "🔍 Verificando backends..." +backends=( + "portainer" + "gitea" + "geo-ids" + "planilla-ui" + "planilla-api" + "planilla-mcp" + "whatsapp-router" + "repodructor" + "amigos-app" + "duplicati" + "radiusnucleo-node-1" +) + +for backend in "${backends[@]}"; do + docker ps --filter "name=$backend" --format "{{.Names}}" | grep -q "$backend" || { + echo "⚠️ Backend '$backend' no encontrado o detenido" + } +done + +# Crear estructura Traefik +echo "📁 Creando estructura de directorios..." +mkdir -p /srv/traefik/{config,certificates/interno.com,logs} +touch /srv/traefik/acme.json +chmod 600 /srv/traefik/acme.json + +# Copiar certificados +echo "🔐 Copiando certificados SSL..." +cp /srv/nginx-proxy-manager/data/custom_ssl/npm-1/fullchain.pem \ + /srv/traefik/certificates/interno.com/ +cp /srv/nginx-proxy-manager/data/custom_ssl/npm-1/privkey.pem \ + /srv/traefik/certificates/interno.com/ + +echo "✅ Pre-migration completa" +echo "" +echo "Próximos pasos:" +echo "1. Crear archivos de configuración de Traefik" +echo "2. Actualizar labels en docker-compose de cada stack" +echo "3. Ejecutar migration.sh" +``` + +### 7.2 Script de Migración + +```bash +#!/bin/bash +# migration.sh + +set -e + +echo "🚀 Iniciando migración NPM → Traefik" + +# Detener NPM +echo "🛑 Deteniendo NPM..." +cd /srv/nginx-proxy-manager +docker-compose down + +# Levantar Traefik +echo "🚀 Levantando Traefik..." +cd /srv/traefik +docker-compose up -d + +# Esperar a que Traefik esté listo +echo "⏳ Esperando a que Traefik esté listo..." +sleep 10 + +# Verificar Traefik +echo "✅ Verificando Traefik..." +docker logs traefik --tail 50 + +# Verificar dashboard +echo "🌐 Dashboard disponible en: https://traefik.interno.com" + +# Restart de cada stack para aplicar labels +echo "🔄 Reiniciando stacks con nuevas labels..." +stacks=( + "/srv/gitea" + "/srv/planilla" + "/srv/conversation-layer" + # ... más stacks +) + +for stack in "${stacks[@]}"; do + if [ -d "$stack" ]; then + echo " Reiniciando $stack..." + cd "$stack" + docker-compose up -d --force-recreate + fi +done + +echo "✅ Migración completa!" +echo "" +echo "Verificar:" +echo "1. Dashboard Traefik: https://traefik.interno.com" +echo "2. Logs: docker logs traefik -f" +echo "3. Probar cada dominio manualmente" +``` + +### 7.3 Script de Rollback + +```bash +#!/bin/bash +# rollback.sh + +set -e + +echo "⏪ Rollback a NPM" + +# Detener Traefik +echo "🛑 Deteniendo Traefik..." +cd /srv/traefik +docker-compose down + +# Levantar NPM +echo "🚀 Levantando NPM..." +cd /srv/nginx-proxy-manager +docker-compose up -d + +echo "✅ Rollback completo" +echo "NPM disponible en: http://Nginx.interno.com:81" +``` + +### 7.4 Script de Verificación + +```bash +#!/bin/bash +# verify-migration.sh + +domains=( + "portainer.interno.com" + "gitea.interno.com" + "geoids.interno.com" + "planilla.interno.com" + "musica.interno.com" + "nucleoriofrio.com" + "snatchgame.interno.com" + "amigos.nucleoriofrio.com" +) + +echo "🔍 Verificando dominios..." + +for domain in "${domains[@]}"; do + echo -n "Testing $domain... " + if curl -skI "https://$domain" | head -1 | grep -q "200\|301\|302"; then + echo "✅ OK" + else + echo "❌ FAIL" + fi +done + +echo "" +echo "Verificar manualmente:" +echo "1. Autenticación Authentik en geoids.interno.com" +echo "2. WebSocket en musica.interno.com" +echo "3. Multi-location en planilla.interno.com" +echo "4. API streaming en nucleoriofrio.com/api/chat/stream" +``` + +--- + +## 8. Tabla de Mapeo Completa + +### NPM → Traefik Equivalencias + +| Característica NPM | Equivalente Traefik | +|-------------------|---------------------| +| `proxy_pass` | `service.loadBalancer.server.url` | +| `server_name` | `router.rule=Host(...)` | +| `location /path` | `router.rule=PathPrefix(...)` + `priority` | +| `proxy_set_header` | `middleware.headers.customRequestHeaders` | +| `add_header` | `middleware.headers.customResponseHeaders` | +| `auth_request` | `middleware.forwardAuth` | +| `ssl_certificate` | `tls.certificates` o `tls.certResolver` | +| `include force-ssl.conf` | `entrypoint.http.redirections` | +| `proxy_buffering off` | `middleware.buffering` | +| `client_max_body_size` | `middleware.buffering.maxRequestBodyBytes` | +| `proxy_read_timeout` | `service.loadBalancer.responseForwarding.timeout` | +| `upstream` con múltiples IPs | `service.loadBalancer.servers` (array) | +| `map` para variables | Middlewares condicionales o dynamic config | +| `if` statements | No soportado directamente, usar priorities | +| `limit_req` | `middleware.rateLimit` | +| `access_log` | `accessLog` en traefik.yml | +| `error_log` | `log` en traefik.yml | + +--- + +## 9. Checklist de Migración + +### Antes de Migrar + +- [ ] Backup completo de NPM configs +- [ ] Backup de base de datos de NPM +- [ ] Copiar certificados SSL +- [ ] Verificar que todos los backends están en red `principal` +- [ ] Documentar configuraciones custom + +### Durante la Migración + +- [ ] Crear estructura de directorios de Traefik +- [ ] Configurar `traefik.yml` +- [ ] Crear middlewares comunes +- [ ] Crear configs dinámicas por servicio +- [ ] Actualizar docker-compose de cada stack con labels +- [ ] Detener NPM +- [ ] Levantar Traefik +- [ ] Verificar dashboard de Traefik + +### Después de Migrar + +- [ ] Probar cada dominio manualmente +- [ ] Verificar certificados SSL +- [ ] Verificar autenticación Authentik +- [ ] Verificar WebSockets +- [ ] Verificar multi-location routing +- [ ] Verificar streaming endpoints +- [ ] Monitorear logs de Traefik +- [ ] Configurar alertas (opcional) +- [ ] Actualizar documentación + +### En Caso de Problemas + +- [ ] Rollback a NPM +- [ ] Revisar logs de Traefik +- [ ] Verificar conectividad de red +- [ ] Verificar resolución DNS interna +- [ ] Verificar permisos de certificados + diff --git a/traefik/traefik.yml b/traefik/traefik.yml old mode 100755 new mode 100644