Actualiza toolkit operativo y documentación
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
# ISSUE: cloudflare-tunnel · routing · websocket-tls-handshake
|
||||
|
||||
**ID:** `cloudflare-tunnel_routing_websocket-tls-handshake`
|
||||
**Tags:** `cloudflare-tunnel` `routing` `websocket` `tls` `coolify` `terminal` `realtime` `6001` `6002`
|
||||
**Severidad:** Alta — terminal de Coolify inoperativa, websockets de la UI rotos
|
||||
**Fecha:** 2026-04-11
|
||||
|
||||
---
|
||||
|
||||
## Síntoma
|
||||
|
||||
- La terminal dentro de Coolify muestra `Terminal websocket connection lost`
|
||||
- La UI de Coolify se comporta de forma inestable (reconexiones constantes)
|
||||
- Los logs de `cloudflared` muestran:
|
||||
|
||||
```
|
||||
tls: first record does not look like a TLS handshake
|
||||
originService=https://192.168.0.117:6001
|
||||
|
||||
tls: first record does not look like a TLS handshake
|
||||
originService=https://192.168.0.117:6002
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Causa Raíz
|
||||
|
||||
Las rutas del Cloudflare Tunnel para los puertos 6001 (realtime/websocket) y 6002 (terminal/websocket) están configuradas con `https://` como prefijo del servicio de origen.
|
||||
|
||||
Estos puertos **no hablan HTTPS** — solo HTTP plano. Cloudflared intenta establecer un handshake TLS con un servicio que responde en texto plano, causando el error.
|
||||
|
||||
---
|
||||
|
||||
## Dónde vive la configuración (importante)
|
||||
|
||||
El túnel está **gestionado desde el dashboard de Cloudflare** (remotely-managed),
|
||||
no por el `config.yml` local. El `/etc/cloudflared/config.yml` dentro del contenedor
|
||||
solo tiene el UUID del túnel, las credenciales y el comodín `*.urieljareth.org`:
|
||||
|
||||
```yaml
|
||||
tunnel: 5f0e5c5b-a180-46f2-a090-44d151006a62
|
||||
credentials-file: /etc/cloudflared/credentials.json
|
||||
ingress:
|
||||
- hostname: "*.urieljareth.org"
|
||||
service: https://192.168.0.117:443
|
||||
- service: http_status:404
|
||||
```
|
||||
|
||||
**Las rutas de `coolify.urieljareth.org` (incluidas 6001/6002) NO están en ese
|
||||
archivo — vienen del dashboard/API.** La firma de esto en los logs es la línea
|
||||
`INF Updated to new configuration version=N`. Consecuencia práctica: **este problema
|
||||
no se arregla editando archivos en el servidor**, sino en el dashboard (rápido) o
|
||||
por la API de Cloudflare (control total — ver runbook).
|
||||
|
||||
---
|
||||
|
||||
## Configuración Correcta del Tunnel (coolify-tunnel)
|
||||
|
||||
El orden importa: Cloudflare evalúa las rutas de **arriba hacia abajo**. Las rutas específicas deben ir ANTES del comodín.
|
||||
|
||||
| # | Dominio | Ruta | Servicio | Protocolo |
|
||||
|---|---------|------|---------|-----------|
|
||||
| 1 | `coolify.dominio.com` | `/build/*` | `http://192.168.0.117:8000` | HTTP |
|
||||
| 2 | `coolify.dominio.com` | `/app/*` | `http://192.168.0.117:6001` | HTTP ⚠️ |
|
||||
| 3 | `coolify.dominio.com` | `/terminal/ws*` | `http://192.168.0.117:6002` | HTTP ⚠️ |
|
||||
| 4 | `coolify.dominio.com` | `*` | `http://192.168.0.117:8000` | HTTP |
|
||||
| 5 | `*.dominio.com` | `*` | `https://192.168.0.117:443` | HTTPS |
|
||||
|
||||
### Reglas Críticas
|
||||
|
||||
- Los puertos **6001 y 6002 deben usar `http://`**, nunca `https://`
|
||||
- La ruta `/terminal/ws*` se escribe **sin barra final** (no `/terminal/ws/*`)
|
||||
- El comodín `*.dominio.com` va **siempre al final**
|
||||
- El comodín de Coolify (ruta 4) también usa `http://`
|
||||
|
||||
---
|
||||
|
||||
## Diagnóstico
|
||||
|
||||
Dentro del CT 102 (referencia):
|
||||
|
||||
```bash
|
||||
# Ver errores actuales del tunnel
|
||||
docker logs cloudflared --tail 30
|
||||
|
||||
# Confirmar configuración activa del tunnel
|
||||
docker logs cloudflared --tail 50 | grep "Updated to new configuration"
|
||||
```
|
||||
|
||||
Desde este repo (PowerShell, vía el path SSH habitual):
|
||||
|
||||
```powershell
|
||||
# Errores recientes del túnel
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker logs cloudflared --tail 40"
|
||||
|
||||
# Configuración activa (toma el version=N más alto)
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker logs cloudflared --tail 60" |
|
||||
Select-String "Updated to new configuration"
|
||||
```
|
||||
|
||||
En la configuración activa (línea `INF Updated to new configuration version=N`), verificar que los servicios de 6001 y 6002 digan `http://` y no `https://`. El runbook
|
||||
[runbooks/cloudflare-tunnel.md](../runbooks/cloudflare-tunnel.md) tiene el procedimiento completo paso a paso.
|
||||
|
||||
---
|
||||
|
||||
## Solución
|
||||
|
||||
1. Ir a **Cloudflare Zero Trust → Networks → Tunnels → coolify-tunnel → Public Hostnames**
|
||||
2. Editar la ruta `/app/*` → cambiar servicio de `https://IP:6001` a `http://IP:6001`
|
||||
3. Editar la ruta `/terminal/ws*` → cambiar servicio de `https://IP:6002` a `http://IP:6002`
|
||||
4. Guardar — Cloudflared aplica el cambio automáticamente sin reinicio
|
||||
|
||||
**Verificación:**
|
||||
|
||||
```bash
|
||||
docker logs cloudflared --tail 10
|
||||
```
|
||||
|
||||
Debe aparecer `INF Updated to new configuration version=<N>` con los servicios correctos en el JSON.
|
||||
|
||||
---
|
||||
|
||||
## Notas Adicionales
|
||||
|
||||
- Los errores previos en los logs son residuales de conexiones ya abiertas — desaparecen solos
|
||||
- Si el orden de las rutas también está mal (comodín antes que las específicas), el tráfico de websocket nunca llega a las rutas correctas
|
||||
- Este error es silencioso desde la perspectiva del usuario — solo ve que la terminal no conecta
|
||||
|
||||
---
|
||||
|
||||
## Reincidencia verificada (2026-06-03)
|
||||
|
||||
El problema volvió a presentarse (`Terminal websocket connection lost`). Hallazgos
|
||||
de esa intervención:
|
||||
|
||||
- Config activa (`version=14`) tenía **`/app/*` (6001) y `/terminal/ws/` (6002) en `https://`**.
|
||||
- Variante observada: la ruta de terminal estaba como **`/terminal/ws/`** (con barra
|
||||
final, sin comodín), además del `https://` — ambos errores juntos.
|
||||
- Solución aplicada desde el **dashboard**: 6001 y 6002 a `http://`, y path de terminal
|
||||
corregido a `/terminal/ws*`. Cloudflared aplicó solo (`version=14 → 15 → 16`).
|
||||
- Resultado: terminal de Coolify operativa. Los errores TLS residuales desaparecieron solos.
|
||||
- Pendiente menor: `app/*` quedó sin barra inicial (`/app/*` sería lo ideal); no es
|
||||
crítico porque el protocolo ya es correcto.
|
||||
@@ -0,0 +1,169 @@
|
||||
# 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`
|
||||
@@ -0,0 +1,425 @@
|
||||
> # ⚠️ DOCUMENTO OBSOLETO — NO SEGUIR
|
||||
>
|
||||
> Archivado el 2026-08-07. **No uses este archivo como guía.** Contiene datos que
|
||||
> contradicen la realidad verificada del host:
|
||||
>
|
||||
> - Da `192.168.0.117` como IP del servidor Coolify. **El host Proxmox es
|
||||
> `192.168.0.200`** y todo se alcanza por `ssh [email protected]` +
|
||||
> `pct exec 102 -- ...`. Ver [../proxmox-inventory.md](../proxmox-inventory.md).
|
||||
> - Describe editar la configuración del túnel en archivos del host. **El túnel
|
||||
> es gestionado desde el dashboard de Cloudflare** (el ingress baja del edge);
|
||||
> editar archivos en el host no tiene efecto.
|
||||
>
|
||||
> **Procedimiento vigente:** [../runbooks/cloudflare-tunnel.md](../runbooks/cloudflare-tunnel.md).
|
||||
> **Herramienta vigente:** `scripts/Invoke-CloudflareApi.ps1` — ver
|
||||
> [../TOOL-INDEX.md](../TOOL-INDEX.md).
|
||||
>
|
||||
> Se conserva solo por el valor histórico del diagnóstico.
|
||||
|
||||
---
|
||||
|
||||
# Instrucciones para Agente IA — Cloudflare Tunnel + Coolify
|
||||
|
||||
**Entorno:** Proxmox VE → LXC CT 102 → Coolify (Docker) → Traefik + cloudflared
|
||||
**Dominio:** urieljareth.org
|
||||
**IP interna del servidor Coolify:** 192.168.0.117
|
||||
|
||||
---
|
||||
|
||||
## HERRAMIENTAS DISPONIBLES
|
||||
|
||||
El agente tiene acceso a:
|
||||
|
||||
1. **SSH a Proxmox** — para ejecutar comandos en el servidor
|
||||
2. **API de Cloudflare** — para configurar DNS, Tunnel y Zero Trust sin usar la UI
|
||||
|
||||
Credenciales necesarias antes de comenzar:
|
||||
- `CF_API_TOKEN` — token con permisos: `Zona → DNS → Editar` y `Zero Trust → Editar` para urieljareth.org
|
||||
- `CF_ACCOUNT_ID` — ID de cuenta de Cloudflare (visible en el panel principal)
|
||||
- `CF_ZONE_ID` — ID de zona DNS (visible en la sección DNS del dominio)
|
||||
- `TUNNEL_TOKEN` — token del túnel cloudflared (se obtiene o regenera via API)
|
||||
- Acceso SSH al host Proxmox o directamente al CT 102 (root@192.168.0.117)
|
||||
|
||||
---
|
||||
|
||||
## PASO 1 — Verificar conectividad básica desde el servidor
|
||||
|
||||
Conectarse por SSH al contenedor de Coolify y ejecutar:
|
||||
|
||||
```bash
|
||||
# Verificar que TCP/443 saliente funciona
|
||||
curl -v https://cloudflare.com 2>&1 | head -10
|
||||
|
||||
# Verificar que UDP/7844 NO está disponible (es común en redes domésticas)
|
||||
nc -zv 198.41.192.37 7844
|
||||
```
|
||||
|
||||
**Resultado esperado:**
|
||||
- `curl` debe mostrar `Connected to cloudflare.com`
|
||||
- `nc` debe mostrar `Connection timed out` (UDP bloqueado — esto es normal y se resuelve en el Paso 3)
|
||||
|
||||
---
|
||||
|
||||
## PASO 2 — Configurar DNS en Cloudflare via API
|
||||
|
||||
### 2.1 Verificar registros existentes
|
||||
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" | jq '.result[] | {name, type, content, proxied}'
|
||||
```
|
||||
|
||||
### 2.2 Crear registro CNAME wildcard (obligatorio)
|
||||
|
||||
Reemplazar `<TUNNEL_ID>` con el ID del túnel (formato: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`):
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"type": "CNAME",
|
||||
"name": "*",
|
||||
"content": "<TUNNEL_ID>.cfargotunnel.com",
|
||||
"proxied": true,
|
||||
"ttl": 1
|
||||
}'
|
||||
```
|
||||
|
||||
### 2.3 Crear registro CNAME para coolify
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"type": "CNAME",
|
||||
"name": "coolify",
|
||||
"content": "<TUNNEL_ID>.cfargotunnel.com",
|
||||
"proxied": true,
|
||||
"ttl": 1
|
||||
}'
|
||||
```
|
||||
|
||||
> ⚠️ Ambos registros deben tener `proxied: true` (ícono naranja en la UI). Sin el wildcard `*`, los subdominios de las apps desplegadas devuelven `DNS_PROBE_FINISHED_NXDOMAIN`.
|
||||
|
||||
---
|
||||
|
||||
## PASO 3 — Obtener o regenerar el token del túnel
|
||||
|
||||
### 3.1 Listar túneles existentes
|
||||
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result[] | {id, name, status}'
|
||||
```
|
||||
|
||||
### 3.2 Obtener el token del túnel existente
|
||||
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel/<TUNNEL_ID>/token" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" | jq -r '.result'
|
||||
```
|
||||
|
||||
Guardar el resultado como `TUNNEL_TOKEN`.
|
||||
|
||||
### 3.3 (Alternativa) Crear un túnel nuevo
|
||||
|
||||
Solo si no existe un túnel previo:
|
||||
|
||||
```bash
|
||||
curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"name": "coolify-tunnel",
|
||||
"tunnel_secret": "'$(openssl rand -base64 32)'"
|
||||
}' | jq '{id: .result.id, name: .result.name}'
|
||||
```
|
||||
|
||||
Luego obtener el token con el endpoint del paso 3.2.
|
||||
|
||||
---
|
||||
|
||||
## PASO 4 — Configurar las rutas del túnel via API
|
||||
|
||||
Este es el paso más crítico. Las rutas se llaman "ingress rules" y deben configurarse en orden exacto.
|
||||
|
||||
### Orden obligatorio de rutas
|
||||
|
||||
| # | Hostname | Path | Servicio | Protocolo | Notas |
|
||||
|---|----------|------|----------|-----------|-------|
|
||||
| 1 | coolify.urieljareth.org | /build/* | 192.168.0.117:8000 | http | Build logs |
|
||||
| 2 | coolify.urieljareth.org | /project/* | 192.168.0.117:8000 | http | **CRÍTICO: UI de apps** |
|
||||
| 3 | coolify.urieljareth.org | /app/* | 192.168.0.117:6001 | http | Websocket realtime |
|
||||
| 4 | coolify.urieljareth.org | /terminal/ws* | 192.168.0.117:6002 | http | Terminal websocket |
|
||||
| 5 | coolify.urieljareth.org | * | 192.168.0.117:8000 | http | Catch-all Coolify UI |
|
||||
| 6 | *.urieljareth.org | * | 192.168.0.117:443 | https | Apps via Traefik |
|
||||
|
||||
### Aplicar configuración via API
|
||||
|
||||
```bash
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel/<TUNNEL_ID>/configurations" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{
|
||||
"config": {
|
||||
"ingress": [
|
||||
{
|
||||
"hostname": "coolify.urieljareth.org",
|
||||
"path": "/build/*",
|
||||
"service": "http://192.168.0.117:8000"
|
||||
},
|
||||
{
|
||||
"hostname": "coolify.urieljareth.org",
|
||||
"path": "/project/*",
|
||||
"service": "http://192.168.0.117:8000"
|
||||
},
|
||||
{
|
||||
"hostname": "coolify.urieljareth.org",
|
||||
"path": "/app/*",
|
||||
"service": "http://192.168.0.117:6001"
|
||||
},
|
||||
{
|
||||
"hostname": "coolify.urieljareth.org",
|
||||
"path": "/terminal/ws*",
|
||||
"service": "http://192.168.0.117:6002"
|
||||
},
|
||||
{
|
||||
"hostname": "coolify.urieljareth.org",
|
||||
"service": "http://192.168.0.117:8000"
|
||||
},
|
||||
{
|
||||
"hostname": "*.urieljareth.org",
|
||||
"service": "https://192.168.0.117:443",
|
||||
"originRequest": {
|
||||
"noTLSVerify": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"service": "http_status:404"
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
> ⚠️ El último elemento `http_status:404` es obligatorio. La API rechaza la configuración si no hay un catch-all final sin hostname.
|
||||
|
||||
### Verificar que las rutas se aplicaron correctamente
|
||||
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/cfd_tunnel/<TUNNEL_ID>/configurations" \
|
||||
-H "Authorization: Bearer $CF_API_TOKEN" | jq '.result.config.ingress[] | {hostname, path, service}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PASO 5 — Reglas críticas de las rutas (no negociables)
|
||||
|
||||
### Puertos 6001 y 6002 — siempre HTTP, nunca HTTPS
|
||||
|
||||
Los puertos `6001` (websocket realtime) y `6002` (terminal websocket) de Coolify NO hablan TLS internamente. Si se configura `https://` para estas rutas, cloudflared devuelve:
|
||||
|
||||
```
|
||||
tls: first record does not look like a TLS handshake
|
||||
```
|
||||
|
||||
Siempre usar `http://192.168.0.117:6001` y `http://192.168.0.117:6002`.
|
||||
|
||||
### Ruta /project/* — va ANTES de /app/*
|
||||
|
||||
Sin la regla `/project/*` en posición 2, cualquier URL con `/application/` en el path (como `/project/xxx/environment/xxx/application/xxx`) es capturada por `/app/*` y enviada al websocket del puerto 6001. La UI de Coolify carga en blanco.
|
||||
|
||||
### Ruta /terminal/ws* — sin barra al final
|
||||
|
||||
Escribir `/terminal/ws*` y NO `/terminal/ws/*`. La variante con barra no hace match con las conexiones del terminal.
|
||||
|
||||
### Ruta *.urieljareth.org — siempre al final con noTLSVerify
|
||||
|
||||
El wildcard debe ir después de todas las rutas específicas de `coolify.urieljareth.org`. Apunta a Traefik en puerto 443 con HTTPS y requiere `noTLSVerify: true` porque Traefik usa certificados autofirmados internamente.
|
||||
|
||||
---
|
||||
|
||||
## PASO 6 — Desplegar cloudflared en el servidor
|
||||
|
||||
Ejecutar via SSH en el contenedor de Coolify:
|
||||
|
||||
```bash
|
||||
# Detener y eliminar el contenedor anterior si existe
|
||||
docker stop cloudflared 2>/dev/null
|
||||
docker rm cloudflared 2>/dev/null
|
||||
|
||||
# Crear el contenedor con protocolo HTTP2 forzado
|
||||
docker run -d \
|
||||
--name cloudflared \
|
||||
--restart always \
|
||||
-e TUNNEL_EDGE_PORT=443 \
|
||||
cloudflare/cloudflared:latest \
|
||||
tunnel --no-autoupdate --protocol http2 run --token $TUNNEL_TOKEN
|
||||
```
|
||||
|
||||
### Por qué --protocol http2 es obligatorio
|
||||
|
||||
En redes domésticas, el puerto UDP/7844 que usa QUIC (el protocolo por defecto de cloudflared) está bloqueado por la mayoría de routers e ISPs. Sin `--protocol http2`, el túnel se conecta brevemente y cae en timeout cada ~5 minutos con el error:
|
||||
|
||||
```
|
||||
failed to dial to edge with quic: timeout: no recent network activity
|
||||
```
|
||||
|
||||
`-e TUNNEL_EDGE_PORT=443` fuerza la conexión TCP por el puerto 443, que siempre está abierto.
|
||||
|
||||
### Verificar que el túnel está activo
|
||||
|
||||
```bash
|
||||
docker logs cloudflared --tail 20
|
||||
```
|
||||
|
||||
Resultado correcto — deben aparecer 4 líneas como esta:
|
||||
|
||||
```
|
||||
INF Registered tunnel connection connIndex=0 ... protocol=http2
|
||||
INF Registered tunnel connection connIndex=1 ... protocol=http2
|
||||
INF Registered tunnel connection connIndex=2 ... protocol=http2
|
||||
INF Registered tunnel connection connIndex=3 ... protocol=http2
|
||||
```
|
||||
|
||||
Si aparece `Provided Tunnel token is not valid`, el token se truncó. Repetir el Paso 3.2 para obtenerlo completo.
|
||||
|
||||
---
|
||||
|
||||
## PASO 7 — Configurar Traefik con DNS Challenge
|
||||
|
||||
Esto elimina la dependencia de validación HTTP para obtener certificados SSL. Es necesario cuando "Always Use HTTPS" está activo en Cloudflare (que redirige las validaciones HTTP de Let's Encrypt antes de que lleguen a Traefik).
|
||||
|
||||
### 7.1 Crear token de API para DNS Challenge
|
||||
|
||||
El token debe tener permisos: `Zona → DNS → Editar` para `urieljareth.org`.
|
||||
|
||||
```bash
|
||||
# Verificar que el token tiene los permisos correctos
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
|
||||
-H "Authorization: Bearer $CF_DNS_API_TOKEN" | jq '{status: .result.status}'
|
||||
```
|
||||
|
||||
### 7.2 Editar el docker-compose de Traefik via SSH
|
||||
|
||||
```bash
|
||||
# Hacer backup primero
|
||||
cp /data/coolify/proxy/docker-compose.yml /data/coolify/proxy/docker-compose.yml.bak
|
||||
|
||||
# Editar
|
||||
nano /data/coolify/proxy/docker-compose.yml
|
||||
```
|
||||
|
||||
Agregar dentro del servicio `traefik`, sección `environment`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- CF_DNS_API_TOKEN=<token-dns-api>
|
||||
```
|
||||
|
||||
Reemplazar las líneas de `httpchallenge` en `command` por:
|
||||
|
||||
```yaml
|
||||
- '--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'
|
||||
```
|
||||
|
||||
### 7.3 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
|
||||
```
|
||||
|
||||
> ⚠️ Si hay error 429 en los logs de coolify-proxy, Let's Encrypt aplicó rate limit por intentos fallidos previos. Esperar 1 hora antes de reintentar.
|
||||
|
||||
---
|
||||
|
||||
## PASO 8 — Verificación final
|
||||
|
||||
### Verificar estado de todos los servicios
|
||||
|
||||
```bash
|
||||
# Contenedores corriendo
|
||||
docker ps --format "table {{.Names}}\t{{.Status}}" | grep -E "coolify|cloudflared|traefik"
|
||||
|
||||
# Túnel con 4 conexiones activas
|
||||
docker logs cloudflared --tail 5 | grep "Registered tunnel"
|
||||
|
||||
# Traefik sin errores de certificado
|
||||
docker logs coolify-proxy --tail 50 2>&1 | grep -i "error\|certificate\|acme\|429"
|
||||
```
|
||||
|
||||
### Verificar rutas desde afuera
|
||||
|
||||
```bash
|
||||
# Coolify UI debe responder 200
|
||||
curl -s -o /dev/null -w "%{http_code}" https://coolify.urieljareth.org
|
||||
|
||||
# Una app desplegada debe responder 200 o 301
|
||||
curl -s -o /dev/null -w "%{http_code}" https://miapp.urieljareth.org
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DIAGNÓSTICO DE ERRORES COMUNES
|
||||
|
||||
| Error | Causa más probable | Verificar |
|
||||
|-------|--------------------|-----------|
|
||||
| `530` — Unregistered from Argo Tunnel | cloudflared caído | `docker logs cloudflared --tail 20` |
|
||||
| `502 Bad Gateway` | Traefik sin cert SSL o puerto 3000 | Logs de coolify-proxy |
|
||||
| Página en blanco al abrir app en Coolify | Falta regla `/project/*` | Verificar rutas del túnel |
|
||||
| `tls: first record does not look like TLS` | https:// en puerto 6001 o 6002 | Corregir a http:// en ingress rules |
|
||||
| `DNS_PROBE_FINISHED_NXDOMAIN` | Falta CNAME wildcard | Verificar registro `*` en DNS |
|
||||
| Túnel cae cada 5 min | UDP/7844 bloqueado | Confirmar `--protocol http2` en el contenedor |
|
||||
| `429` en logs de Traefik | Rate limit de Let's Encrypt | Esperar 1h, luego reiniciar Traefik |
|
||||
| `Provided Tunnel token is not valid` | Token truncado | Obtener token completo via API (Paso 3.2) |
|
||||
|
||||
---
|
||||
|
||||
## FLUJO PARA DESPLEGAR UNA APP NUEVA
|
||||
|
||||
Por un bug en Coolify beta.472, la UI de apps individuales no carga tras la creación. Usar este flujo:
|
||||
|
||||
```bash
|
||||
# 1. Obtener el ID y UUID de la app recién creada
|
||||
docker exec coolify-db psql -U coolify -d coolify \
|
||||
-c "SELECT id, uuid, name, fqdn FROM applications ORDER BY id DESC LIMIT 3;"
|
||||
|
||||
# 2. Actualizar dominio y puerto antes del deploy
|
||||
docker exec coolify-db psql -U coolify -d coolify \
|
||||
-c "UPDATE applications SET fqdn='https://miapp.urieljareth.org', ports_exposes='80' WHERE id=<ID>;"
|
||||
|
||||
# 3. Hacer deploy via API de Coolify
|
||||
curl -X POST "http://localhost:8000/api/v1/deploy?uuid=<UUID>&force=false" \
|
||||
-H "Authorization: Bearer <COOLIFY_API_TOKEN>"
|
||||
|
||||
# 4. Verificar que Traefik apunta al puerto correcto
|
||||
grep "server.port" /data/coolify/applications/<UUID>/docker-compose.yaml
|
||||
```
|
||||
|
||||
Si el puerto sigue siendo 3000 en lugar de 80:
|
||||
|
||||
```bash
|
||||
sed -i 's/loadbalancer.server.port=3000/loadbalancer.server.port=80/g' \
|
||||
/data/coolify/applications/<UUID>/docker-compose.yaml
|
||||
|
||||
docker compose -f /data/coolify/applications/<UUID>/docker-compose.yaml up -d --force-recreate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ARCHIVOS DE REFERENCIA EN EL SERVIDOR
|
||||
|
||||
| Archivo | Ruta |
|
||||
|---------|------|
|
||||
| Docker-compose de Traefik | `/data/coolify/proxy/docker-compose.yml` |
|
||||
| Backup de Traefik | `/data/coolify/proxy/docker-compose.yml.bak` |
|
||||
| Certificados SSL | `/data/coolify/proxy/acme.json` |
|
||||
| Docker-compose de cada app | `/data/coolify/applications/<UUID>/docker-compose.yaml` |
|
||||
@@ -0,0 +1,88 @@
|
||||
# Coolify cleanup report
|
||||
|
||||
> **Date:** 2026-06-29
|
||||
> **Target:** self-hosted Coolify inside Proxmox LXC `102` (`192.168.0.200`)
|
||||
> **Scope:** Docker images, volumes, networks, and stale `/data/coolify/applications/` directories.
|
||||
|
||||
## Executive summary
|
||||
|
||||
| Item | Before | After | Δ |
|
||||
|------|-------:|------:|---|
|
||||
| Docker images | 41 | 38 | **−3** (≈ **4.7 GB**) |
|
||||
| Orphan volumes | 2 | 0 | −2 |
|
||||
| Orphan networks | 1 | 0 | −1 |
|
||||
| Orphan `/data/coolify/applications/*` dirs | 4 | 0 | −4 |
|
||||
| LXC disk usage | **71 GB / 99 GB (75%)** | **≈ 66 GB / 99 GB (≈ 67%)** | **≈ 5 GB freed** |
|
||||
|
||||
All deletions were verified against the Coolify API (`/api/v1/{services,applications,databases,projects}`) and the running container set: every removed item had **zero matching container and zero matching API resource**.
|
||||
|
||||
## Methodology
|
||||
|
||||
1. Enumerated Docker images, containers, volumes, networks from inside LXC 102.
|
||||
2. Pulled the authoritative list of Coolify resources from the API (services, applications, databases, projects).
|
||||
3. Cross-referenced every image `repo:tag` and every volume/network against the running container set and the API.
|
||||
4. Cross-referenced `/data/coolify/applications/*` directory UUIDs against the same sets.
|
||||
5. Tagged anything with no active consumer as orphan.
|
||||
|
||||
## Items removed
|
||||
|
||||
### Docker images (no container references)
|
||||
|
||||
| Image | ID | Size | Age | Reason |
|
||||
|-------|----|-----:|-----|--------|
|
||||
| `e6vie34d83iv5vw3eyzinl3s:ab190560...` | `ae3586b9690a` | 1.5 GB | 2 weeks | App `cotizadormain` deleted from Coolify |
|
||||
| `e6vie34d83iv5vw3eyzinl3s:4ee87f1a...` | `d36f87274b9d` | 1.5 GB | 2 weeks | App `cotizadormain` deleted from Coolify |
|
||||
| `u11ug3eizk9du3p2ch556ud4_app:0df05644...` | `0e831f095231` | 1.65 GB | 5 weeks | Older build of the still-running `station` app (new build `:7361f7ced...` retained) |
|
||||
|
||||
> `ghcr.io/coollabsio/coolify-helper:1.0.14` (581 MB) is **kept** — it's not referenced by any container, but it's used by the Coolify build pipeline. Deleting it could break future builds of apps with build packs. Re-evaluate on the next Coolify upgrade.
|
||||
|
||||
### Docker volumes (no container references)
|
||||
|
||||
| Volume | Reason |
|
||||
|--------|--------|
|
||||
| `ff38d8acc367314a2f26b6ca041819ce55b72e07b3b72c89d99bab2df171f62c` | No container uses it; left over from a deleted app |
|
||||
| `m7d87ukrkgcag7g2ij9m7f1i_station-data` | App's UUID prefix (`m7d87...`) no longer present in any container, volume, network, or API resource |
|
||||
|
||||
> The other hash-named volumes (`2aa23d9d...` and `b76a6b81...`) **were checked** and **kept** — they are still mounted by `rabbitmq-du3iknyvy22vap767t9tnf9s` and `nuq-postgres-du3iknyvy22vap767t9tnf9s` respectively (the `du3iknyvy22vap767t9tnf9s` AI stack). Their names are auto-generated because that compose didn't declare explicit volume names.
|
||||
|
||||
### Docker networks (no container references)
|
||||
|
||||
| Network | Reason |
|
||||
|---------|--------|
|
||||
| `a7dwp54y5ohnu855x9rrlui2` | UUID prefix not present in any container, volume, or Coolify resource. Stale bridge network from a deleted app. |
|
||||
|
||||
### `/data/coolify/applications/*` directories (no matching Coolify API resource)
|
||||
|
||||
| UUID | Last deployment | App (per embedded compose labels) | Reason |
|
||||
|------|-----------------|----------------------------------|--------|
|
||||
| `dc1rvdq1wt4rx4ezw2bunhij` | 2026-04-05 | `rag-google:main` (project `rag`) | Deleted from Coolify UI; left a `.env`, `docker-compose.yaml`, `README.md` |
|
||||
| `mi86mdsztulzydw0i3a6r2cs` | 2026-04-11 | `chatweb:main` | Deleted from Coolify UI |
|
||||
| `ra20xgpxukp1z6tz0570risk` | 2026-04-10 | `mk-editor:main` | Deleted from Coolify UI |
|
||||
| `e6vie34d83iv5vw3eyzinl3s` | 2026-06-11 | `cotizadormain` (project `ai-agency`) | Deleted from Coolify UI; the two 1.5 GB images were the only artifacts left behind |
|
||||
|
||||
> The remaining four application directories (`du3iknyvy22vap767t9tnf9s`, `pugr2d3moykf6q9gjvz015dg`, `u11ug3eizk9du3p2ch556ud4`, `vngcvnhbfqboov4nln88zc73`) were **kept** — they are still referenced by running containers, even though they don't appear in `/api/v1/applications` (Coolify's API only lists `service_type` resources; these are legacy "application" resources).
|
||||
|
||||
## Coolify settings adjusted
|
||||
|
||||
Inside `/data/coolify/sentinel/.../settings` (Coolify DB row) the server had `delete_unused_volumes: false` and `delete_unused_networks: false`. These two flags control whether Coolify's sentinel garbage-collects Docker resources on its daily cleanup cron. **Switched both to `true`** to prevent the same drift from recurring.
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
docker system df
|
||||
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
||||
Images 38 37 60.05GB 55.24GB (91%)
|
||||
Containers 47 47 2.64GB 0B (0%)
|
||||
Local Volumes 42 41 9.615GB 36.86kB (0%)
|
||||
Build Cache 0 0 0B 0B
|
||||
|
||||
docker ps --format '{{.Names}}' | wc -l # 47 → 47 (unchanged)
|
||||
```
|
||||
|
||||
All 47 containers that were running before the cleanup are still running.
|
||||
|
||||
## Caveats / follow-ups
|
||||
|
||||
- **`coolify-helper:1.0.14`** is left in place intentionally. Delete after upgrading Coolify to a version that ships a newer helper.
|
||||
- **Disk pressure:** the LXC is at ~67% used after the cleanup. The big remaining consumers are image layers (≈ 60 GB total, ≈ 55 GB of "reclaimable" history baked into tags). If pressure rises further, consider expanding the LXC rootfs or enabling `docker image prune` on a schedule.
|
||||
- **Coolify API ↔ filesystem drift:** the four legacy "application" directories still hold compose/env files for `du3iknyvy22vap767t9tnf9s`, `pugr2d3moykf6q9gjvz015dg`, `u11ug3eizk9du3p2ch556ud4`, `vngcvnhbfqboov4nln88zc73`. Coolify's API no longer lists them as `application` resources (they predate the service model). They are still functional, but cannot be managed from the Coolify UI. Plan to recreate them as `service_type` resources or migrate them.
|
||||
@@ -0,0 +1,20 @@
|
||||
# Incidentes — archivo histórico
|
||||
|
||||
> ⚠️ **Esto NO es fuente de verdad.** Es material histórico: incidentes ya
|
||||
> resueltos y documentos superados. Describe cómo estaba el sistema en la fecha
|
||||
> de cada archivo, no cómo está hoy.
|
||||
>
|
||||
> - Estado actual → [../proxmox-inventory.md](../proxmox-inventory.md)
|
||||
> - Procedimientos vigentes → [../runbooks/](../runbooks/)
|
||||
> - Qué herramienta usar → [../TOOL-INDEX.md](../TOOL-INDEX.md)
|
||||
|
||||
Se conserva porque el diagnóstico y la causa raíz siguen siendo útiles cuando un
|
||||
síntoma parecido reaparece.
|
||||
|
||||
| Archivo | Fecha | Qué fue | Estado |
|
||||
|---|---|---|---|
|
||||
| [2026-04-11-cloudflare-tunnel-websocket-tls.md](2026-04-11-cloudflare-tunnel-websocket-tls.md) | 2026-04-11 | Terminal de Coolify y websockets de la UI caídos: routing del túnel en los puertos 6001/6002. | Resuelto. Procedimiento vigente en [../runbooks/cloudflare-tunnel.md](../runbooks/cloudflare-tunnel.md). |
|
||||
| [2026-04-11-coolify-static-app-deploy.md](2026-04-11-coolify-static-app-deploy.md) | 2026-04-11 | App estática desde GitHub servía página en blanco y 502. | Resuelto. Era Coolify v4.0.0-beta.472; hoy corre v4.1.2. |
|
||||
| [2026-06-29-coolify-cleanup-report.md](2026-06-29-coolify-cleanup-report.md) | 2026-06-29 | Limpieza de imágenes, volúmenes y redes de Docker (−4.7 GB). | Reporte de una ejecución puntual. |
|
||||
| [2026-04-cloudflare-tunnel-guia-agente-OBSOLETA.md](2026-04-cloudflare-tunnel-guia-agente-OBSOLETA.md) | 2026-04 | Guía de agente para el túnel Cloudflare. | **Obsoleta y contradictoria** — ver el aviso dentro del archivo. Usa el runbook. |
|
||||
| [openclaw.md](openclaw.md) | varias | Historial de incidentes de OpenClaw. | Referencia. |
|
||||
@@ -0,0 +1,47 @@
|
||||
# Runbook: Incidentes OpenClaw Browser/CDP
|
||||
|
||||
Historial resumido de incidentes previos con OpenClaw y su browser container.
|
||||
|
||||
## Sintomas comunes
|
||||
|
||||
- Browser container aparece `unhealthy`.
|
||||
- OpenClaw no conecta al browser via CDP.
|
||||
- Timeouts contra el puerto CDP.
|
||||
|
||||
## Diagnostico
|
||||
|
||||
```powershell
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' | grep -E 'openclaw|browser'"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker exec <browser-container> ss -tlnp"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker logs <browser-container> --tail 100"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker logs <openclaw-container> --tail 100"
|
||||
```
|
||||
|
||||
## Puerto CDP
|
||||
|
||||
En un incidente previo, Chromium escuchaba en `127.0.0.1:9222` dentro del
|
||||
container y nginx exponia `0.0.0.0:9223` para otros containers. No asumas que
|
||||
`9222` o `9223` es correcto sin probar desde la red Docker actual.
|
||||
|
||||
Prueba desde el container OpenClaw:
|
||||
|
||||
```powershell
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker exec <openclaw-container> curl -sf http://<browser-host>:9223/json/version"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker exec <openclaw-container> curl -sf http://<browser-host>:9222/json/version"
|
||||
```
|
||||
|
||||
## Acciones que requieren confirmacion
|
||||
|
||||
```powershell
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker exec <browser-container> pkill -f chromium"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker restart <browser-container>"
|
||||
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker restart <openclaw-container>"
|
||||
```
|
||||
|
||||
## Notas de configuracion
|
||||
|
||||
- Montar `/dev/shm` o usar `shm_size` suficiente suele mejorar estabilidad de
|
||||
Chromium en Docker.
|
||||
- Limpiar locks de perfil en startup puede resolver arranques atascados.
|
||||
- Cambios de capacidades como `SYS_ADMIN` o `seccomp:unconfined` son sensibles;
|
||||
revisarlos antes de aplicarlos.
|
||||
Reference in New Issue
Block a user