Linux Browser Runtime

在 Linux 虚拟机上注册并运行 EthanKit Browser Runtime,配置 4 路并发、内网访问、实时画面和 Human in the Loop。

English

适用场景

Registered Browser Runtime 让 EthanKit 的模型循环继续运行在 API 侧,而浏览器 MCP、Chromium、实时画面和人工接管运行在你控制的 Linux 机器上。它适合:

  • 目标网站只能从公司内网或指定出口访问。
  • 登录状态需要长期保存在专用浏览器 Profile 中。
  • 登录、MFA、验证码或审批步骤需要 Human in the Loop(HIL)。
  • 同一台机器需要承载多个隔离的浏览器会话。

Runtime 主动连接 EthanKit API。普通部署只需要出站 HTTPS/WSS,不需要公网 IP,也不需要开放开发端口、CDP 端口或 VNC 端口。

前置准备

推荐使用 Ubuntu 22.04/24.04 x86_64。四路并发的起始规格建议为 8 vCPU、16 GiB RAM 和 30 GiB 可用磁盘;复杂页面、视频页面或大 Profile 需要更多资源。GPU 不是必需项。

准备以下条件:

  • Node.js 24、Git、pnpm 10.30.2,以及构建 native supervisor 所需的 Rust 工具链。
  • 能通过 DNS 和 TCP 443 访问 EthanKit API 与目标网站。
  • 一个普通 Linux 用户;安装系统依赖和启用 lingering 时需要 sudo。
  • 管理入口可以是 JumpServer。VM 不必有公网 IP;SSH 只需对 JumpServer 或可信内网开放。
  • 网页 HIL 需要 Xvfb 和 Openbox;仅监听回环地址的 x11vnc 只用于管理员初始化 Profile 和紧急排障。

安装浏览器与桌面依赖:

sudo apt-get update
sudo apt-get install -y \
  build-essential ca-certificates cargo curl ffmpeg git rustc \
  xvfb openbox x11vnc xdotool dbus-x11 \
  fonts-liberation fonts-noto-cjk

corepack enable
corepack prepare [email protected] --activate
pnpm --filter @ethankit/agent-browser exec playwright install-deps chromium

ffmpeg 用于 WebM 操作录像;缺失时浏览器仍可运行,但录像产物会失败。

通过 JumpServer 配置 SSH

在本地生成这台 Runtime 专用的密钥,不要复用个人主密钥:

ssh-keygen -t ed25519 -f ~/.ssh/ethankit-browser-runtime \
  -C "ethankit-browser-runtime"

通过 JumpServer 登录 VM,把 .pub 文件的整行内容追加到运行用户的 ~/.ssh/authorized_keys,并校正权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

验证连接:

ssh -i ~/.ssh/ethankit-browser-runtime <user>@<private-ip>

如果本地不能直接路由到内网 IP,使用公司提供的 JumpServer ProxyJump 配置,不要为 VM 临时增加公网 IP。

安装并注册 Runtime

在 Linux VM 上检出与 EthanKit 部署匹配的仓库版本,然后执行:

pnpm install --frozen-lockfile
pnpm browser-runtime:install

在 Agent Builder 的 Browser Use inspector 或 Browser Use Lab 中点击“注册一台机器”,创建一次性 pairing token。Token 十分钟后过期且只能使用一次。交互式输入不会把 Token 写进 shell history:

ethankit-browser setup \
  --runtime-name prod-browser-runtime-shanghai-01

CLI 默认连接 https://api.ethankit.com,安装受支持的 Playwright Chromium,创建 EthanKit 专用的持久化 Profile,并在后台启动 Runtime。只有自建环境才需要通过 --api-url <origin> 覆盖 API 地址。

不要把 pairing token 写入文档、聊天记录、systemd unit 或 Git。注册完成后,长期 credential 会以 0600 权限保存在 ~/.ethankit/browser-runtime.json

