Ir al contenido

Acceso remoto (SSH, túneles y tailnets)

¿Alguna vez has sentido la frustración de tener una configuración de IA increíble en tu escritorio pero no poder usarla cuando estás fuera de casa? Configurar el acceso remoto suele ser un proceso tedioso que termina en configuraciones de red inseguras o demasiado complejas que solo funcionan a medias.

Lo mejor es mantener las cosas simples y seguras. En esta guía te explico cómo gestionar el acceso remoto de forma directa, priorizando la seguridad sin sacrificar la comodidad de tener tu agente siempre disponible.

Este repo permite el “remoto sobre SSH” manteniendo un único Gateway (el maestro) ejecutándose en un host dedicado (escritorio/servidor) y conectando los clientes a él.

  • Para operadores (tú / la app de macOS): el túnel SSH es la solución universal.
  • Para nodos (iOS/Android y futuros dispositivos): conéctate al WebSocket del Gateway (LAN/tailnet o túnel SSH según sea necesario).
  • El WebSocket del Gateway se vincula al loopback en tu puerto configurado (por defecto 18789).
  • Para uso remoto, rediriges ese puerto loopback a través de SSH (o usas una tailnet/VPN y reduces el uso de túneles).

Configuraciones comunes de VPN/tailnet (donde vive el agente)

Sección titulada «Configuraciones comunes de VPN/tailnet (donde vive el agente)»

Piensa en el host del Gateway como “el lugar donde vive el agente”. Es el dueño de las sesiones, perfiles de autenticación, canales y el estado. Tu laptop/escritorio (y los nodos) se conectan a ese host.

1) Gateway siempre encendido en tu tailnet (VPS o servidor doméstico)

Sección titulada «1) Gateway siempre encendido en tu tailnet (VPS o servidor doméstico)»

Ejecuta el Gateway en un host persistente y accede a él mediante Tailscale o SSH.

  • Mejor UX: mantén gateway.bind: "loopback" y usa Tailscale Serve para la Control UI.
  • Alternativa: mantén loopback + túnel SSH desde cualquier máquina que necesite acceso.
  • Ejemplos: exe.dev (VM fácil) o Hetzner (VPS de producción).

Esto es ideal si tu laptop entra en reposo a menudo pero quieres que el agente esté siempre activo.

2) El escritorio de casa ejecuta el Gateway, la laptop es el control remoto

Sección titulada «2) El escritorio de casa ejecuta el Gateway, la laptop es el control remoto»

La laptop no ejecuta el agente. Se conecta de forma remota:

  • Usa el modo Remote over SSH de la app de macOS (Settings → General → “OpenClaw runs”).
  • La app abre y gestiona el túnel, así que el WebChat y los health checks funcionan sin problemas.

Guía de pasos: macOS remote access.

3) La laptop ejecuta el Gateway, acceso remoto desde otras máquinas

Sección titulada «3) La laptop ejecuta el Gateway, acceso remoto desde otras máquinas»

Mantén el Gateway local pero exponlo de forma segura:

  • Crea un túnel SSH hacia la laptop desde otras máquinas, o
  • Usa Tailscale Serve para la Control UI y mantén el Gateway solo en loopback.

Guía: Tailscale y Web overview.

Flujo de comandos (qué se ejecuta y dónde)

Sección titulada «Flujo de comandos (qué se ejecuta y dónde)»

Un único servicio de Gateway posee el estado y los canales. Los nodos son periféricos.

Ejemplo de flujo (Telegram → nodo):

  • El mensaje de Telegram llega al Gateway.
  • El Gateway ejecuta el agent y decide si debe llamar a una herramienta de nodo.
  • El Gateway llama al nodo a través del WebSocket del Gateway (node.* RPC).
  • El nodo devuelve el resultado; el Gateway responde de vuelta a Telegram.

Notas:

  • Los nodos no ejecutan el servicio de gateway. Solo debe ejecutarse un gateway por host a menos que uses perfiles aislados intencionalmente (ver Multiple gateways).
  • El “modo nodo” de la app de macOS es simplemente un cliente de nodo sobre el WebSocket del Gateway.

Crea un túnel local hacia el WS del Gateway remoto:

Ventana de terminal
ssh -N -L 18789:127.0.0.1:18789 user@host

Con el túnel activo:

  • openclaw health y openclaw status --deep ahora llegan al gateway remoto a través de ws://127.0.0.1:18789.
  • openclaw gateway {status,health,send,agent,call} también pueden apuntar a la URL redirigida mediante --url cuando sea necesario.

Nota: reemplaza 18789 con tu gateway.port configurado (o --port/OPENCLAW_GATEWAY_PORT). Nota: cuando pasas --url, la CLI no recurre a las credenciales de configuración o entorno. Incluye --token o --password explícitamente. Omitir credenciales explícitas resultará en un error.

Puedes persistir un objetivo remoto para que los comandos de la CLI lo usen por defecto:

{
gateway: {
mode: "remote",
remote: {
url: "ws://127.0.0.1:18789",
token: "your-token",
},
},
}

Cuando el gateway está solo en loopback, mantén la URL en ws://127.0.0.1:18789 y abre primero el túnel SSH.

