Files
Proxmox-Coolify-Manager/docs/issue-coolify-static-app-deploy.md
urieljareth f587a8baa2 Agrega scripts y runbooks: Cloudflare API, autostart Coolify, parche Chatwoot, deploy Solo Leveling + docs de casos
- scripts/Invoke-CloudflareApi.ps1: control de tunnel/DNS via API
- scripts/Install-CoolifyAutostart.ps1 + scripts/host/: autostart de LXC 102 + tunnel tras corte
- scripts/Apply-ChatwootEnterprisePatch.ps1: parche enterprise (autodetecta creds)
- Deploy-SoloLeveling.ps1: deploy build-on-server verificado
- docs/runbooks/cloudflare-tunnel.md y autostart-coolify.md
- docs/casos/chatwoot-enterprise-patch.md (credenciales redactadas)
- docs/AGENTS-coolify-apps.md + issues y reportes
- deploy_skill/references/coolify-4.1.2-notes.md: hallazgos verificados (seccion 7)
- package.json para verify-online.mjs del coolify-deploy skill
- .gitignore: excluye .claude/ y .opencode/ (config local de herramientas)
2026-07-18 11:31:31 -06:00

170 lines
6.8 KiB
Markdown

# Issue: Despliegue de App Estática en Coolify — Página en Blanco y 502
**Fecha:** 2026-04-11
**Entorno:** Coolify v4.0.0-beta.472 — Proxmox LXC CT 102 — Cloudflare Tunnel
**Estado:** Resuelto ✅
---
## Síntomas
- Al crear una app desde GitHub y dar clic en **Continue**, la UI redirige a una URL como:
`coolify.urieljareth.org/project/{uuid}/environment/{uuid}/application/{uuid}`
y muestra **página en blanco** o **HTTP 404**.
- Al hacer clic en una app existente desde la lista de proyectos, también carga en blanco.
- El dominio de la app desplegada devuelve **502 Bad Gateway** desde Cloudflare.
---
## Causas Raíz (múltiples)
### 1. Regla del Cloudflare Tunnel capturaba rutas de la UI incorrectamente
La ruta `/app/*` del tunnel (usada para websockets del puerto 6001) hacía match parcial con `/application/...` porque Cloudflare evalúa prefijos. Cualquier URL con `/application/` en el path era enviada al puerto 6001 (websocket) en lugar del puerto 8000 (Coolify UI).
**Solución:** Agregar una regla explícita `/project/*` antes de `/app/*` para que las rutas de la UI de Coolify sean enrutadas correctamente al puerto 8000.
### 2. Certificados SSL fallaban por "Always Use HTTPS" en Cloudflare
Let's Encrypt valida dominios por HTTP (`/.well-known/acme-challenge/`). Con "Usar siempre HTTPS" activo en Cloudflare, esas solicitudes eran redirigidas a HTTPS antes de llegar a Traefik, causando error 502 en la validación y rate limit 429.
**Solución:** Configurar Traefik para usar **DNS Challenge via API de Cloudflare** en lugar de HTTP Challenge. Esto elimina la dependencia de validación HTTP para siempre.
### 3. Puerto incorrecto en etiquetas de Traefik
Coolify asignaba puerto 3000 por defecto a apps nuevas. Las apps nginx escuchan en puerto 80. Traefik enviaba tráfico al 3000 y obtenía 502.
**Solución:** Actualizar `ports_exposes` en la base de datos a `80` antes del primer deploy.
### 4. Dominio UUID autogenerado
Coolify genera un UUID como subdominio cuando no detecta el dominio durante la creación. Esos subdominios UUID no tienen registro DNS y no funcionan.
**Solución:** Actualizar `fqdn` en la base de datos inmediatamente después de crear la app.
---
## Solución Permanente
### Paso 1 — Configurar DNS Challenge en Traefik
Crear token de API en Cloudflare con permisos `Zona → DNS → Editar` para `urieljareth.org`.
Editar `/data/coolify/proxy/docker-compose.yml`:
```yaml
environment:
- CF_DNS_API_TOKEN=<token>
command:
# Reemplazar httpchallenge por dnschallenge:
- '--certificatesresolvers.letsencrypt.acme.dnschallenge=true'
- '--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare'
- '--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53'
- '--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json'
```
Limpiar certificados anteriores y reiniciar:
```bash
echo '{}' > /data/coolify/proxy/acme.json && chmod 600 /data/coolify/proxy/acme.json
docker compose -f /data/coolify/proxy/docker-compose.yml up -d --force-recreate
```
### Paso 2 — Configurar rutas del Cloudflare Tunnel
Orden correcto en **Zero Trust → Networks → Tunnels → coolify-tunnel → Rutas de aplicación publicada:**
| # | Dominio | Ruta | Servicio | Notas |
|---|---------|------|---------|-------|
| 1 | coolify.urieljareth.org | /build/* | http://192.168.0.117:8000 | Build logs |
| 2 | coolify.urieljareth.org | /project/* | http://192.168.0.117:8000 | **Crítico: UI de apps** |
| 3 | coolify.urieljareth.org | /app/* | http://192.168.0.117:6001 | Websocket realtime |
| 4 | coolify.urieljareth.org | /terminal/ws* | http://192.168.0.117:6002 | Terminal websocket |
| 5 | coolify.urieljareth.org | * | http://192.168.0.117:8000 | Catch-all Coolify |
| 6 | *.urieljareth.org | * | https://192.168.0.117:443 | Apps via Traefik |
> ⚠️ La regla `/project/*` en posición 2 es crítica. Sin ella, `/application/...` es capturada por `/app/*` y la UI falla.
---
## Flujo de Trabajo para Nuevas Apps (mientras dure el bug de UI)
Debido a un bug de Coolify beta.472, la UI de apps individuales no carga correctamente tras la creación. El flujo correcto es:
**1. Crear la app en la UI** (seleccionar repo, Build Pack: Static, continuar)
**2. Obtener el ID de la app recién creada:**
```bash
docker exec coolify-db psql -U coolify -d coolify \
-c "SELECT id, name, fqdn FROM applications ORDER BY id DESC LIMIT 3;"
```
**3. Actualizar dominio y puerto antes del deploy:**
```bash
docker exec coolify-db psql -U coolify -d coolify \
-c "UPDATE applications SET fqdn='https://miapp.urieljareth.org', ports_exposes='80' WHERE id=<ID>;"
```
**4. Hacer deploy via API:**
```bash
curl -X POST "http://localhost:8000/api/v1/deploy?uuid=<UUID>&force=false" \
-H "Authorization: Bearer <TOKEN>"
```
**5. Verificar que el puerto en el docker-compose generado sea 80:**
```bash
grep "server.port" /data/coolify/applications/<UUID>/docker-compose.yaml
```
Si sigue mostrando 3000, corregir manualmente:
```bash
sed -i 's/loadbalancer.server.port=3000/loadbalancer.server.port=80/g' \
/data/coolify/applications/<UUID>/docker-compose.yaml
sed -i 's/upstreams 3000/upstreams 80/g' \
/data/coolify/applications/<UUID>/docker-compose.yaml
docker compose -f /data/coolify/applications/<UUID>/docker-compose.yaml up -d --force-recreate
```
---
## Comandos de Diagnóstico
```bash
# Ver estado de todos los contenedores Coolify
docker ps --format "table {{.Names}}\t{{.Status}}" | grep coolify
# Ver logs de Traefik (certificados, errores)
docker logs coolify-proxy --tail 50 2>&1 | grep -i "error\|certificate\|acme"
# Ver logs del tunnel
docker logs cloudflared --tail 30
# Verificar etiquetas Traefik de una app
docker inspect <nombre-contenedor> | grep "server.port\|rule\|certresolver"
# Listar apps en la base de datos
docker exec coolify-db psql -U coolify -d coolify \
-c "SELECT id, name, fqdn, ports_exposes FROM applications;"
```
---
## Lecciones Aprendidas
| Problema | Causa | Solución |
|----------|-------|---------|
| UI página en blanco al abrir app | `/app/*` captura `/application/...` en Cloudflare | Agregar regla `/project/*` antes de `/app/*` |
| 502 en dominio de app | Traefik sin certificado SSL | DNS Challenge con token Cloudflare |
| 502 en dominio de app | Puerto 3000 en lugar de 80 | Actualizar `ports_exposes` en DB |
| UUID como subdominio | Dominio no configurado al crear | Actualizar `fqdn` en DB antes del deploy |
| Rate limit 429 de Let's Encrypt | Intentos fallidos de validación HTTP | DNS Challenge elimina la validación HTTP |
---
## Configuración de Referencia
**Archivo:** `/data/coolify/proxy/docker-compose.yml`
**Backup:** `/data/coolify/proxy/docker-compose.yml.bak`
**Certificados:** `/data/coolify/proxy/acme.json`
**Apps:** `/data/coolify/applications/<UUID>/docker-compose.yaml`