跳转至

远程访问

OpenClaw 在一台主机上运行一个 Gateway(主节点),并将所有客户端连接到它。Gateway 拥有会话、认证配置、通道和状态;其他一切都是客户端。

  • 操作员(你,或 macOS 应用):当 Gateway 可达时,直接 LAN/Tailnet WebSocket 最简单;SSH 隧道是通用回退方案。
  • 节点(iOS/Android 和其他设备):连接到 Gateway WebSocket(LAN/tailnet 或 SSH 隧道)。

远程客户端可以通过 URL 或简短引用继续同一个由 Gateway 拥有的对话。参见 会话同步与附加。

核心思想

Gateway WebSocket 默认绑定到 loopback,端口为 18789(gateway.port)。用于远程访问时,可以通过 Tailscale Serve / 受信任的 LAN-Tailnet 绑定暴露它,或者通过 SSH 转发 loopback 端口。

拓扑选项

设置 Gateway 运行位置 最适合
你的 tailnet 中始终在线的 Gateway 持久主机(VPS 或家庭服务器),通过 Tailscale 或 SSH 访问 经常休眠但需要智能体始终在线的笔记本电脑。参见 exe.dev(简易 VM)或 Hetzner(生产 VPS)。
家庭台式机 台式机;笔记本电脑通过 macOS 应用的远程模式远程连接(设置 → 连接 → OpenClaw runs) 让智能体保持在持续通电的硬件上。运行手册:macOS 远程访问。
笔记本电脑 笔记本电脑,通过 SSH 隧道或 Tailscale Serve 安全暴露(保持 gateway.bind: "loopback") 单机器设置。参见 Tailscale 和 Web。

对于始终在线和笔记本电脑设置,建议保持 gateway.bind: "loopback",并为控制 UI 使用 Tailscale Serve,或使用受信任的 LAN/Tailnet 绑定配合 gateway.remote.transport: "direct"。SSH 隧道是从任何机器都能工作的回退方案。

应用预览需要它们自己的私有入口。仅转发 Gateway 端口的隧道不会转发门户。使用 托管私有 Serve 或通配符门户入口;浏览器和应用必须使用服务返回的门户 URL,而不替换其主机或端口。

命令流程(在哪里运行)

一个 Gateway 拥有状态和通道;节点是外设。示例(Telegram 消息路由到节点工具):

  1. Telegram 消息到达 Gateway。
  2. Gateway 运行 智能体,由它决定是否调用节点工具。
  3. Gateway 通过 Gateway WebSocket 调用 节点(node.invoke RPC)。
  4. 节点返回结果;Gateway 回复 Telegram。

节点不运行 Gateway 服务。每台主机应只运行一个 Gateway,除非你有意运行隔离配置(参见 多个网关)。macOS 应用的“节点模式”只是通过 Gateway WebSocket 的节点客户端。

SSH 隧道(CLI + 工具)

ssh -N -L 18789:127.0.0.1:18789 user@gateway-host

隧道建立后,openclaw health 和 openclaw status --deep 通过 ws://127.0.0.1:18789 访问远程 Gateway。openclaw gateway status、openclaw gateway health、openclaw gateway probe 和 openclaw gateway call 也可以通过 --url 指向转发后的 URL。

要在保持 Gateway 位于 loopback 的同时,用单个私有 wss:// 端点替代每个客户端的 SSH 隧道,请遵循 为你的 Gateway 提供稳定的 HTTPS URL。

Note

第一个端口是本地端口;最后一个端口是远程 Gateway 目标端口。为了保持 上面的本地 URL,只需将远程目标替换为你 配置的 gateway.port(或 --port / OPENCLAW_GATEWAY_PORT)。例如, ssh -N -L 18789:127.0.0.1:29443 user@gateway-host 通过相同的本地 URL 访问远程端口 29443 上的 Gateway。发现与引导使用此目标解析出的 Gateway 服务端口。

Warning

--url 永远不会回退到配置或环境凭据。请显式传递 --token 或 --password;如果没有它们,客户端不会发送凭据,如果目标 Gateway 需要认证,连接将失败。

CLI 远程默认值

持久化一个远程目标,使 CLI 命令默认使用它:

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