La resolución de credenciales del Gateway sigue un contrato compartido en las rutas de call/probe/status y el monitoreo de aprobación de ejecución de Discord. El host del nodo usa el mismo contrato base con una excepción en el modo local (ignora intencionalmente gateway.remote.*):

  • Las credenciales explícitas (--token, --password, o la herramienta gatewayToken) siempre mandan en las rutas de llamada que aceptan autenticación explícita.
  • Seguridad en la anulación de URL:
    • Las anulaciones de URL por CLI (--url) nunca reutilizan credenciales implícitas de configuración o entorno.
    • Las anulaciones de URL por entorno (OPENCLAW_GATEWAY_URL) pueden usar solo credenciales de entorno (OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD).
  • Valores por defecto en modo local:
    • token: OPENCLAW_GATEWAY_TOKEN -> gateway.auth.token -> gateway.remote.token (el respaldo remoto se aplica solo cuando la entrada del token de autenticación local no está definida).
    • password: OPENCLAW_GATEWAY_PASSWORD -> gateway.auth.password -> gateway.remote.password (el respaldo remoto se aplica solo cuando la entrada de la contraseña de autenticación local no está definida).
  • Valores por defecto en modo remoto:
    • token: gateway.remote.token -> OPENCLAW_GATEWAY_TOKEN -> gateway.auth.token
    • password: OPENCLAW_GATEWAY_PASSWORD -> gateway.remote.password -> gateway.auth.password
  • Excepción de modo local en el host del nodo: se ignoran gateway.remote.token / gateway.remote.password.
  • Las comprobaciones de token de probe/status remoto son estrictas por defecto: usan solo gateway.remote.token (sin respaldo de token local) cuando apuntan al modo remoto.
  • Las anulaciones de entorno del Gateway usan solo OPENCLAW_GATEWAY_*.

WebChat ya no utiliza un puerto HTTP independiente. La interfaz de chat de SwiftUI se conecta directamente al WebSocket del Gateway.

  • Redirige el puerto 18789 a través de SSH (ver arriba), luego conecta los clientes a ws://127.0.0.1:18789.
  • En macOS, es preferible usar el modo “Remote over SSH” de la app, que gestiona el túnel automáticamente.

La app de la barra de menú de macOS puede gestionar toda esta configuración de extremo a extremo (comprobaciones de estado remotas, WebChat y reenvío de Voice Wake).

Guía de pasos: macOS remote access.

Versión corta: mantén el Gateway solo en loopback a menos que estés seguro de que necesitas vincularlo a otra interfaz.

  • Loopback + SSH/Tailscale Serve es la opción más segura por defecto (sin exposición pública).
  • El uso de ws:// en texto plano es solo para loopback por defecto. Para redes privadas de confianza, establece OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 en el proceso del cliente como medida de emergencia.
  • Vínculos que no son loopback (lan/tailnet/custom, o auto cuando loopback no está disponible) deben usar tokens o contraseñas de autenticación.
  • gateway.remote.token / .password son fuentes de credenciales del cliente. No configuran la autenticación del servidor por sí mismos.
  • Las rutas de llamadas locales pueden usar gateway.remote.* como respaldo solo cuando gateway.auth.* no está definido.
  • Si gateway.auth.token / gateway.auth.password se configura explícitamente mediante SecretRef y no se resuelve, la resolución falla por seguridad (sin enmascaramiento por respaldo remoto).
  • gateway.remote.tlsFingerprint fija el certificado TLS remoto cuando se usa wss://.
  • Tailscale Serve puede autenticar el tráfico de la Control UI/WebSocket mediante cabeceras de identidad cuando gateway.auth.allowTailscale: true; los endpoints de la API HTTP siguen requiriendo autenticación por token/contraseña. Este flujo sin token asume que el host del gateway es de confianza. Cámbialo a false si quieres tokens/contraseñas en todas partes.
  • Trata el control del navegador como un acceso de operador: solo tailnet + emparejamiento de nodos deliberado.

Análisis detallado: Security.

macOS: túnel SSH persistente mediante LaunchAgent

Sección titulada «macOS: túnel SSH persistente mediante LaunchAgent»

Para clientes de macOS que se conectan a un gateway remoto, la configuración persistente más sencilla utiliza una entrada de configuración LocalForward de SSH más un LaunchAgent para mantener el túnel activo tras reinicios o fallos.

Edita ~/.ssh/config:

Ventana de terminal
Host remote-gateway
HostName <REMOTE_IP>
User <REMOTE_USER>
LocalForward 18789 127.0.0.1:18789
IdentityFile ~/.ssh/id_rsa

Reemplaza <REMOTE_IP> y <REMOTE_USER> con tus valores.

Ventana de terminal
ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>

Guarda el token en la configuración para que persista entre reinicios:

Ventana de terminal
openclaw config set gateway.remote.token "<your-token>"

Guarda esto como ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ai.openclaw.ssh-tunnel</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ssh</string>
<string>-N</string>
<string>remote-gateway</string>
</array>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Ventana de terminal
launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist

El túnel se iniciará automáticamente al iniciar sesión, se reiniciará si falla y mantendrá activo el puerto redirigido.

Nota: si tienes un LaunchAgent com.openclaw.ssh-tunnel antiguo, descárgalo y elimínalo.

Comprueba si el túnel se está ejecutando:

Ventana de terminal
ps aux | grep "ssh -N remote-gateway" | grep -v grep
lsof -i :18789

Reiniciar el túnel:

Ventana de terminal
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel

Detener el túnel:

Ventana de terminal
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
Entrada de configuraciónQué hace
LocalForward 18789 127.0.0.1:18789Redirige el puerto local 18789 al puerto remoto 18789
ssh -NSSH sin ejecutar comandos remotos (solo redirección de puertos)
KeepAliveReinicia automáticamente el túnel si falla
RunAtLoadInicia el túnel cuando el LaunchAgent se carga al iniciar sesión

¿Necesitas ayuda para configurar tu entorno? Prueba el AI Setup Assistant.

OpenClaw

OpenClaw Expert

Sigues atascado?

Si esta pagina no resolvio tu caso, pregunta a OpenClaw Expert para pasos concretos.