配置内网域名

Runtime 的 SSRF 防护默认开启。公网域名可以直接访问;解析到私网 IP 的域名必须显式加入 allowlist:

ethankit-browser private-hosts add \
  paigod.work '*.paigod.work' \
  pplabs.tech '*.pplabs.tech' \
  ppinfra.com '*.ppinfra.com' \
  ppio.com '*.ppio.com'

通配符只覆盖子域名;如果 apex 域名也会被访问,应同时添加 example.com'*.example.com'。参数中的 * 必须加引号,避免被 shell 展开。

如果 Agent 绑定了多台 Runtime,可以在 Browser Use inspector 选择 Runtime pool,配置 pool members、host routes 与 default route。路由只根据 browser_use.start_url 匹配;精确 host 优先于通配符。候选 Runtime 建立会话后会保持粘性,HIL、直播和产物都继续使用实际 选中的 Runtime。路由配置不会绕过本机 allowlist,因此每台可能被选中的 Runtime 都必须 单独添加所需私有域名。

使用 systemd 管理 Runtime 时,修改配置前先停止 unit,避免 CLI 的自动重启与 systemd 同时拉起进程:

systemctl --user stop ethankit-browser
ethankit-browser private-hosts add intranet.example '*.intranet.example'
systemctl --user start ethankit-browser

配置虚拟桌面和 systemd

仓库的 deploy/browser-runtime-linux/ 提供四个 user service 和一个输入状态清理脚本:

  • ethankit-xvfb.service:创建 DISPLAY=:99,分辨率为 1920×1080×24。
  • ethankit-openbox.service:管理 Chromium 窗口。
  • ethankit-x11vnc.service:只在 127.0.0.1:5900 提供管理员备用桌面。
  • ethankit-browser.service:以前台模式运行 Runtime,并声明四路容量。
  • ethankit-x11vnc-reset-input:在首个 VNC 客户端认证后及最后一个客户端断开后,释放残留的 X11 按键状态。

先创建 VNC 密码:

install -d -m 700 ~/.vnc
x11vnc -storepasswd ~/.vnc/passwd
chmod 600 ~/.vnc/passwd

为避免浏览器恢复后尺寸过小,把系统 Openbox 配置复制到用户目录:

install -d -m 700 ~/.config/openbox
cp /etc/xdg/openbox/rc.xml ~/.config/openbox/rc.xml

~/.config/openbox/rc.xml<applications> 中加入:

<application class="Chromium-browser" type="normal">
  <decor>yes</decor>
  <focus>yes</focus>
  <desktop>1</desktop>
  <maximized>yes</maximized>
</application>

安装并启用 user services:

install -d -m 700 ~/.config/systemd/user
install -d -m 700 ~/.local/libexec
install -m 755 \
  deploy/browser-runtime-linux/ethankit-x11vnc-reset-input \
  ~/.local/libexec/
