跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

Gateway ports, already running, and remote mode

Gateway ports, remote-mode clients, bind addresses, and running more than one Gateway

Gateway: ports, "already running", and remote mode

What port does the Gateway use?

gateway.port controls the single multiplexed port for WebSocket + HTTP (Control UI, hooks, etc.). Precedence:

--port > OPENCLAW_GATEWAY_PORT > gateway.port > default 18789
Why does openclaw gateway status report a running process but a failed connection?

"Running" is the supervisor's view (launchd/systemd/schtasks); the connectivity check is the CLI actually connecting to the gateway WebSocket. In openclaw gateway status, compare the connection target URL with Listening: (what is actually bound on the port), and inspect Last gateway error: for the failure cause when the process is alive but the port is not listening.

Why does openclaw gateway status show "Config (cli)" and "Config (service)" different?

You are editing one config file while the service runs another (often a --profile / OPENCLAW_STATE_DIR mismatch).

Fix, run from the same --profile / environment you want the service to use:

openclaw gateway install --force
What does "another gateway instance is already listening" mean?

OpenClaw enforces a runtime lock by binding the WebSocket listener immediately on startup (default ws://127.0.0.1:18789). If the bind fails with EADDRINUSE, it throws GatewayLockError ("another gateway instance is already listening").

Fix: stop the other instance, free the port, or run with openclaw gateway --port <port>.

How do I run OpenClaw in remote mode (client connects to a Gateway elsewhere)?

Set gateway.mode: "remote" and point to a remote WebSocket URL, optionally with shared-secret remote credentials:

{
  gateway: {
    mode: "remote",
    remote: {
      url: "ws://gateway.tailnet:18789",
      token: "your-token",
      password: "your-password",
    },
  },
}
  • openclaw gateway only starts when gateway.mode is local (or you pass an override flag).
  • The macOS app watches the config file and switches modes live when these values change.
  • gateway.remote.token / .password are client-side remote credentials only; they do not enable local gateway auth by themselves.
The Control UI says "unauthorized" (or keeps reconnecting). What now?

Your gateway auth path and the UI's auth method do not match.

Facts (from code):

  • The Control UI keeps the token in sessionStorage, scoped to the current browser tab and selected gateway URL, so same-tab refreshes keep working without long-lived localStorage token persistence.
  • On AUTH_TOKEN_MISMATCH, trusted clients can attempt one bounded retry with a cached device token when the gateway returns retry hints (canRetryWithDeviceToken=true, recommendedNextStep=retry_with_device_token).
  • That cached-token retry reuses the cached approved scopes stored with the device token; explicit deviceToken / explicit scopes callers keep their requested scope set instead of inheriting cached scopes.
  • Outside that retry path, connect auth precedence is explicit shared token/password first, then explicit deviceToken, then stored device token, then bootstrap token.
  • Built-in setup-code bootstrap returns a node device token with scopes: [] plus a bounded operator handoff token for trusted mobile onboarding. The operator handoff can read setup-time native configuration but does not grant pairing mutation scopes or operator.admin.

Fix:

I set gateway.bind tailnet but it listens only on loopback

tailnet bind picks a Tailscale IP from your network interfaces (100.64.0.0/10). If the machine is not on Tailscale (or the interface is down), the Gateway falls back to loopback instead of exposing another network interface.

Fix: start Tailscale on that host and restart the Gateway, or switch explicitly to gateway.bind: "loopback" / "lan".

tailnet is explicit; auto prefers loopback. Use gateway.bind: "tailnet" to limit non-loopback exposure to the Tailnet while retaining the required same-host 127.0.0.1 listener.

Can I run multiple Gateways on the same host?

Usually no - one Gateway can run multiple messaging channels and agents. Use multiple Gateways only for redundancy (for example a rescue bot) or hard isolation, and isolate each with its own OPENCLAW_CONFIG_PATH, OPENCLAW_STATE_DIR, agents.defaults.workspace, and unique gateway.port.

Recommended: openclaw --profile <name> ... per instance (auto-creates ~/.openclaw-<name>), a unique gateway.port per profile config (or --port for manual runs), and a per-profile service with openclaw --profile <name> gateway install.

Profiles also suffix service names: launchd ai.openclaw.<profile>, systemd openclaw-gateway-<profile>.service, Windows OpenClaw Gateway (<profile>). The unqualified openclaw-gateway systemd unit only exists for the default profile; the legacy pre-rename systemd unit name clawdbot-gateway is migrated automatically.

Full guide: Multiple gateways.

What does "invalid handshake" / code 1008 mean?

The Gateway is a WebSocket server and expects the first message to be a connect frame. Anything else closes the connection with code 1008 (policy violation).

Common causes: you opened the HTTP URL in a browser instead of a WS client, used the wrong port/path, or a proxy/tunnel stripped auth headers or sent a non-Gateway request.

Fix: use the WS URL (ws://<host>:18789, or wss://... over HTTPS), do not open the WS port in a normal browser tab, and include the token/password in the connect frame when auth is on. CLI/TUI example:

openclaw tui --url ws://<host>:18789 --token <token>

Protocol details: Gateway protocol.