把 OpenClaw 主实例迁移到树莓派之后,一个问题很快出现:主实例已经在树莓派上运行,但完整桌面浏览器仍然在桌面 Linux 主机上。

树莓派适合承担长期在线的 OpenClaw gateway、消息通道和主工作区,但它并不适合作为完整图形浏览器主机。桌面机已经具备图形环境、浏览器、用户会话和更强的桌面交互能力,因此更适合继续提供浏览器/CDP 能力。

这就形成了一种分离式结构:

树莓派:
- OpenClaw 主实例
- gateway
- 消息通道
- 主工作区
- 通过 SSH 调用外部资源

桌面机:
- 图形桌面环境
- Brave 浏览器
- 专用浏览器 profile
- CDP 端口

本篇记录的是:如何让运行在树莓派上的 OpenClaw,按需调用桌面机上的 Brave 浏览器。

为什么不直接在树莓派上运行浏览器

理论上,可以在树莓派上安装 Chromium 或 Brave,再让 OpenClaw 直接使用本机浏览器。但实际并不一定合适。

原因包括:

- 树莓派存储容量有限
- 图形环境可能不完整
- 浏览器 profile 体积可能较大
- 浏览器运行时资源消耗明显
- 某些网页自动化更适合在完整桌面环境下运行
- 已有浏览器授权、cookie、扩展和环境可能在桌面机上

对一个长期运行的 AI 代理系统来说,主实例和浏览器并不一定要在同一台机器上。

更合理的结构是:

主实例负责调度
桌面机负责浏览器执行
SSH tunnel 负责连接
CDP 负责控制浏览器

这样,树莓派保持轻量稳定,桌面机只在需要时提供浏览器能力。

CDP 是什么角色

CDP,即 Chrome DevTools Protocol,是 Chromium 系浏览器提供的远程调试和自动化接口。Brave 基于 Chromium,因此也可以通过 CDP 被自动化工具连接。

浏览器启动时指定 remote debugging 参数,例如:

--remote-debugging-address=127.0.0.1
--remote-debugging-port=****

浏览器就会在本机提供一个 CDP endpoint。访问:

http://127.0.0.1:****/json/version

如果返回包含 webSocketDebuggerUrl 的 JSON,就说明 CDP 接口可用。

OpenClaw 或其他自动化工具并不是“看见屏幕再点击”,而是通过这个 CDP endpoint 控制浏览器页面、读取 DOM、打开 URL、执行脚本或抓取信息。

为什么 CDP 只监听 127.0.0.1

CDP 权限非常高。拥有 CDP 访问权的程序,通常可以读取网页内容、操作标签页、执行脚本,甚至间接访问已登录的网站状态。

因此,CDP 不应该直接暴露到局域网或公网。

正确做法是让桌面机上的 Brave 只监听本机回环地址:

127.0.0.1:****

这样,局域网内其他机器无法直接访问桌面机的 CDP 端口。即使桌面机防火墙没有开放 ****,也不影响本机浏览器正常启动。

需要远程访问时,不开放端口,而是通过 SSH tunnel:

树莓派 127.0.0.1:****
  -> SSH tunnel
  -> 桌面机 127.0.0.1:****

这种方式的好处是:

- CDP 不暴露到局域网
- 不需要开放桌面机防火墙 ****
- 访问权限由 SSH 控制
- 树莓派可以像访问本机端口一样访问远程浏览器

整体连接结构

最终连接结构如下:

OpenClaw 主实例
  -> 访问树莓派本机 http://127.0.0.1:****
  -> SSH tunnel
  -> 桌面机 http://127.0.0.1:****
  -> Brave CDP
  -> 可见浏览器窗口或 headless 浏览器

树莓派上的 OpenClaw 只需要知道一个本地 endpoint:

http://127.0.0.1:****

它不需要直接知道桌面机浏览器内部如何启动,也不需要让 CDP 暴露在局域网。

SSH tunnel 的作用

SSH tunnel 的作用是把远程主机上的本地端口映射成本机端口。

抽象命令如下:

