docs: add WSL2 + Windows remote Chrome CDP troubleshooting (#39407) (thanks @Owlock)

This commit is contained in:
Peter Steinberger
2026-03-08 19:19:14 +00:00
parent d3111fbbcb
commit 9d467d1620
6 changed files with 252 additions and 1 deletions

View File

@@ -1013,7 +1013,8 @@
"tools/browser",
"tools/browser-login",
"tools/chrome-extension",
"tools/browser-linux-troubleshooting"
"tools/browser-linux-troubleshooting",
"tools/browser-wsl2-windows-remote-cdp-troubleshooting"
]
},
{

View File

@@ -290,6 +290,7 @@ flowchart TD
- [/gateway/troubleshooting#browser-tool-fails](/gateway/troubleshooting#browser-tool-fails)
- [/tools/browser-linux-troubleshooting](/tools/browser-linux-troubleshooting)
- [/tools/browser-wsl2-windows-remote-cdp-troubleshooting](/tools/browser-wsl2-windows-remote-cdp-troubleshooting)
- [/tools/chrome-extension](/tools/chrome-extension)
</Accordion>

View File

@@ -0,0 +1,242 @@
---
summary: "Troubleshoot WSL2 Gateway + Windows Chrome remote CDP and extension-relay setups in layers"
read_when:
- Running OpenClaw Gateway in WSL2 while Chrome lives on Windows
- Seeing overlapping browser/control-ui errors across WSL2 and Windows
- Deciding between raw remote CDP and the Chrome extension relay in split-host setups
title: "WSL2 + Windows + remote Chrome CDP troubleshooting"
---
# WSL2 + Windows + remote Chrome CDP troubleshooting
This guide covers the common split-host setup where:
- OpenClaw Gateway runs inside WSL2
- Chrome runs on Windows
- browser control must cross the WSL2/Windows boundary
It also covers the layered failure pattern from [issue #39369](https://github.com/openclaw/openclaw/issues/39369): several independent problems can show up at once, which makes the wrong layer look broken first.
## Choose the right browser mode first
You have two valid patterns:
### Option 1: Raw remote CDP
Use a remote browser profile that points from WSL2 to a Windows Chrome CDP endpoint.
Choose this when:
- you only need browser control
- you are comfortable exposing Chrome remote debugging to WSL2
- you do not need the Chrome extension relay
### Option 2: Chrome extension relay
Use the built-in `chrome` profile plus the OpenClaw Chrome extension.
Choose this when:
- you want to attach to an existing Windows Chrome tab with the toolbar button
- you want extension-based control instead of raw `--remote-debugging-port`
- the relay itself must be reachable across the WSL2/Windows boundary
If you use the extension relay across namespaces, `browser.relayBindHost` is the important setting introduced in [Browser](/tools/browser) and [Chrome extension](/tools/chrome-extension).
## Working architecture
Reference shape:
- WSL2 runs the Gateway on `127.0.0.1:18789`
- Windows opens the Control UI in a normal browser at `http://127.0.0.1:18789/`
- Windows Chrome exposes a CDP endpoint on port `9222`
- WSL2 can reach that Windows CDP endpoint
- OpenClaw points a browser profile at the address that is reachable from WSL2
## Why this setup is confusing
Several failures can overlap:
- WSL2 cannot reach the Windows CDP endpoint
- the Control UI is opened from a non-secure origin
- `gateway.controlUi.allowedOrigins` does not match the page origin
- token or pairing is missing
- the browser profile points at the wrong address
- the extension relay is still loopback-only when you actually need cross-namespace access
Because of that, fixing one layer can still leave a different error visible.
## Critical rule for the Control UI
When the UI is opened from Windows, use Windows localhost unless you have a deliberate HTTPS setup.
Use:
`http://127.0.0.1:18789/`
Do not default to a LAN IP for the Control UI. Plain HTTP on a LAN or tailnet address can trigger insecure-origin/device-auth behavior that is unrelated to CDP itself. See [Control UI](/web/control-ui).
## Validate in layers
Work top to bottom. Do not skip ahead.
### Layer 1: Verify Chrome is serving CDP on Windows
Start Chrome on Windows with remote debugging enabled:
```powershell
chrome.exe --remote-debugging-port=9222
```
From Windows, verify Chrome itself first:
```powershell
curl http://127.0.0.1:9222/json/version
curl http://127.0.0.1:9222/json/list
```
If this fails on Windows, OpenClaw is not the problem yet.
### Layer 2: Verify WSL2 can reach that Windows endpoint
From WSL2, test the exact address you plan to use in `cdpUrl`:
```bash
curl http://WINDOWS_HOST_OR_IP:9222/json/version
curl http://WINDOWS_HOST_OR_IP:9222/json/list
```
Good result:
- `/json/version` returns JSON with Browser / Protocol-Version metadata
- `/json/list` returns JSON (empty array is fine if no pages are open)
If this fails:
- Windows is not exposing the port to WSL2 yet
- the address is wrong for the WSL2 side
- firewall / port forwarding / local proxying is still missing
Fix that before touching OpenClaw config.
### Layer 3: Configure the correct browser profile
For raw remote CDP, point OpenClaw at the address that is reachable from WSL2:
```json5
{
browser: {
enabled: true,
defaultProfile: "remote",
profiles: {
remote: {
cdpUrl: "http://WINDOWS_HOST_OR_IP:9222",
attachOnly: true,
color: "#00AA00",
},
},
},
}
```
Notes:
- use the WSL2-reachable address, not whatever only works on Windows
- keep `attachOnly: true` for externally managed browsers
- test the same URL with `curl` before expecting OpenClaw to succeed
### Layer 4: If you use the Chrome extension relay instead
If the browser machine and the Gateway are separated by a namespace boundary, the relay may need a non-loopback bind address.
Example:
```json5
{
browser: {
enabled: true,
defaultProfile: "chrome",
relayBindHost: "0.0.0.0",
},
}
```
Use this only when needed:
- default behavior is safer because the relay stays loopback-only
- `0.0.0.0` expands exposure surface
- keep Gateway auth, node pairing, and the surrounding network private
If you do not need the extension relay, prefer the raw remote CDP profile above.
### Layer 5: Verify the Control UI layer separately
Open the UI from Windows:
`http://127.0.0.1:18789/`
Then verify:
- the page origin matches what `gateway.controlUi.allowedOrigins` expects
- token auth or pairing is configured correctly
- you are not debugging a Control UI auth problem as if it were a browser problem
Helpful page:
- [Control UI](/web/control-ui)
### Layer 6: Verify end-to-end browser control
From WSL2:
```bash
openclaw browser open https://example.com --browser-profile remote
openclaw browser tabs --browser-profile remote
```
For the extension relay:
```bash
openclaw browser tabs --browser-profile chrome
```
Good result:
- the tab opens in Windows Chrome
- `openclaw browser tabs` returns the target
- later actions (`snapshot`, `screenshot`, `navigate`) work from the same profile
## Common misleading errors
Treat each message as a layer-specific clue:
- `control-ui-insecure-auth`
- UI origin / secure-context problem, not a CDP transport problem
- `token_missing`
- auth configuration problem
- `pairing required`
- device approval problem
- `Remote CDP for profile "remote" is not reachable`
- WSL2 cannot reach the configured `cdpUrl`
- `gateway timeout after 1500ms`
- often still CDP reachability or a slow/unreachable remote endpoint
- `Chrome extension relay is running, but no tab is connected`
- extension relay profile selected, but no attached tab exists yet
## Fast triage checklist
1. Windows: does `curl http://127.0.0.1:9222/json/version` work?
2. WSL2: does `curl http://WINDOWS_HOST_OR_IP:9222/json/version` work?
3. OpenClaw config: does `browser.profiles.<name>.cdpUrl` use that exact WSL2-reachable address?
4. Control UI: are you opening `http://127.0.0.1:18789/` instead of a LAN IP?
5. Extension relay only: do you actually need `browser.relayBindHost`, and if so is it set explicitly?
## Practical takeaway
The setup is usually viable. The hard part is that browser transport, Control UI origin security, token/pairing, and extension-relay topology can each fail independently while looking similar from the user side.
When in doubt:
- verify the Windows Chrome endpoint locally first
- verify the same endpoint from WSL2 second
- only then debug OpenClaw config or Control UI auth

View File

@@ -649,6 +649,9 @@ Strict-mode example (block private/internal destinations by default):
For Linux-specific issues (especially snap Chromium), see
[Browser troubleshooting](/tools/browser-linux-troubleshooting).
For WSL2 Gateway + Windows Chrome split-host setups, see
[WSL2 + Windows + remote Chrome CDP troubleshooting](/tools/browser-wsl2-windows-remote-cdp-troubleshooting).
## Agent tools + how control works
The agent gets **one tool** for browser automation:

View File

@@ -531,6 +531,9 @@ Browser tool:
- `profile` (optional; defaults to `browser.defaultProfile`)
- `target` (`sandbox` | `host` | `node`)
- `node` (optional; pin a specific node id/name)
- Troubleshooting guides:
- Linux startup/CDP issues: [Browser troubleshooting (Linux)](/tools/browser-linux-troubleshooting)
- WSL2 Gateway + Windows remote Chrome CDP: [WSL2 + Windows + remote Chrome CDP troubleshooting](/tools/browser-wsl2-windows-remote-cdp-troubleshooting)
## Recommended agent flows