---
read_when:
    - Ejecutar o solucionar problemas de configuraciones remotas de Gateway
summary: Acceso remoto mediante túneles SSH (Gateway WS) y redes tailnet
title: Acceso remoto
x-i18n:
    generated_at: "2026-05-06T05:35:42Z"
    model: gpt-5.5
    provider: openai
    source_hash: c6272f4ee9fa52091d461cd70be05ccf01c209c3b26fe98a71752f6ea86ea448
    source_path: gateway/remote.md
    workflow: 16
---

Este repositorio admite "remoto por 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 alternativa universal.
- Para **nodos (iOS/Android y dispositivos futuros)**: conéctate al **WebSocket** del Gateway (LAN/tailnet o túnel SSH según sea necesario).

## La idea central

- El WebSocket del Gateway se vincula a **loopback** en el puerto configurado (18789 de forma predeterminada).
- Para uso remoto, reenvías ese puerto loopback por SSH (o usas una tailnet/VPN y menos túneles).

## Configuraciones comunes de VPN y tailnet

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

### Gateway siempre activo en tu tailnet

Ejecuta el Gateway en un host persistente (VPS o servidor doméstico) y accede a él mediante **Tailscale** o SSH.

- **Mejor UX:** conserva `gateway.bind: "loopback"` y usa **Tailscale Serve** para la interfaz de control.
- **Alternativa:** conserva loopback más un túnel SSH desde cualquier máquina que necesite acceso.
- **Ejemplos:** [exe.dev](/es/install/exe-dev) (VM sencilla) o [Hetzner](/es/install/hetzner) (VPS de producción).

Ideal cuando tu laptop entra en reposo con frecuencia, pero quieres que el agente esté siempre activo.

### El escritorio doméstico ejecuta el Gateway

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

- Usa el modo **Remoto por SSH** de la app de macOS (Configuración → General → OpenClaw se ejecuta).
- La app abre y gestiona el túnel, por lo que WebChat y las comprobaciones de estado funcionan sin más.

Runbook: [acceso remoto en macOS](/es/platforms/mac/remote).

### La laptop ejecuta el Gateway

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

- Túnel SSH hacia la laptop desde otras máquinas, o
- Tailscale Serve para la interfaz de control y conserva el Gateway solo en loopback.

Guías: [Tailscale](/es/gateway/tailscale) y [resumen web](/es/web).

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

Un servicio de Gateway es dueño del estado + canales. Los nodos son periféricos.

Ejemplo de flujo (Telegram → nodo):

- Un mensaje de Telegram llega al **Gateway**.
- El Gateway ejecuta el **agente** y decide si llamar a una herramienta de nodo.
- El Gateway llama al **nodo** por el WebSocket del Gateway (RPC `node.*`).
- El nodo devuelve el resultado; el Gateway responde de vuelta a Telegram.

Notas:

- **Los nodos no ejecutan el servicio de gateway.** Solo debería ejecutarse un gateway por host, salvo que ejecutes perfiles aislados intencionalmente (consulta [Múltiples gateways](/es/gateway/multiple-gateways)).
- El "modo nodo" de la app de macOS es solo un cliente de nodo sobre el WebSocket del Gateway.

## Túnel SSH (CLI + herramientas)

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

```bash
ssh -N -L 18789:127.0.0.1:18789 user@host
```

Con el túnel activo:

- `openclaw health` y `openclaw status --deep` ahora 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 la URL reenviada mediante `--url` cuando sea necesario.

<Note>
Reemplaza `18789` por tu `gateway.port` configurado (o `--port` u `OPENCLAW_GATEWAY_PORT`).
</Note>

<Warning>
Cuando pasas `--url`, la CLI no recurre a credenciales de configuración o entorno. Incluye `--token` o `--password` explícitamente. La falta de credenciales explícitas es un error.
</Warning>

## Valores remotos predeterminados de la CLI

Puedes persistir un destino remoto para que los comandos de la CLI lo usen de forma predeterminada:

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

Cuando el gateway es solo loopback, conserva la URL en `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, los nombres de host de gateway descubiertos pertenecen a
`gateway.remote.sshTarget`; `gateway.remote.url` sigue siendo la URL del túnel local.

## Precedencia de credenciales

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

- Las credenciales explícitas (`--token`, `--password` o la herramienta `gatewayToken`) siempre ganan en las rutas de llamada que aceptan autenticación explícita.
- Seguridad de anulación de URL:
  - Las anulaciones de URL de la CLI (`--url`) nunca reutilizan credenciales implícitas de configuración/entorno.
  - Las anulaciones de URL de entorno (`OPENCLAW_GATEWAY_URL`) pueden usar solo credenciales de entorno (`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`).
- Valores predeterminados de modo local:
  - token: `OPENCLAW_GATEWAY_TOKEN` -> `gateway.auth.token` -> `gateway.remote.token` (la alternativa remota se aplica solo cuando la entrada de token de autenticación local no está definida)
  - password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway.auth.password` -> `gateway.remote.password` (la alternativa remota se aplica solo cuando la entrada de contraseña de autenticación local no está definida)
