You already run OpenClaw Gateway on a small-memory Ubuntu/Debian VPS, but once you enable browser-style capabilities that need Chromium, logs show errors such as no display, missing executable, or sandbox failures. This article is for engineers who treat headless Linux as a production Gateway: seven checklist items to surface hidden assumptions around DISPLAY / Xvfb / browser.executablePath, a comparison table to bound ops cost for virtual framebuffer versus a real display, then a six-step reproducible runbook (install dependencies, start Xvfb, export the environment, validate config, wire systemd/Docker, accept with a minimal case), and a clear split with the on-site cross-platform install, not ready troubleshooting, and observability posts.
Upstream docs often assume a machine with a display stack; production is more often a headless VPS. The seven items below turn debates from “just install Chrome” into a risk table you can sign.
Assuming the Gateway process inherits DISPLAY from your shell:If systemd Environment= omits it, browser children can still land on an empty display.
Pointing browser.executablePath at a desktop distro path:Containers or minimal images use different paths; symptoms look like spawn ENOENT.
Ignoring fonts and ICU dependencies:Without font packages, rendering can fail quietly or time out and look like the Gateway is “stuck”.
Running the browser sandbox as root:Chromium may downgrade or refuse the sandbox; use a dedicated unprivileged user and align with least privilege in the security hardening post.
Not pinning startup order between Xvfb and Gateway:Races make the first tool call fail and retries “self-heal,” which is hard to reproduce.
Budgeting browser RAM together with model calls:On small boxes Chromium often OOMs before the LLM.
Reading only Gateway logs, not child exit codes:A crashing browser surfaces downstream as tool timeouts; align timelines with openclaw logs and the system journal.
The shared root cause is treating the browser as an optional plugin instead of a runtime with an OS dependency chain. Compared with the MCP handshake post: MCP covers tool discovery and sessions; this post closes the loop on browser binary + display stack.
If you run both Docker production and bare-metal systemd, document who starts DISPLAY and Xvfb in your topology so the two orchestrators do not fight for the same display number.
There is no silver bullet: you trade reproducibility for troubleshooting surface area.
| Dimension | Xvfb + DISPLAY | Physical / VNC display | Chromium --headless only (no Xvfb) |
|---|---|---|---|
| Dependency footprint | Maintain Xvfb, display number, font packages | Maintain session, resolution, human-in-the-loop windows | Depends on headless policy per version; behavior may drift after upgrades |
| Reproducibility | High: systemd units or compose can pin env vars | Medium: desktop session and lock screen effects | Medium–high: depends on distro and sandbox mix |
| Triage signals | Clear: DISPLAY, Xvfb logs, Chromium stderr | Harder: GUI state and permission prompts | Sporadic: GPU/ANGLE paths bite more on GPU-less hosts |
| Typical fit | Small-memory VPS, screenshots / automation only | Heavy GUI or signature-popup flows | Toolchain proven to run headless on that build |
“Reproducible” here means: the same systemd unit or compose file still brings up Xvfb + Gateway + browser cleanly on a fresh VPS.
Pair with the not ready post: if the Gateway process is not stably listening, do not stack browser-layer triage yet or logs will cross-contaminate.
Order matters: display stack first, then Gateway, then tools. Commands are Debian/Ubuntu-style; swap package names on other distros.
Install Chromium and font dependencies:apt install the distro chromium or google-chrome-stable package and add common fonts such as fonts-noto.
Install Xvfb:Confirm Xvfb :99 -screen 0 1920x1080x24 starts manually with no socket conflicts.
Export DISPLAY:Set DISPLAY=:99 in the same environment as Gateway; use Environment=DISPLAY=:99 in systemd and an environment block in Docker.
Set browser.executablePath:Align with which chromium or the package path, then run openclaw doctor (or equivalent) after config changes.
Pin order in systemd or compose:Xvfb must be ready before Gateway; give Xvfb restart policy and log to disk.
Minimal acceptance:After Gateway is healthy, trigger one browser tool that only opens about:blank; confirm logs are free of sandbox/display errors before wider traffic.
# 手动验证(维护窗): Xvfb :99 -screen 0 1920x1080x24 & export DISPLAY=:99 chromium --no-sandbox --disable-dev-shm-usage --headless=new --dump-dom about:blank >/tmp/blank.html # 然后以相同 DISPLAY 启动/重启 Gateway(systemd 或 docker compose)
Tip: --no-sandbox is for constrained diagnostics only; in production return to a non-root user, least privilege, and tighten exposure with networkPolicy.
Align with observability: keep Xvfb and Chromium stderr on the same ticket timeline so “Gateway green, tools red” is not misread as a model backend issue.
Pin this table in on-call to cut noise. If the error already involves WebSocket close codes, switch to the gateway closed (1000) post.
cannot open display: check DISPLAY and that Xvfb is alive. executablePath ENOENT: check the path and that the container mounts the same binary. zygote / sandbox: confirm unprivileged user and kernel knobs before temporary diagnostic flags.
Note: do not leave permissive sandbox flags in production long term; after diagnostics roll back config, record the change ticket, and meet audit expectations.
In Docker also verify /dev/shm and shared memory size: too small makes Chromium exit intermittently and tools flake.
Use these fields for second-line alignment; redact before sharing externally.
/etc/os-release, uname -r, and the Chromium major version.ss -lxn | grep X11 or equivalent listener checks.dmesg shows the OOM killer.Binding Gateway only to a laptop that may sleep leaves the display stack and network unstable; a bare-minimum VPS often OOMs when browser and model run together. If you need a long-lived, contract-friendly macOS or dedicated compute tier for OpenClaw and its toolchain, a dedicated remote Mac is usually steadier than “making do” locally. Versus ad-hoc hardware, NodeMini Mac Mini cloud rental helps platform governance with fixed SSH, clear disk tiers, and repeatable node profiles; see specs and pricing on the Mac Mini rental rates page, onboarding in the help center, and start the OpenClaw series from the blog category.
Once the browser layer is stable, tag the root cause in your change log so the next Chromium upgrade does not repeat the same pitfall.
Whether DISPLAY points at a listening Xvfb; whether browser.executablePath matches the real binary; whether systemd or Docker injects DISPLAY and font dependencies into the Gateway process. For capacity planning, see Mac Mini rental rates and the help center.
The not ready post focuses on ports, memory, timeouts, and container startup order; this one focuses on the browser subsystem and display stack. If issues persist, compare not ready and closed (1000).
Start from the OpenClaw category for install, Docker, systemd, security, observability, and MCP posts; for onboarding help use the help center.