对于手动管理的 SSH 隧道,保持 URL 为 ws://127.0.0.1:18789,并先打开 隧道。对于客户端管理的隧道,设置 gateway.remote.sshTarget (user@host 或 user@host:port);gateway.remote.url 保持为本地隧道 URL。 macOS 应用使用相同的设置。如果远程端口与本地 端口不同,设置 gateway.remote.remotePort。

当配置的 loopback 远程 URL 具有 gateway.remote.sshTarget,且 传输方式不是 direct 时,CLI 客户端拥有 SSH 隧道,就像 macOS 应用一样。它们 会为所选 SSH 目标和远程 Gateway 端口缓存已配对设备凭据, 独立于分配的本地端口。当远程 Gateway 端口与 URL 中的端口不同时,设置 gateway.remote.remotePort。TUI/RPC 客户端 和诊断探针共享该凭据范围;配对后,诊断 不需要每次连接都使用共享 Token 或密码。客户端在 关闭时关闭其隧道,并且无法通过已释放的转发端口重新连接。 具有 sshTarget 的现有配置在升级时采用此客户端管理路由。若要保留手动管理的 转发,请设置 gateway.remote.transport: "direct"。

已固定的 wss:// 回环端点使用一种凭据范围,该范围还包含证书指纹。未识别的、手动转发的回环 URL 不能安全地复用仅为该 URL 保存的设备令牌:同一端口现在可能指向另一个 Gateway。请配置 SSH 目标或 TLS 固定值,并使用 gateway.remote.token / gateway.remote.password 注册所选路由,然后在该 Gateway 上批准配对。历史 URL-only 条目保持不变,绝不会静默重新分配到新路由。CLI 和环境变量 URL 覆盖会保留所选监听器,而不是启动已配置的 SSH 隧道,即使 URL 匹配也是如此。CLI --url 仍遵循上述显式凭据规则。SSH 别名及其 OpenSSH 配置仍然是由操作员拥有的路由选择,而不是加密 Gateway 标识符。重新分配已注册的 SSH 别名会保留其已保存凭据范围,因此其设备令牌可以发送到新选择的目的地。连接到不同 Gateway 时请使用新别名。

本地诊断优先使用其本地配对设备凭据;origin-cache 回退必须匹配本地 Gateway 的配对记录。非回环远程探测保留其现有精确 origin 缓存。这些更改使用现有凭据表,而不添加模式迁移。仅回退路由绑定会保留两套凭据完整。如果旧二进制文件拒绝独立升级的数据库模式,请恢复兼容的更新前状态;仅保留的令牌行本身不是数据库降级。

再次运行 openclaw configure --section gateway 或交互式入门,当保持相同 URL(忽略周围空白)时,会保留远程 TLS 指纹和传输设置。更改 URL 会清除这些端点设置。新确认的发现指纹仅替换已发现 URL 的保存固定值,并且你选择的身份验证方法仍然适用。接受发现的直接连接会选择直接传输。选择发现的 SSH 隧道会清除建议回环 URL 的已保存传输设置,该 URL 现在可能到达不同主机;请手动启动显示的隧道。

入门和 configure 就绪检查使用同一端点保存的 TLS 指纹。探测不同 URL 不会继承其证书固定值。

主机密钥验证默认严格(gateway.remote.sshHostKeyPolicy: "strict")。将其设置为 "openssh" 可改为委托给你的有效 OpenSSH 配置;启用前请检查用户和系统 SSH 设置。

对于已在受信任 LAN 或 Tailnet 上可达的 Gateway,请使用直接模式:

{
  gateway: {
    mode: "remote",
    remote: {
      transport: "direct",
      url: "ws://192.168.0.202:18789",
      token: "your-token",
    },
  },
}

身份感知代理后面的 Gateway

要从头以这种方式部署——隧道、Access 应用、Gateway 可信代理身份验证和节点路由——请参阅 Cloudflare Tunnel and Access。本节仅涵盖客户端:CLI、TUI 或应用如何向该边缘进行身份验证。

当身份感知代理必须在流量到达 Gateway 之前对 WebSocket 升级进行身份验证时,请使用 gateway.remote.edgeAuth。头部值是 SecretInput 字段,因此它们可以来自 env、file、exec 或 store 秘密提供程序,而无需将凭据直接放在配置中。

对于 Cloudflare Access,通用 exec 秘密提供程序可以从操作员安装的 cloudflared 二进制文件获取短期应用令牌:

