diff --git a/docs/cli/node.md b/docs/cli/node.md index 23abbd3fb368..2743ea021b1e 100644 --- a/docs/cli/node.md +++ b/docs/cli/node.md @@ -62,7 +62,7 @@ Options: - `--tls`: Use TLS for the gateway connection - `--no-tls`: Force a plaintext Gateway connection even when the local Gateway config enables TLS - `--tls-fingerprint `: Expected TLS certificate fingerprint (sha256) -- `--node-id `: Override node id (clears pairing token) +- `--node-id `: Override the legacy client instance ID stored in `node.json` (does not reset pairing) - `--display-name `: Override the node display name ## Gateway auth for node host @@ -101,7 +101,7 @@ Options: - `--context-path `: Gateway WebSocket context path (e.g. `/openclaw-gw`). Appended to the WebSocket URL. - `--tls`: Use TLS for the gateway connection - `--tls-fingerprint `: Expected TLS certificate fingerprint (sha256) -- `--node-id `: Override node id (clears pairing token) +- `--node-id `: Override the legacy client instance ID stored in `node.json` (does not reset pairing) - `--display-name `: Override the node display name - `--runtime `: Service runtime (`node` or `bun`) - `--force`: Reinstall/overwrite if already installed @@ -160,9 +160,46 @@ If the node retries pairing with changed auth details (role/scopes/public key), the previous pending request is superseded and a new `requestId` is created. Run `openclaw devices list` again before approval. -The node host stores its node id, token, display name, and gateway connection -info in `node.json` in the OpenClaw state directory (`~/.openclaw` by default, -or `$OPENCLAW_STATE_DIR` when set). +### Identity and pairing state + +The headless node separates its legacy client instance ID from the signed device +identity that the Gateway uses for pairing and routing. These files live in the +OpenClaw state directory (`~/.openclaw` by default, or `$OPENCLAW_STATE_DIR` +when set): + +| File | Purpose | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `node.json` | Client instance ID under the legacy `nodeId` key, display name, and Gateway connection metadata. The client sends this value as `instanceId`. | +| `identity/device.json` | Signed Ed25519 keypair and derived device ID. For signed connections, this device ID is the routed node ID and pairing identity. | +| `identity/device-auth.json` | Paired device tokens, keyed by cryptographic device ID and role. | + +`--node-id` changes only the client instance ID in `node.json`. It does not +change the cryptographic device ID or clear pairing auth. Deleting only +`node.json` likewise does not reset pairing. To revoke and re-pair a node: + +1. On the Gateway, run `openclaw nodes remove --node `. +2. On the node, restart the installed service with `openclaw node restart`, or + stop and rerun the foreground `openclaw node run` command. This starts the + device-pairing flow. If `openclaw devices list` does not show a request + and the node reports `AUTH_DEVICE_TOKEN_MISMATCH`, restart or rerun it once + more. The rejected attempt clears the now-revoked local token; the next + attempt can request pairing. +3. On the Gateway, run `openclaw devices list`, then + `openclaw devices approve `. +4. Restart or rerun the node again. A client paused for pairing does not resume + automatically after approval; this reconnect creates the separate + command-surface request. +5. On the Gateway, run `openclaw nodes pending`, then + `openclaw nodes approve `. + +The two request IDs are distinct. An applicable trusted-CIDR policy can +auto-approve the first-time device-pairing step; command-surface approval remains +a separate check. + +Older OpenClaw releases could leave a legacy `token` field in `node.json`. +Current OpenClaw does not use that field and removes it the next time the node +host saves the file. Keep both files under `identity/` private; they contain the +device keypair and auth tokens. ## Exec approvals diff --git a/docs/docs_map.md b/docs/docs_map.md index 65d36fa127d4..c3263c5af97e 100644 --- a/docs/docs_map.md +++ b/docs/docs_map.md @@ -1715,6 +1715,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - H2: Gateway auth for node host - H2: Service (background) - H2: Pairing + - H3: Identity and pairing state - H2: Exec approvals - H2: Related @@ -4723,6 +4724,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - H3: Remote gateway via SSH tunnel (loopback bind) - H3: Start a node host (service) - H3: Pair + name + - H3: Headless identity state - H3: Allowlist the commands - H3: Point exec at the node - H3: Local model inference diff --git a/docs/nodes/index.md b/docs/nodes/index.md index 05fd372f25ab..dcee282c056e 100644 --- a/docs/nodes/index.md +++ b/docs/nodes/index.md @@ -82,7 +82,7 @@ On the node machine: openclaw node run --host --port 18789 --display-name "Build Node" ``` -`node run` also accepts `--context-path` (Gateway WS context path), `--tls`, `--tls-fingerprint `, and `--node-id` (override the generated node instance id). +`node run` also accepts `--context-path` (Gateway WS context path), `--tls`, `--tls-fingerprint `, and `--node-id` (override the legacy client instance ID; this does not reset pairing). ### Remote gateway via SSH tunnel (loopback bind) @@ -117,7 +117,7 @@ openclaw node start openclaw node restart ``` -`node install` also accepts `--context-path`, `--tls`, `--tls-fingerprint`, `--node-id`, `--runtime ` (default: node), and `--force` to reinstall. `node status`, `node stop`, and `node uninstall` are also available. +`node install` also accepts `--context-path`, `--tls`, `--tls-fingerprint`, `--node-id` (legacy client instance ID only), `--runtime ` (default: node), and `--force` to reinstall. `node status`, `node stop`, and `node uninstall` are also available. ### Pair + name @@ -133,9 +133,23 @@ If the node retries with changed auth details, re-run `openclaw devices list` an Naming options: -- `--display-name` on `openclaw node run` / `openclaw node install` (persists in `~/.openclaw/node.json` on the node, alongside the node id, token, and gateway connection info). +- `--display-name` on `openclaw node run` / `openclaw node install` (persists in `~/.openclaw/node.json` on the node, alongside the client instance ID and Gateway connection metadata). - `openclaw nodes rename --node --name "Build Node"` (gateway override). +### Headless identity state + +The headless node keeps three separate state files: + +- `~/.openclaw/node.json`: the legacy client instance ID (stored as `nodeId`), display name, and Gateway connection metadata. +- `~/.openclaw/identity/device.json`: the signed device keypair and derived cryptographic device ID. +- `~/.openclaw/identity/device-auth.json`: paired device auth tokens keyed by cryptographic device ID and role. + +For a signed node, the Gateway uses the cryptographic device ID for pairing and +node routing. The client instance ID is only connection metadata. Changing +`--node-id` or deleting only `node.json` therefore does not reset pairing. See +[Identity and pairing state](/cli/node#identity-and-pairing-state) for the +supported revoke-and-re-pair flow and upgrade notes. + ### Allowlist the commands Exec approvals are **per node host**. Add allowlist entries from the gateway: @@ -504,7 +518,7 @@ openclaw node run --host --port 18789 Notes: - Pairing is still required (the Gateway will show a device pairing prompt). -- The node host stores its node id, token, display name, and gateway connection info in `~/.openclaw/node.json`. +- Client instance metadata, signed device identity, and pairing auth use separate files; see [Headless identity state](#headless-identity-state). - Exec approvals are enforced locally via `~/.openclaw/exec-approvals.json` (see [Exec approvals](/tools/exec-approvals)). - On macOS, the headless node host executes `system.run` locally by default. Set `OPENCLAW_NODE_EXEC_HOST=app` to route `system.run` through the companion app exec host; add `OPENCLAW_NODE_EXEC_FALLBACK=0` to require the app host and fail closed if it is unavailable. - Add `--tls` / `--tls-fingerprint` when the Gateway WS uses TLS.