install -m 644 deploy/browser-runtime-linux/*.service \
  ~/.config/systemd/user/

sudo loginctl enable-linger "$USER"
systemctl --user daemon-reload
systemctl --user enable --now \
  ethankit-xvfb.service \
  ethankit-openbox.service \
  ethankit-x11vnc.service

# setup 已经启动了一个后台 daemon;切换到 systemd 前先停止它。
ethankit-browser stop
systemctl --user enable --now ethankit-browser.service

如果 CLI 安装在自定义目录,把该目录加入 ethankit-browser.servicePATH。不要同时运行 CLI 后台 daemon 和 systemd foreground daemon。

验证:

systemctl --user --no-pager --full status \
  ethankit-xvfb ethankit-openbox ethankit-x11vnc ethankit-browser
ethankit-browser status
ethankit-browser doctor
ethankit-browser logs -n 100

初始化登录 Profile

持久化 Profile 允许任务复用登录状态。systemd 管理下先停止 Runtime,再打开专用 Profile:

systemctl --user stop ethankit-browser
DISPLAY=:99 ethankit-browser profile init \
  --url https://test-console.paigod.work/

通过下一节的 SSH/VNC 隧道完成登录,随后关闭 Chromium 窗口并重新启动 Runtime:

systemctl --user start ethankit-browser

不要把系统 Chrome 的 Default Profile 直接复制给 managed Chromium。浏览器版本不兼容时使用 profile repair;它会先保留时间戳备份,再创建干净的专用 Profile。

四路并发的边界

ethankit-browser.service 设置 AGENT_BROWSER_MAX_SESSIONS=4,Runtime 会向 API 声明四路容量。需要同时满足:

  • 建议至少 8 vCPU/16 GiB RAM,并通过压测观察单页内存。
  • 四个会话应使用 isolated Profile;每个会话会得到独立副本,避免 Chrome 数据库锁冲突。
  • 同一个 persistent Profile 同时只能被一个会话占用。需要四个独立的持久化登录上下文时,应部署多个 Runtime/OS 用户,各自使用独立 Profile、状态文件、SSRF 代理端口和显示环境。
  • 网页 HIL 通过各自的 CDP 页面输入,可在 isolated 会话间并行;仍需按 JPEG 流量、CPU 和内存压测实际并发上限。

Human in the Loop 操作

正式用户直接在 EthanKit 运行页接管浏览器,不需要 SSH、Linux、VPN 或 VNC 客户端。页面复用当前 Runtime 会话的 JPEG 实时流,并把受限的鼠标、滚轮、键盘、粘贴和中文输入事件送回同一个 Chromium CDP target。

正确流程:

  1. 等 EthanKit 页面显示“等待你的操作”,并等待浏览器画面标记为可控制。
  2. 点击画面,在页面内完成登录、MFA、验证码或审批;不要在聊天中提供账号、密码或验证码。
  3. 不要关闭或重新打开远端 Chromium。Runtime 会继续使用同一个浏览器进程、Profile 和 CDP target。
  4. 点击“我已完成,继续”。系统会先释放残留按键和鼠标状态,再恢复自动化。

一个 HIL action 同时只允许一个网页控制端;另一个窗口只能查看并会显示控制权冲突。页面关闭、休眠或断网后,短租约会自动过期。x11vnc 仍可用于管理员初始化 Profile 和紧急排障,但必须保持在 VM 回环地址,并且不是正式用户流程。

页面还会校验画面/Runtime 状态是否新鲜:Runtime 每 2 秒发送带时间戳的状态;连续 6 秒没有收到新帧或状态时,页面立即标记“连接已中断”、禁用输入并释放控制权,只把最后一张 JPEG 作为过期上下文保留。只要重连仍回到持有状态的 API 进程,Runtime 传输层会在最长 90 秒内保留并恢复原浏览器 session。

网络与端口安全

端口/协议方向是否对公网开放用途
TCP 443出站不适用EthanKit HTTPS/WSS、目标网站
TCP 22入站仅 JumpServer/可信内网运维 SSH 和管理员备用转发
TCP 5900VM 回环管理员备用 x11vnc
TCP 9234VM 回环Runtime SSRF forward proxy
CDP 随机端口VM 回环Runtime 观察 Chromium

不要在安全组中开放 5900、9234 或 CDP 端口。Runtime 不需要公网 IP 或所谓“开发端口”。

Xvfb 模板为同一台 VM 上的桌面进程启用本地访问,因此应使用单用途 VM 和专用 OS 用户,不要与不受信任的本地用户共享这台机器。

故障排查

先检查预期的生命周期:

preparing_profile -> starting_engine -> waiting_for_cdp
-> starting_stream -> ready -> draining -> stopping -> cleaning -> closed

实时日志:

journalctl --user -u ethankit-browser -f
# 或
ethankit-browser logs -f

常见现象:

  • 一直停在 WAITING FOR CDP:确认 Xvfb/Openbox 与 Runtime 都使用 DISPLAY=:99,并查找首帧截图错误。不要运行外部 watcher 在 CDP 建连前隐藏或 unmap Chromium。
  • page.screenshot: Timeout 10000ms exceeded 且日志停在 fonts loaded:窗口很可能被过早隐藏,或 Runtime 构建过旧。移除额外的最小化脚本,升级 Runtime 后重启。
  • lost its CDP target/ECONNREFUSED 127.0.0.1:<port>:Chromium 在跳转时更换了 CDP endpoint。新版 Runtime 会继续读取新的 DevToolsActivePort 并恢复流;旧版本需要升级。
  • 操作历史有截图但实时画面中途停止:通常是 stream observer 仍绑定旧 CDP Browser 对象,升级到包含重连修复的 Runtime。
  • VNC 全黑:检查 ethankit-xvfbethankit-openboxethankit-x11vnc 是否 active,并确认隧道连接的是 127.0.0.1:5900
  • 浏览器尺寸过小:确认 Xvfb 是 1920×1080,并检查 Openbox 的 Chromium maximize 规则是否生效。
  • HIL 中焦点持续像按住 Tab 一样跳动:先确认 Runtime 日志已经进入 waiting_for_human 且没有新的 browser tool call,再检查 journalctl --user -u ethankit-x11vnc 是否出现 key_down=23 Tab。这表示 VNC/X11 丢失了 KeyUp,不是网页动画。只释放 Tab 可执行 DISPLAY=:99 xdotool keyup Tab;如果无法确定卡住的是哪个键,在没有人工输入时执行 DISPLAY=:99 x11vnc -sync -R clear_all。随后重新验证焦点不再移动,并升级到包含输入清理 hook 的 unit。
  • SSRF blocked CONNECT <host>:为解析到私网 IP 的目标补充 exact host 和 wildcard,之后重启 Runtime。
  • persistent browser profile is busy:等待当前 persistent 会话完成,改用 isolated 模式,或分配另一台 Runtime。
  • 一次性的 session lease does not match 出现在会话关闭后:通常是旧请求的迟到响应;如果 Runtime 随后重新连接可忽略。持续出现时重启 Runtime 并检查 API/daemon 版本是否一致。

升级与回滚

systemd 管理下先停止服务,再从目标分支或 release 重新安装:

systemctl --user stop ethankit-browser
git pull --ff-only
pnpm install --frozen-lockfile
pnpm browser-runtime:install --rebuild

install -d -m 700 ~/.local/libexec ~/.config/systemd/user
install -m 755 \
  deploy/browser-runtime-linux/ethankit-x11vnc-reset-input \
  ~/.local/libexec/
install -m 644 deploy/browser-runtime-linux/*.service \
  ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user restart \
  ethankit-xvfb ethankit-openbox ethankit-x11vnc

systemctl --user start ethankit-browser
ethankit-browser doctor

安装器也会识别仍处于 active 状态的 ethankit-browser.service,并通过 systemd 停止和恢复服务,避免升级后丢失 DISPLAY=:99。即使同时传入 --setup,安装器也只更新配置, 不会在 SSH shell 下拉起一个与 systemd 竞争、且缺少 DISPLAY 的后台 daemon。生产操作仍建议使用上面的显式顺序, 便于同时更新和重启 Xvfb、Openbox、x11vnc unit。升级后的 doctor 会检查 daemon 实际继承的 DISPLAY 及对应 X11 socket;该检查失败时不要执行 Browser Test。

不要在 HIL 正在进行时升级;重启虚拟桌面会断开当前 VNC 和 Chromium。升级不会删除 ~/.ethankit/browser-runtime.jsonconfig.json 或专用 Profile。生产升级前仍应备份 ~/.ethankit/browser-runtime/,并在 Browser Use Lab 中验证实时流与一次 HIL。