From d4e93e791bc5093ea14666bf4d8202b45a5132b4 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 24 Apr 2026 06:07:15 +0100 Subject: [PATCH] fix: persist private ws opt-in for node services --- docs/cli/node.md | 5 +++++ docs/plugins/google-meet.md | 16 ++++++++++++++++ src/daemon/service-env.test.ts | 7 +++++++ src/daemon/service-env.ts | 2 ++ 4 files changed, 30 insertions(+) diff --git a/docs/cli/node.md b/docs/cli/node.md index 7db9937c55c..46c794d8590 100644 --- a/docs/cli/node.md +++ b/docs/cli/node.md @@ -74,6 +74,11 @@ Options: - In `gateway.mode=remote`, remote client fields (`gateway.remote.token` / `gateway.remote.password`) are also eligible per remote precedence rules. - Node host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars. +For a node connecting to a non-loopback `ws://` Gateway on a trusted private +network, set `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`. Without it, node startup +fails closed and asks you to use `wss://`, an SSH tunnel, or Tailscale. +`openclaw node install` persists this opt-in into the supervised node service. + ## Service (background) Install a headless node host as a user service. diff --git a/docs/plugins/google-meet.md b/docs/plugins/google-meet.md index c96f048b1dd..8ea99bff0fb 100644 --- a/docs/plugins/google-meet.md +++ b/docs/plugins/google-meet.md @@ -136,6 +136,22 @@ Start the node host in the VM: openclaw node run --host --port 18789 --display-name parallels-macos ``` +If `` is a LAN IP and you are not using TLS, the node refuses the +plaintext WebSocket unless you opt in for that trusted private network: + +```bash +OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 \ + openclaw node run --host --port 18789 --display-name parallels-macos +``` + +Use the same environment variable when installing the node as a LaunchAgent: + +```bash +OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1 \ + openclaw node install --host --port 18789 --display-name parallels-macos --force +openclaw node restart +``` + Approve the node from the Gateway host: ```bash diff --git a/src/daemon/service-env.test.ts b/src/daemon/service-env.test.ts index aa1cae68b0f..9edb2d84d03 100644 --- a/src/daemon/service-env.test.ts +++ b/src/daemon/service-env.test.ts @@ -388,6 +388,13 @@ describe("buildNodeServiceEnvironment", () => { expect(env.OPENCLAW_GATEWAY_TOKEN).toBe("node-token"); }); + it("passes through OPENCLAW_ALLOW_INSECURE_PRIVATE_WS for node services", () => { + const env = buildNodeServiceEnvironment({ + env: { HOME: "/home/user", OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: " 1 " }, + }); + expect(env.OPENCLAW_ALLOW_INSECURE_PRIVATE_WS).toBe("1"); + }); + it("omits OPENCLAW_GATEWAY_TOKEN when the env var is empty", () => { const env = buildNodeServiceEnvironment({ env: { diff --git a/src/daemon/service-env.ts b/src/daemon/service-env.ts index c415df817c8..0c238df5a6c 100644 --- a/src/daemon/service-env.ts +++ b/src/daemon/service-env.ts @@ -298,9 +298,11 @@ export function buildNodeServiceEnvironment(params: { params.execPath, ); const gatewayToken = normalizeOptionalString(env.OPENCLAW_GATEWAY_TOKEN); + const allowInsecurePrivateWs = normalizeOptionalString(env.OPENCLAW_ALLOW_INSECURE_PRIVATE_WS); return { ...buildCommonServiceEnvironment(env, sharedEnv), OPENCLAW_GATEWAY_TOKEN: gatewayToken, + OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: allowInsecurePrivateWs, OPENCLAW_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(), OPENCLAW_SYSTEMD_UNIT: resolveNodeSystemdServiceName(), OPENCLAW_WINDOWS_TASK_NAME: resolveNodeWindowsTaskName(),