{
  secrets: {
    providers: {
      "cloudflare-access": {
        source: "exec",
        command: "/usr/local/bin/cloudflared",
        args: ["access", "token", "-app=https://gateway.example"],
        jsonOnly: false,
        passEnv: ["HOME"],
        trustedDirs: ["/usr/local/bin"],
      },
    },
  },
  gateway: {
    mode: "remote",
    remote: {
      url: "wss://gateway.example",
      edgeAuth: {
        "Cf-Access-Token": {
          source: "exec",
          provider: "cloudflare-access",
          id: "token",
        },
      },
    },
  },
}

secrets.providers.*.command 必须是绝对路径;请将 /usr/local/bin/cloudflared 替换为主机上真实、非符号链接的安装位置,例如 Homebrew 前缀下解析后的可执行文件,并保持 trustedDirs 指向实际包含它的目录。

Exec 提供程序在清理后的环境中运行。cloudflared 从用户主目录读取其缓存的应用令牌,因此需要 passEnv: ["HOME"];没有它,提供程序会以非零退出,并且不会生成头部。请先运行一次 cloudflared access login <gateway-url>,以便存在可读的令牌。

对于 Cloudflare Access 服务令牌,请从任何受支持的秘密提供程序提供两个固定头部。此示例从基于环境的 SecretRefs 读取它们:

{
  secrets: {
    providers: {
      default: { source: "env" },
    },
  },
  gateway: {
    mode: "remote",
    remote: {
      url: "wss://gateway.example",
      edgeAuth: {
        "CF-Access-Client-Id": {
          source: "env",
          provider: "default",
          id: "CF_ACCESS_CLIENT_ID",
        },
        "CF-Access-Client-Secret": {
          source: "env",
          provider: "default",
          id: "CF_ACCESS_CLIENT_SECRET",
        },
      },
    },
  },
}

OpenClaw 的 Gateway 连接代码本身从不运行 cloudflared,也没有 Cloudflare 依赖项或登录流程。只有通用 exec 秘密提供程序会调用操作员配置的确切命令。解析后的 edge-auth 头部仅在目标匹配配置的 gateway.remote.url 范围时发送,仅在 wss:// 上发送,并且从不跨重定向发送。

凭据优先级

Gateway 凭据解析在 call/probe/status 路径和 Discord exec-approval 监控中遵循一个共享契约。Node-host 使用相同契约,但有一个本地模式例外(它忽略 gateway.remote.*)。

  • 显式凭据(--token、--password 或工具的 gatewayToken)在接受显式认证的调用路径上始终优先。
  • URL 覆盖安全性:
  • CLI --url 从不复用隐式配置/环境变量凭据。
  • 环境变量 OPENCLAW_GATEWAY_URL 只能使用环境变量凭据(OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD)。
  • 本地模式默认值:
  • token:gateway.auth.token -> OPENCLAW_GATEWAY_TOKEN -> gateway.remote.token(仅当本地 token 未设置时才回退到远程)
  • password:gateway.auth.password -> OPENCLAW_GATEWAY_PASSWORD -> gateway.remote.password(仅当本地 password 未设置时才回退到远程)
  • 远程模式默认值:
  • token:gateway.remote.token -> OPENCLAW_GATEWAY_TOKEN -> gateway.auth.token
  • password:OPENCLAW_GATEWAY_PASSWORD -> gateway.remote.password -> gateway.auth.password
  • Node-host 本地模式例外:环境变量凭据仍保持第一优先级,并且忽略 gateway.remote.token / gateway.remote.password,因为 node 命令指向显式的主机和端口。
  • 支持 SecretRef 的远程启动/状态/向导探测会将已配置的 gateway.remote.token 和 gateway.remote.password 视为针对已配置目标的权威凭据。仅当两个远程凭据都未配置时,才会考虑环境中的凭据。如果已配置的远程 SecretRef 无法解析,探测会发出警告,并且不会回退到环境变量凭据;单独配置的、可成功解析的同级凭据仍然可用。
  • Gateway 环境变量覆盖仅使用 OPENCLAW_GATEWAY_*。

聊天 UI 远程访问

WebChat 没有单独的 HTTP 端口;SwiftUI 聊天 UI 直接连接到 Gateway WebSocket。

  • 通过 SSH 转发 18789(见上文),然后将客户端连接到 ws://127.0.0.1:18789。
  • 对于 LAN/Tailnet 直连模式,将客户端连接到已配置的私有 ws:// 或安全 wss:// URL。
  • 在 macOS 上,应用的远程模式会自动管理所选传输方式。