ssh -fN \
  -L 127.0.0.1:****:127.0.0.1:**** \
  <desktop-user>@<desktop-host>

含义是:

树莓派本机 127.0.0.1:****
转发到
桌面机本机 127.0.0.1:****

建立成功后,在树莓派上访问:

http://127.0.0.1:****/json/version

实际访问的是桌面机上 Brave 的:

http://127.0.0.1:****/json/version

如果返回 JSON,并包含 webSocketDebuggerUrl,说明远程浏览器链路已经打通。

为什么不需要打开桌面机防火墙

很多人在看到“树莓派要访问桌面机浏览器端口”时,会自然想到打开桌面机防火墙。

但在这个结构里不需要。

因为树莓派并不是直接访问:

<desktop-host>:****

而是访问:

树莓派本机 127.0.0.1:****

真正跨主机的是 SSH 连接。只要树莓派能够 SSH 到桌面机,tunnel 就能把桌面机本机的**** 代理到树莓派本机的 ****。

因此,桌面机防火墙只需要允许 SSH。CDP 端口不需要开放,也不应该开放。

专用浏览器 profile

为了避免影响用户日常浏览器,OpenClaw 应该使用独立的浏览器 profile。

例如:

<desktop-cdp-dir>/user-data

启动 Brave 时指定:

--user-data-dir=<desktop-cdp-dir>/user-data

这样,OpenClaw 使用的是专用 profile,而不是用户日常使用的普通 Brave profile。

专用 profile 的好处是:

- cookie 和登录状态与普通浏览器隔离
- 扩展和设置可单独维护
- 自动化任务不会污染普通浏览器历史
- 关闭或重启专用浏览器时不应影响普通浏览器

需要特别强调的是:专用 profile 和普通 Brave 使用的是同一个 Brave 程序本体。不能通过 /usr/bin/brave/opt/brave-bin/brave 判断某个进程是不是 OpenClaw 专用浏览器。唯一可靠依据是命令行中是否包含专用 --user-data-dir

这一点会在后续权限边界篇中单独展开。

按需启动,而不是常驻服务

远程浏览器能力不一定需要做成 systemd 常驻服务。

一开始很容易想到:

让桌面机开机自启 Brave CDP
让树莓派开机自启 SSH tunnel

这样确实可以让浏览器随时可用,但也带来问题:

- 桌面上会自动弹出浏览器窗口
- 用户关闭后可能被 systemd 自动拉起
- 浏览器变成常驻服务,影响桌面体验
- 故障时更难判断是谁启动的

对于按需浏览器任务,更合理的方式是:

1. OpenClaw 需要浏览器时,先检测桌面机是否在线
2. 桌面机在线,则通过 SSH 启动专用 Brave
3. 在树莓派上建立 SSH tunnel
4. 使用 http://127.0.0.1:**** 访问 CDP
5. 任务结束后,不自动删除 profile
6. 是否关闭专用浏览器由明确规则决定

这样,浏览器不会无缘无故常驻,也不会在用户关闭窗口后自动复活。

启动前先检测桌面机是否在线

由于浏览器能力依赖桌面机,使用前必须先检查桌面机是否在线。

抽象流程是:

ssh -o BatchMode=yes -o ConnectTimeout=5 <desktop-user>@<desktop-host> 'echo online'

如果 SSH 不通,应该直接报告:

桌面机当前不在线或 SSH 无法连接,因此无法使用远程浏览器。

不应该继续尝试浏览器启动,也不应该把失败误判为网页问题、模型问题或 OpenClaw 插件问题。

远程浏览器是外部资源。外部资源不可用时,应当明确失败原因。

可见窗口启动:关键在图形会话环境

在桌面机上通过 SSH 启动可见浏览器窗口,并不等同于在本机终端里运行浏览器。

因为 SSH session 默认不一定拥有桌面图形会话的环境变量。可见窗口通常依赖:

DISPLAY
XAUTHORITY
DBUS_SESSION_BUS_ADDRESS

如果这些变量不正确,浏览器可能无法显示窗口,或者出现 X 授权问题。

