- Operadores (tú, o la app de macOS): el WebSocket directo por LAN/Tailnet es lo más simple cuando el Gateway es alcanzable; el túnel SSH es la alternativa universal.
- Nodos (iOS/Android y otros dispositivos): se conectan al WebSocket del Gateway (LAN/tailnet o túnel SSH).
La idea central
El WebSocket del Gateway se enlaza a loopback de forma predeterminada, en el puerto18789 (gateway.port). Para uso remoto, exponlo mediante Tailscale Serve / un enlace LAN-Tailnet de confianza, o reenvía el puerto loopback por SSH.
Opciones de topología
| Configuración | Dónde se ejecuta el Gateway | Ideal para |
|---|---|---|
| Gateway siempre activo en tu tailnet | Host persistente (VPS o servidor doméstico), accesible vía Tailscale o SSH | Portátiles que entran en suspensión a menudo pero necesitan que el agente esté siempre activo. Consulta exe.dev (VM fácil) o Hetzner (VPS de producción). |
| Escritorio doméstico | Escritorio; el portátil se conecta de forma remota mediante el modo remoto de la app de macOS (Settings → Connection → OpenClaw runs) | Mantener el agente en hardware que permanece encendido. Guía operativa: acceso remoto en macOS. |
| Portátil | Portátil, expuesto de forma segura mediante túnel SSH o Tailscale Serve (mantén gateway.bind: "loopback") | Configuraciones de una sola máquina. Consulta Tailscale y Web. |
gateway.bind: "loopback" y usar Tailscale Serve para la interfaz de usuario de control, o un enlace LAN/Tailnet de confianza con gateway.remote.transport: "direct". El túnel SSH es la alternativa que funciona desde cualquier máquina.
Flujo de comandos (qué se ejecuta dónde)
Un Gateway es propietario del estado y los canales; los nodos son periféricos. Ejemplo (mensaje de Telegram enrutado a una herramienta de nodo):- El mensaje de Telegram llega al Gateway.
- El Gateway ejecuta el agente, que decide si llamar a una herramienta de nodo.
- El Gateway llama al nodo mediante el WebSocket del Gateway (RPC
node.invoke). - El nodo devuelve el resultado; el Gateway responde a Telegram.
Túnel SSH (CLI + herramientas)
openclaw health y openclaw status --deep alcanzan el Gateway remoto mediante ws://127.0.0.1:18789. openclaw gateway status, openclaw gateway health, openclaw gateway probe y openclaw gateway call también pueden apuntar a una URL reenviada mediante --url.
Sustituye
18789 por tu gateway.port configurado (o --port / OPENCLAW_GATEWAY_PORT).Valores predeterminados remotos de la CLI
Persiste un destino remoto para que los comandos de CLI lo usen de forma predeterminada:ws://127.0.0.1:18789 y abre primero el túnel SSH. En el transporte de túnel SSH de la app de macOS, el nombre de host del Gateway descubierto va en gateway.remote.sshTarget (user@host o user@host:port); gateway.remote.url permanece como la URL del túnel local. Si el puerto remoto difiere del local, configura gateway.remote.remotePort.
La verificación de clave de host es estricta de forma predeterminada (gateway.remote.sshHostKeyPolicy: "strict"). Configúrala en "openssh" para delegar en tu configuración efectiva de OpenSSH; revisa tus ajustes SSH de usuario y sistema antes de habilitarlo.
Para un Gateway ya accesible en una LAN o Tailnet de confianza, usa el modo directo:
Precedencia de credenciales
La resolución de credenciales del Gateway sigue un contrato compartido en las rutas call/probe/status y en la monitorización de aprobación de ejecución de Discord. Node-host usa el mismo contrato con una excepción de modo local (ignoragateway.remote.*).
- Las credenciales explícitas (
--token,--passwordo elgatewayTokende una herramienta) siempre tienen prioridad en las rutas de llamada que aceptan autenticación explícita. - Seguridad de sobrescritura de URL:
- La CLI
--urlnunca reutiliza credenciales implícitas de configuración/entorno. - Env
OPENCLAW_GATEWAY_URLpuede usar solo credenciales de entorno (OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD).
- La CLI
- Valores predeterminados del modo local:
- token:
OPENCLAW_GATEWAY_TOKEN->gateway.auth.token->gateway.remote.token(alternativa remota solo cuando el token local no está configurado) - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.auth.password->gateway.remote.password(alternativa remota solo cuando la contraseña local no está configurada)
- token:
- Valores predeterminados del modo remoto:
- token:
gateway.remote.token->OPENCLAW_GATEWAY_TOKEN->gateway.auth.token - password:
OPENCLAW_GATEWAY_PASSWORD->gateway.remote.password->gateway.auth.password
- token:
- Excepción de modo local de Node-host:
gateway.remote.token/gateway.remote.passwordse ignoran. - Las comprobaciones de token de probe/status remotos son estrictas de forma predeterminada: usan solo
gateway.remote.token(sin alternativa de token local) cuando apuntan al modo remoto. - Las sobrescrituras de entorno del Gateway usan solo
OPENCLAW_GATEWAY_*.
Acceso remoto a la interfaz de chat
WebChat no tiene un puerto HTTP separado; la interfaz de chat SwiftUI se conecta directamente al WebSocket del Gateway.- Reenvía
18789por SSH (ver arriba) y luego conecta los clientes aws://127.0.0.1:18789. - Para el modo directo LAN/Tailnet, conecta los clientes a la URL privada
ws://o segurawss://configurada. - En macOS, el modo remoto de la app gestiona automáticamente el transporte seleccionado.
Modo remoto de la app de macOS
La app de barra de menú de macOS gestiona la misma configuración de extremo a extremo: comprobaciones de estado remoto, WebChat y reenvío de Voice Wake. Guía operativa: acceso remoto en macOS.Reglas de seguridad (remoto/VPN)
Mantén el Gateway solo en loopback salvo que tengas claro que necesitas un enlace.- Loopback + SSH/Tailscale Serve es el valor predeterminado más seguro (sin exposición pública).
ws://en texto claro se acepta para loopback, privada/LAN (RFC 1918), link-local, CGNAT, hosts.localy.ts.net. Los hosts remotos públicos deben usarwss://.- Los enlaces que no son loopback (
lan/tailnet/custom, oautocuando loopback no está disponible) deben usar autenticación de Gateway: token, contraseña o un proxy inverso consciente de identidad congateway.auth.mode: "trusted-proxy". gateway.remote.token/.passwordson fuentes de credenciales de cliente; por sí solas no configuran la autenticación del servidor.- Las rutas de llamada locales pueden usar
gateway.remote.*como alternativa solo cuandogateway.auth.*no está configurado. - Si
gateway.auth.token/gateway.auth.passwordse configura explícitamente mediante SecretRef y no se resuelve, la resolución falla cerrada (sin enmascaramiento por alternativa remota). gateway.remote.tlsFingerprintfija el certificado TLS remoto parawss://, incluido el modo directo de macOS. Sin un pin almacenado, macOS solo fija en el primer uso después de que pase la confianza normal del sistema; los Gateways autofirmados o con CA privada necesitan una huella explícita o remoto por SSH.- Tailscale Serve puede autenticar el tráfico de la interfaz de usuario de control/WebSocket mediante encabezados de identidad cuando
gateway.auth.allowTailscale: true. Los endpoints de la API HTTP no usan esa autenticación por encabezado y, en su lugar, siguen el modo de autenticación HTTP normal del Gateway. Este flujo sin token asume que el host del Gateway es de confianza; configúralo enfalsepara autenticación con secreto compartido en todas partes. - La autenticación trusted-proxy espera de forma predeterminada un proxy consciente de identidad que no sea loopback. Los proxies inversos loopback en el mismo host requieren
gateway.auth.trustedProxy.allowLoopback = trueexplícito. - Trata el control desde navegador como acceso de operador: solo tailnet y emparejamiento de nodos deliberado.
macOS: túnel SSH persistente mediante LaunchAgent
Para clientes macOS, la configuración persistente más sencilla usa una entrada de configuración SSHLocalForward más un LaunchAgent que mantiene el túnel activo entre reinicios y fallos.
Paso 1: añadir configuración SSH
Edita~/.ssh/config:
<REMOTE_IP> y <REMOTE_USER> por tus valores.
Paso 2: copiar la clave SSH (una sola vez)
Paso 3: configurar el token del gateway
gateway.remote.password en su lugar si el Gateway remoto usa autenticación por contraseña. OPENCLAW_GATEWAY_TOKEN sigue siendo válido como sobrescritura a nivel de shell, pero la configuración duradera de cliente remoto es gateway.remote.token / gateway.remote.password.
Paso 4: crear el LaunchAgent
Guarda como~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist:
Paso 5: cargar el LaunchAgent
Si tienes un LaunchAgent
com.openclaw.ssh-tunnel sobrante de una configuración anterior, descárgalo y elimínalo.Solución de problemas
| Entrada de configuración | Qué hace |
|---|---|
LocalForward 18789 127.0.0.1:18789 | Reenvía el puerto local 18789 al puerto remoto 18789 |
ssh -N | SSH sin ejecutar comandos remotos (solo reenvío de puertos) |
KeepAlive | Reinicia el túnel automáticamente si falla |
RunAtLoad | Inicia el túnel cuando el LaunchAgent se carga al iniciar sesión |