macOS 应用远程模式

macOS 菜单栏应用端到端驱动相同的设置:远程状态检查、WebChat 以及 Voice Wake 转发。操作手册:macOS 远程访问。

安全规则(远程/VPN)

除非确定需要绑定,否则保持 Gateway 仅限回环。

  • 回环 + SSH/Tailscale Serve 是最安全的默认方式(无公开暴露)。
  • 明文 ws:// 仅接受回环、私有/LAN(RFC 1918)、链路本地、CGNAT、.local 和 .ts.net 主机。公共远程主机必须使用 wss://。
  • 非回环绑定(lan/tailnet/custom,或在回环不可用时使用 auto)必须使用 Gateway 认证:token、password,或具有身份感知能力的反向代理,并设置 gateway.auth.mode: "trusted-proxy"。
  • gateway.remote.token / .password 是客户端凭据来源;它们本身不会配置服务器认证。
  • 本地调用路径只有在 gateway.auth.* 未设置时,才能将 gateway.remote.* 用作回退。
  • 如果 gateway.auth.token / gateway.auth.password 通过 SecretRef 显式配置且未解析,则解析失败关闭(不会用远程回退掩盖)。
  • gateway.remote.tlsFingerprint 为 wss:// 固定远程 TLS 证书,包括操作员/控制流量以及 macOS 直连模式中的伴随节点。如果没有存储的固定值,macOS 仅在正常系统信任通过后于首次使用时固定;自签名或私有 CA Gateway 需要显式指纹或 Remote over SSH。
  • 当 gateway.auth.allowTailscale: true 时,Tailscale Serve 可以通过身份头认证 Control UI/WebSocket 流量。HTTP API 端点不使用该头认证,而是遵循 Gateway 的正常 HTTP 认证模式。这种无 token 流程假定 Gateway 主机可信;如需在所有位置使用共享密钥认证,请将其设置为 false。
  • Trusted-proxy 认证默认期望非回环身份感知代理。同主机回环反向代理需要显式设置 gateway.auth.trustedProxy.allowLoopback = true。
  • 将浏览器控制视为操作员访问:仅限 tailnet,加上有意的节点配对。

深入阅读:安全。

macOS:通过 LaunchAgent 建立持久 SSH 隧道

对于 macOS 客户端,最简单的持久设置是使用 SSH LocalForward 配置项,外加一个 LaunchAgent,使隧道在重启和崩溃后保持存活。

步骤 1:添加 SSH 配置

编辑 ~/.ssh/config:

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

将 <REMOTE_IP> 和 <REMOTE_USER> 替换为你的值。

步骤 2:复制 SSH 密钥(一次性)

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

步骤 3:配置网关令牌

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

Gateway 接受其已配置的密钥,无论放在哪个字段:gateway.remote.token 或 gateway.remote.password 均可使用,包括针对 password 模式 Gateway。服务器的 gateway.auth.mode 选择使用哪个已配置的密钥。OPENCLAW_GATEWAY_TOKEN 仍然可作为 shell 级覆盖有效,但持久的远程客户端设置是 gateway.remote.token / gateway.remote.password。

步骤 4:创建 LaunchAgent

保存为 ~/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>

步骤 5:加载 LaunchAgent

launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.ssh-tunnel.plist

隧道会在登录时自动启动,在崩溃时重启,并保持转发端口处于活动状态。

设置完成后,打开或重新打开 OpenClaw.app,然后使用 macOS 远程访问 检查项来验证连接。

Note

如果旧配置中残留了 com.openclaw.ssh-tunnel LaunchAgent,请卸载并删除它。

故障排除

# Check if the tunnel is running
ps aux | grep "ssh -N remote-gateway" | grep -v grep
lsof -i :18789

# Restart the tunnel
launchctl kickstart -k gui/$UID/ai.openclaw.ssh-tunnel

# Stop the tunnel
launchctl bootout gui/$UID/ai.openclaw.ssh-tunnel
配置项 作用
LocalForward 18789 127.0.0.1:18789 将本地端口 18789 转发到远程端口 18789
ssh -N 不执行远程命令的 SSH(仅端口转发)
KeepAlive 如果隧道崩溃,则自动重启隧道
RunAtLoad 登录时 LaunchAgent 加载后启动隧道

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw