把 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
拿到真实的 DISPLAY、XAUTHORITY 和 DBUS_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 代理基础设施中比较实用的一种分工方式:主实例不必拥有所有能力,但必须知道如何安全调用外部能力。