- Valores predeterminados de 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 de Node-host: `gateway.remote.token` / `gateway.remote.password` se ignoran.
- Las comprobaciones de token de probe/status remotas son estrictas de forma predeterminada: usan solo `gateway.remote.token` (sin alternativa de token local) al apuntar al modo remoto.
- Las anulaciones de entorno del Gateway usan solo `OPENCLAW_GATEWAY_*`.

## Interfaz de chat por SSH

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

- Reenvía `18789` por SSH (consulta arriba) y luego conecta los clientes a `ws://127.0.0.1:18789`.
- En macOS, prefiere el modo "Remoto por SSH" de la app, que gestiona el túnel automáticamente.

## Remoto por SSH en la app de macOS

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

Runbook: [acceso remoto en macOS](/es/platforms/mac/remote).

## Reglas de seguridad (remoto/VPN)

Versión corta: **mantén el Gateway solo en loopback** salvo que tengas claro que necesitas un bind.

- **Loopback + SSH/Tailscale Serve** es el valor predeterminado más seguro (sin exposición pública).
- El texto sin cifrar `ws://` es solo loopback de forma predeterminada. Para redes privadas de confianza,
  establece `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` en el proceso cliente como
  medida de emergencia. No hay equivalente en `openclaw.json`; esto debe estar en el
  entorno de proceso del cliente que realiza la conexión WebSocket.
- Los **binds que no son loopback** (`lan`/`tailnet`/`custom`, o `auto` cuando loopback no está disponible) deben usar autenticación del gateway: token, contraseña o un proxy inverso consciente de identidad con `gateway.auth.mode: "trusted-proxy"`.
- `gateway.remote.token` / `.password` son fuentes de credenciales de cliente. **No** configuran la autenticación del servidor por sí mismos.
- Las rutas de llamada locales pueden usar `gateway.remote.*` como alternativa 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 de forma cerrada (sin enmascaramiento por alternativa remota).
- `gateway.remote.tlsFingerprint` fija el certificado TLS remoto al usar `wss://`.
- **Tailscale Serve** puede autenticar el tráfico de la interfaz de control/WebSocket mediante encabezados de identidad
  cuando `gateway.auth.allowTailscale: true`; los endpoints de la API HTTP no
  usan esa autenticación de encabezado de Tailscale y en su lugar siguen el modo
  normal de autenticación HTTP del gateway. Este flujo sin token asume que el host del gateway es de confianza. Establécelo en
  `false` si quieres autenticación con secreto compartido en todas partes.
- La autenticación **trusted-proxy** espera configuraciones de proxy consciente de identidad que no sean loopback de forma predeterminada.
  Los proxies inversos loopback en el mismo host requieren `gateway.auth.trustedProxy.allowLoopback = true` explícito.
- Trata el control del navegador como acceso de operador: solo tailnet + emparejamiento deliberado de nodos.

Análisis detallado: [Seguridad](/es/gateway/security).

### macOS: túnel SSH persistente mediante LaunchAgent

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

#### Paso 1: agrega la configuración SSH

Edita `~/.ssh/config`:

```ssh
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>` por tus valores.

#### Paso 2: copia la clave SSH (una vez)

```bash
ssh-copy-id -i ~/.ssh/id_rsa <REMOTE_USER>@<REMOTE_IP>
```

#### Paso 3: configura el token del gateway

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

```bash
openclaw config set gateway.remote.token "<your-token>"
```

#### Paso 4: crea el LaunchAgent

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

```xml
<?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>
```

#### Paso 5: carga el LaunchAgent

```bash
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 reenviado.

<Note>
Si tienes un LaunchAgent `com.openclaw.ssh-tunnel` sobrante de una configuración anterior, descárgalo y elimínalo.
</Note>

#### Solución de problemas

Comprueba si el túnel está en ejecución:

```bash
ps aux | grep "ssh -N remote-gateway" | grep -v grep
lsof -i :18789
```

Reinicia el túnel:

```bash
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel
```

Detén el túnel:

```bash
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
```

| 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 automáticamente el túnel si falla                   |
| `RunAtLoad`                          | Inicia el túnel cuando el LaunchAgent se carga al iniciar sesión |

## Relacionado

- [Tailscale](/es/gateway/tailscale)
- [Autenticación](/es/gateway/authentication)
- [Configuración de gateway remoto](/es/gateway/remote-gateway-readme)
