Gateway
Discovery and transports
OpenClaw has two related but distinct discovery problems:
- Operator remote control: the macOS menu bar app controlling a Gateway running elsewhere.
- Node pairing: iOS/Android (and future nodes) finding a Gateway and pairing securely.
All network discovery/advertising lives in the Gateway
(openclaw gateway); clients (mac app, iOS) are consumers only.
Terms
- Gateway: a single long-running process that owns state (sessions, pairing, node registry) and runs channels. Most setups use one per host; isolated multi-gateway setups are possible.
- Gateway WS (control plane): the WebSocket endpoint on
127.0.0.1:18789by default; bind it to LAN/tailnet viagateway.bind. - Direct WS transport: a LAN/tailnet-facing Gateway WS endpoint (no SSH).
- SSH transport (fallback): remote control by forwarding
127.0.0.1:18789over SSH.
Protocol details: Gateway protocol.
Why direct and SSH both exist
- Direct WS is the best UX on the same network and within a tailnet: LAN auto-discovery via Bonjour, pairing tokens and ACLs owned by the Gateway, and no shell access required.
- SSH is the universal fallback: works anywhere you have SSH access, even across unrelated networks, survives multicast/mDNS issues, and needs no new inbound port besides SSH.
Discovery inputs
1) Bonjour / DNS-SD
Multicast Bonjour is best-effort and does not cross networks. OpenClaw also
supports browsing the same Gateway beacon via a configured wide-area DNS-SD
domain, so discovery can cover both local. on the same LAN and a configured
unicast DNS-SD domain for cross-network discovery.
The Gateway advertises its WS endpoint via Bonjour when the bundled
bonjour plugin is enabled; clients browse and show a "pick a Gateway" list,
then apply their connection trust policy. On macOS, a selection opens the
connection editor; it does not save the advertised endpoint. See
Configure in the app.
Troubleshooting and beacon details: Bonjour.
Service beacon details
-
Service type:
_openclaw-gw._tcp(Gateway transport beacon). -
TXT keys (non-secret):
Key Notes role=gatewayAlways present. transport=gatewayAlways present. displayName=<name>Operator-configured display name. lanHost=<hostname>.localLAN mDNS advertiser only; not written by wide-area DNS-SD. gatewayPort=18789Gateway WS + HTTP port. gatewayTls=1Only when TLS is enabled. gatewayTlsSha256=<sha256>Only when TLS is enabled and a fingerprint is available. tailnetDns=<magicdns>Optional hint; auto-detected when Tailscale is available. sshPort=<port>Present only when discovery.mdns.mode="full"; omitted (SSH defaults to22) in the default"minimal"mode, on both the LAN advertiser and wide-area DNS-SD.cliPath=<path>Same discovery.mdns.mode="full"gate assshPort; a remote-install hint for the CLI path.
Security notes:
- Bonjour/mDNS TXT records are unauthenticated. Clients must treat TXT values as UX hints only.
- Routing (host/port) should prefer the resolved service endpoint
(SRV + A/AAAA) over TXT-provided
lanHost,tailnetDns, orgatewayPort. - TLS pinning must never let an advertised
gatewayTlsSha256override a previously stored pin. - iOS/Android nodes should require an explicit "trust this fingerprint" confirmation before storing a first-time pin (out-of-band verification) whenever the chosen route is secure/TLS-based.
Enable, disable, and override:
openclaw plugins enable bonjourenables LAN multicast advertising.discovery.mdns.modeinopenclaw.jsoncontrols mDNS broadcast:"minimal"(default),"full"(addscliPath/sshPortto both the LAN beacon and any wide-area DNS-SD zone), or"off"(disables mDNS).OPENCLAW_DISABLE_BONJOUR=1force-disables advertising;discovery.mdns.mode="off"disables it independently.OPENCLAW_DISABLE_BONJOUR=0is an explicit opt-in that overrides the plugin's auto-disable inside a detected container (Docker, containerd, Kubernetes, LXC); it does not overridediscovery.mdns.mode="off". The bundledbonjourplugin auto-starts on macOS hosts (enabledByDefaultOnPlatforms: ["darwin"]) and auto-disables inside detected containers; Linux, Windows, and other containerized deployments need explicitplugins enable bonjour.gateway.bindin~/.openclaw/openclaw.jsoncontrols the Gateway bind mode.OPENCLAW_SSH_PORToverrides the advertised SSH port (only takes effect whendiscovery.mdns.mode="full").OPENCLAW_TAILNET_DNSpublishes atailnetDnshint (MagicDNS).OPENCLAW_CLI_PATHoverrides the advertised CLI path.
2) Tailnet (cross-network)
For Gateways on different physical networks, Bonjour will not help. The recommended direct target is a Tailscale MagicDNS name (preferred) or a stable tailnet IP.
If the Gateway detects it is running under Tailscale, it publishes
tailnetDns as an optional hint for clients (including wide-area beacons).
For a configured macOS connection, prefer a trusted MagicDNS name over a raw
Tailscale IP so the name resolves to the current address. Discovery does not
replace the saved address.
For mobile node pairing, discovery hints never relax transport security on tailnet/public routes:
- iOS/Android still require a secure first-time tailnet/public connect path
(
wss://or Tailscale Serve/Funnel). - A discovered raw tailnet IP is a routing hint, not permission to use
plaintext remote
ws://. - Private LAN direct-connect
ws://remains supported. - For the simplest Tailscale path on mobile nodes, use Tailscale Serve so discovery and setup both resolve to the same secure MagicDNS endpoint.
3) Manual / SSH target
When there is no direct route (or direct is disabled), clients can always connect via SSH by forwarding the loopback Gateway port. See Remote access.
Transport selection (client policy)
The macOS app uses its configured direct or SSH transport. Discovery does not replace that route or select a fallback. For a new connection, the user supplies a trusted address, SSH target, or setup code in the connection editor and saves it.
Discovery-based client selection follows this policy:
- If a paired direct endpoint is configured and reachable, use it.
- Else, if discovery finds a Gateway on
local.or the configured wide-area domain, offer setup for that candidate. Apply the client's trust policy before saving a direct endpoint; discovery alone is not authorization. - Else, if a tailnet DNS/IP is configured, try direct. For mobile nodes on
tailnet/public routes, direct means a secure endpoint, not plaintext
remote
ws://. - Else, fall back to SSH.
Pairing and auth (direct transport)
The Gateway is the source of truth for node/client admission:
- Pairing requests are created/approved/rejected in the Gateway (see Gateway pairing).
- The Gateway enforces auth (token/keypair), scopes/ACLs (it is not a raw proxy to every method), and rate limits.
Responsibilities by component
- Gateway: advertises discovery beacons, owns pairing decisions, hosts the WS endpoint.
- macOS app: edits trusted Gateway connections, shows pairing prompts, and uses the configured direct or SSH transport.
- iOS/Android nodes: browse Bonjour as a convenience, connect to the paired Gateway WS.