← Tu laboratorio en cualquier parteSerie Remoto · paso 11 de 11

Kit de diagnóstico: cuando algo no funciona desde fuera y no sabes por dónde empezar

Estás de viaje, abres el móvil y el agente no carga. Este es el orden en el que lo miramos, de fuera hacia dentro, con la orden exacta de cada paso. Y las cinco mentiras de los indicadores que más tiempo nos han hecho perder.

Dificultadmedia
Tiempo10 minutos por incidencia
Ingredientescurl · tailscale · systemctl · ss · docker · journalctl

Todo lo de esta serie es una cadena: DNS → servidor → Tailscale → bridge → servicio → modelo. Cuando algo falla desde fuera, el error que ves en el móvil casi nunca dice en qué eslabón está. La forma de no perder la tarde es recorrer la cadena de fuera hacia dentro, una comprobación por eslabón, y parar en el primero que falle.

El orden

1 · ¿Llega algo al servidor?

curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' -H 'Accept: text/html' https://agente.tudominio.es/
respuesta significa
200 (pantalla de login) la cadena hasta el bridge funciona; el problema está más dentro
401 funciona, solo que tu petición no es HTML o no llevas sesión
502 / 504 el servidor está vivo pero no llega al destino → paso 3
timeout / error de TLS DNS, IP pública o certificado → paso 2

2 · DNS, IP y certificado

dig +short agente.tudominio.es        # ¿la IP pública actual del servidor?
curl -s https://api.ipify.org          # (en el servidor) ¿cuál es su IP pública ahora?
sudo certbot certificates              # ¿caducado?
tail -20 /var/log/cf-ddns.log          # ¿el DNS dinámico se ha quejado?

Si las dos primeras no coinciden, el DNS dinámico no ha actualizado ese registro. Mira si el subdominio está en la lista del script.

3 · Del servidor al destino, por Tailscale

tailscale status | grep portatil       # ¿conectado? ¿«offline»?
tailscale ping portatil                # ¿responde? ¿directo o relay?
curl --max-time 8 -sS -o /dev/null -w '%{http_code}\n' http://100.x.y.z:3084/

Si el portátil sale offline: está dormido, sin red o en batería con las tareas paradas (P-090). Si responde a ping pero el curl falla, el bridge no está escuchando → paso 4.

4 · En la máquina destino: ¿escucha de verdad?

# Linux
ss -ltnp | grep -E ':(3080|3082|8099)\b'
systemctl --user status mi-servicio --no-pager
journalctl --user -u mi-servicio -n 50 --no-pager
# Windows
Get-NetTCPConnection -State Listen | Where-Object LocalPort -in 3080,3082,8504 |
  Select LocalAddress,LocalPort,OwningProcess
Get-ScheduledTask -TaskName 'Mi tarea' | Select TaskName,State

5 · ¿Y el modelo?

curl -s http://127.0.0.1:8099/health            # gateway: ¿ready? ¿qué perfil?
curl -s -H "Authorization: Bearer $CLAVE" http://127.0.0.1:8099/v1/models

Un 503 DRAINING es una rotación en curso: espera. Un 503 sin más es «no hay residente sano».

Las cinco mentiras de los indicadores

Esto es lo que más tiempo nos ha costado, con diferencia. Todos estos indicadores dijeron «bien» mientras el sistema estaba roto:

  1. systemctl dice active, pero el proceso está esperando que pulses una tecla en un diálogo (P-052). O el servicio es RemainAfterExit=yes y el contenedor que lanzó murió hace horas (P-083).
  2. docker ps dice Up, pero la aplicación dentro murió al intentar escuchar en una IP que todavía no existía y un vigilante mantiene vivo el proceso padre (P-041).
  3. pgrep encuentra el proceso, pero ha casado con el wrapper, no con el trabajo. Nos tuvo 22 minutos creyendo vivo un proceso muerto (P-059).
  4. La GPU está al 96 %, pero consume 18 W: no calcula, espera. El servidor compilaba kernels mientras el cliente se rendía a los 5 minutos y reintentaba, empeorándolo (P-093).
  5. El endpoint dice cómo está configurado, pero informa de su valor por defecto, no del real (P-002).

La regla que sacamos de las cinco: un sistema no funciona porque sus piezas estén vivas; funciona cuando puedes hacer tu trabajo. La comprobación buena es siempre la de extremo a extremo: una petición real que devuelve una respuesta real.

La prueba de humo que usamos para todo

curl -s http://127.0.0.1:8099/v1/chat/completions \
  -H "Authorization: Bearer $CLAVE" -H 'Content-Type: application/json' \
  -d '{"model":"gx10-local","max_tokens":2048,
       "messages":[{"role":"user","content":"Responde exactamente: OK_REMOTO"}]}'

Si esto devuelve OK_REMOTO, el modelo funciona. Si además lo hace a través de la URL pública y el bridge (con tu sesión), toda la cadena funciona. Todo lo demás son opiniones.

Antes de tocar nada en remoto

Tres reglas que aplicamos siempre que estamos lejos de las máquinas:

  • Dos caminos de acceso antes de cambiar cualquier cosa de red o de arranque. Si rompes uno, entras por el otro.
  • Copia fechada de cualquier fichero antes de editarlo, en la misma carpeta.
  • No reinicies «por si acaso». Un reinicio en remoto de una máquina que no has visto arrancar sola es una apuesta. Primero mira el log.

Y con esto termina la serie. Si montas algo parecido, o si alguno de estos pasos no te funciona, cuéntanoslo en X: estas guías mejoran con cada pregunta que nos llega.