比较可靠的做法是从桌面机当前图形会话中读取真实环境变量,例如:

systemctl --user show-environment

或者从桌面进程环境中读取:

kwin_x11
plasmashell

拿到真实的 DISPLAYXAUTHORITYDBUS_SESSION_BUS_ADDRESS 后,再通过 SSH 启动 Brave。

这一步很关键。否则,浏览器可能实际启动失败,或者只能退回 headless 模式。

可见模式和 headless 模式不是一回事

Brave 可以用两种方式运行:

可见模式:
- 桌面上真的出现浏览器窗口
- 使用图形会话
- 适合验证桌面浏览器是否被正确远程启动

headless 模式:
- 没有可见窗口
- 仍然运行 Brave 进程
- 仍然可以提供 CDP
- 适合后台网页访问或抓取

headless 不是 OpenClaw 内置浏览器,也不是另一套浏览器。它仍然可以是桌面机上的 Brave,只是以无窗口模式运行。

但它不能替代“可见窗口启动测试”。

如果目标是验证 OpenClaw 能否远程打开桌面机上的可见浏览器,那么可见窗口启动失败时,不应该自动改用:

--headless=new

正确行为应该是报告:

可见浏览器启动失败,原因可能是图形会话授权或环境变量问题。没有改用 headless。

只有用户明确允许 headless 时,才应该切换到 headless 模式。

验收标准

远程浏览器能力是否成功,不能只看“有没有进程”。

至少应该满足以下检查:

1. 桌面机 SSH 在线
2. Brave 使用专用 profile 启动
3. Mars 本机 CDP endpoint 可用
4. 树莓派本机 tunnel endpoint 可用
5. /json/version 返回 webSocketDebuggerUrl
6. OpenClaw 使用的是树莓派本机 127.0.0.1:****
7. 如果是可见模式,桌面机上确实出现可见窗口
8. 没有暴露 **** 到局域网

其中,/json/version 是最直接的技术验收点。只要树莓派访问本机转发端口能拿到 JSON,就说明 CDP 链路已打通。

可见窗口是否出现,则用于确认图形会话和 X 授权是否正确。

Dashboard 场景下的一个延伸问题

迁移到树莓派后,Dashboard 命令可能只在终端里打印本机 URL,而树莓派没有浏览器。

这不是问题。

树莓派上的 Dashboard 入口可以通过:

- 反向代理域名
- SSH tunnel
- 内网访问

在其他机器的浏览器中打开。

需要注意的是,如果命令打印的是:

http://127.0.0.1:<port>/

这个地址里的 127.0.0.1 属于树莓派,不属于桌面机。因此不能直接把这个地址复制到桌面机浏览器里使用,除非已经建立了对应的 tunnel 或替换成可访问的反向代理地址。

这和 CDP tunnel 是同一个原则:127.0.0.1 永远是“当前机器自己”。

小结

远程浏览器能力的核心不是“在树莓派上装一个浏览器”,而是让树莓派上的 OpenClaw 能够安全、按需地调用桌面机上的 Brave。

完整结构可以总结为:

OpenClaw 主实例在树莓派
Brave 浏览器在桌面机
CDP 只监听桌面机 127.0.0.1
SSH tunnel 映射到树莓派 127.0.0.1
OpenClaw 使用 http://127.0.0.1:****

这套结构有几个关键原则:

- 不开放 CDP 到局域网
- 不需要打开桌面机 **** 防火墙
- 不让浏览器开机自启
- 不让浏览器作为 systemd 常驻服务自动复活
- 使用专用 profile
- 启动前检查桌面机在线
- 可见窗口需要读取真实图形会话环境
- headless 不能偷偷替代可见窗口测试

通过这种方式,树莓派可以继续保持轻量稳定,桌面机则按需提供浏览器、图形环境和 CDP 自动化能力。

这也是本地 AI 代理基础设施中比较实用的一种分工方式:主实例不必拥有所有能力,但必须知道如何安全调用外部能力。

Leave a Reply

Your email address will not be published. Required fields are marked *