2025-12-13 04:28:12 +00:00
---
summary: "Bonjour/mDNS discovery + debugging (Gateway beacons, clients, and common failure modes)"
read_when:
- Debugging Bonjour discovery issues on macOS/iOS
- Changing mDNS service types, TXT records, or discovery UX
2026-01-31 16:04:03 -05:00
title: "Bonjour Discovery"
2025-12-13 04:28:12 +00:00
---
2026-01-31 21:13:13 +09:00
2025-12-13 04:28:12 +00:00
# Bonjour / mDNS discovery
2026-01-30 03:15:10 +01:00
OpenClaw uses Bonjour (mDNS / DNS‑ SD) as a **LAN‑ only convenience** to discover
2026-01-22 23:07:58 +00:00
an active Gateway (WebSocket endpoint). It is best‑ effort and does **not** replace SSH or
2026-01-08 23:06:56 +01:00
Tailnet-based connectivity.
2025-12-13 04:28:12 +00:00
2026-01-08 23:06:56 +01:00
## Wide‑ area Bonjour (Unicast DNS‑ SD) over Tailscale
2025-12-17 14:14:17 +01:00
2026-01-08 23:06:56 +01:00
If the node and gateway are on different networks, multicast mDNS won’ t cross the
boundary. You can keep the same discovery UX by switching to **unicast DNS‑ SD**
("Wide‑ Area Bonjour") over Tailscale.
2025-12-17 14:14:17 +01:00
2026-01-08 23:06:56 +01:00
High‑ level steps:
2025-12-17 14:14:17 +01:00
2026-01-31 21:13:13 +09:00
1. Run a DNS server on the gateway host (reachable over Tailnet).
2. Publish DNS‑ SD records for `_openclaw-gw._tcp` under a dedicated zone
2026-01-30 03:15:10 +01:00
(example: `openclaw.internal.` ).
2026-01-31 21:13:13 +09:00
3. Configure Tailscale **split DNS** so your chosen domain resolves via that
2026-01-08 23:06:56 +01:00
DNS server for clients (including iOS).
2025-12-17 14:14:17 +01:00
2026-01-30 03:15:10 +01:00
OpenClaw supports any discovery domain; `openclaw.internal.` is just an example.
iOS/Android nodes browse both `local.` and your configured wide‑ area domain.
2025-12-17 14:14:17 +01:00
2025-12-17 17:01:10 +01:00
### Gateway config (recommended)
2025-12-17 14:14:17 +01:00
2025-12-17 17:01:10 +01:00
```json5
{
2026-01-22 23:07:58 +00:00
gateway: { bind: "tailnet" }, // tailnet-only (recommended)
2026-01-31 21:13:13 +09:00
discovery: { wideArea: { enabled: true } }, // enables wide-area DNS-SD publishing
2025-12-17 17:01:10 +01:00
}
```
2025-12-17 14:14:17 +01:00
2026-01-08 23:06:56 +01:00
### One‑ time DNS server setup (gateway host)
2025-12-17 14:14:17 +01:00
2025-12-17 17:01:10 +01:00
```bash
2026-01-30 03:15:10 +01:00
openclaw dns setup --apply
2025-12-17 17:01:10 +01:00
```
2025-12-17 14:14:17 +01:00
2025-12-17 17:01:10 +01:00
This installs CoreDNS and configures it to:
2026-01-31 21:13:13 +09:00
2026-01-08 23:06:56 +01:00
- listen on port 53 only on the gateway’ s Tailscale interfaces
2026-01-30 03:15:10 +01:00
- serve your chosen domain (example: `openclaw.internal.` ) from `~/.openclaw/dns/<domain>.db`
2025-12-17 14:14:17 +01:00
2026-01-08 23:06:56 +01:00
Validate from a tailnet‑ connected machine:
2025-12-17 14:14:17 +01:00
```bash
2026-01-30 03:15:10 +01:00
dns-sd -B _openclaw-gw._tcp openclaw.internal.
dig @< TAILNET_IPV4 > -p 53 _openclaw-gw._tcp.openclaw.internal PTR +short
2025-12-17 14:14:17 +01:00
```
### Tailscale DNS settings
In the Tailscale admin console:
- Add a nameserver pointing at the gateway’ s tailnet IP (UDP/TCP 53).
2026-01-30 03:15:10 +01:00
- Add split DNS so your discovery domain uses that nameserver.
2025-12-17 14:14:17 +01:00
2026-01-08 23:06:56 +01:00
Once clients accept tailnet DNS, iOS nodes can browse
2026-01-30 03:15:10 +01:00
`_openclaw-gw._tcp` in your discovery domain without multicast.
2025-12-17 14:14:17 +01:00
2026-01-22 23:07:58 +00:00
### Gateway listener security (recommended)
2025-12-17 14:27:49 +01:00
2026-01-22 23:07:58 +00:00
The Gateway WS port (default `18789` ) binds to loopback by default. For LAN/tailnet
access, bind explicitly and keep auth enabled.
2025-12-17 14:27:49 +01:00
2026-01-08 23:06:56 +01:00
For tailnet‑ only setups:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- Set `gateway.bind: "tailnet"` in `~/.openclaw/openclaw.json` .
2026-01-08 23:06:56 +01:00
- Restart the Gateway (or restart the macOS menubar app).
2025-12-17 14:27:49 +01:00
2025-12-13 04:28:12 +00:00
## What advertises
2026-01-30 03:15:10 +01:00
Only the Gateway advertises `_openclaw-gw._tcp` .
2025-12-13 04:28:12 +00:00
## Service types
2026-01-30 03:15:10 +01:00
- `_openclaw-gw._tcp` — gateway transport beacon (used by macOS/iOS/Android nodes).
2025-12-13 04:28:12 +00:00
2026-01-08 23:06:56 +01:00
## TXT keys (non‑ secret hints)
2025-12-13 04:28:12 +00:00
2026-01-08 23:06:56 +01:00
The Gateway advertises small non‑ secret hints to make UI flows convenient:
2025-12-13 04:28:12 +00:00
2025-12-19 23:12:52 +01:00
- `role=gateway`
2026-01-08 23:06:56 +01:00
- `displayName=<friendly name>`
2025-12-13 04:28:12 +00:00
- `lanHost=<hostname>.local`
2026-01-22 23:07:58 +00:00
- `gatewayPort=<port>` (Gateway WS + HTTP)
- `gatewayTls=1` (only when TLS is enabled)
- `gatewayTlsSha256=<sha256>` (only when TLS is enabled and fingerprint is available)
2026-02-14 14:55:10 +01:00
- `canvasPort=<port>` (only when the canvas host is enabled; currently the same as `gatewayPort` )
2026-01-08 23:06:56 +01:00
- `sshPort=<port>` (defaults to 22 when not overridden)
2026-01-22 23:07:58 +00:00
- `transport=gateway`
2026-01-30 03:15:10 +01:00
- `cliPath=<path>` (optional; absolute path to a runnable `openclaw` entrypoint)
2026-01-08 23:06:56 +01:00
- `tailnetDns=<magicdns>` (optional hint when Tailnet is available)
2025-12-13 04:28:12 +00:00
2026-02-14 17:17:46 +01:00
Security notes:
- Bonjour/mDNS TXT records are **unauthenticated** . Clients must not treat TXT as authoritative routing.
- Clients should route using the resolved service endpoint (SRV + A/AAAA). Treat `lanHost` , `tailnetDns` , `gatewayPort` , and `gatewayTlsSha256` as hints only.
- TLS pinning must never allow an advertised `gatewayTlsSha256` to override a previously stored pin.
2026-02-14 17:47:13 +01:00
- iOS/Android nodes should treat discovery-based direct connects as **TLS-only** and require explicit user confirmation before trusting a first-time fingerprint.
2026-02-14 17:17:46 +01:00
2025-12-13 04:28:12 +00:00
## Debugging on macOS
2026-01-08 23:06:56 +01:00
Useful built‑ in tools:
2025-12-13 04:28:12 +00:00
- Browse instances:
2026-02-06 10:08:59 -05:00
2026-01-08 23:06:56 +01:00
```bash
2026-01-30 03:15:10 +01:00
dns-sd -B _openclaw-gw._tcp local.
2026-01-08 23:06:56 +01:00
```
2026-02-06 10:08:59 -05:00
2025-12-13 04:28:12 +00:00
- Resolve one instance (replace `<instance>` ):
2026-02-06 10:08:59 -05:00
2026-01-08 23:06:56 +01:00
```bash
2026-01-30 03:15:10 +01:00
dns-sd -L "< instance > " _openclaw-gw._tcp local.
2026-01-08 23:06:56 +01:00
```
2025-12-13 04:28:12 +00:00
2026-01-08 23:06:56 +01:00
If browsing works but resolving fails, you’ re usually hitting a LAN policy or
mDNS resolver issue.
2025-12-13 04:28:12 +00:00
2025-12-14 04:34:26 +00:00
## Debugging in Gateway logs
2026-01-08 23:06:56 +01:00
The Gateway writes a rolling log file (printed on startup as
`gateway log file: ...` ). Look for `bonjour:` lines, especially:
2025-12-14 04:34:26 +00:00
2026-01-08 23:06:56 +01:00
- `bonjour: advertise failed ...`
2025-12-14 04:34:26 +00:00
- `bonjour: ... name conflict resolved` / `hostname conflict resolved`
2026-01-08 23:06:56 +01:00
- `bonjour: watchdog detected non-announced service ...`
2025-12-14 04:34:26 +00:00
2025-12-18 13:18:33 +01:00
## Debugging on iOS node
2025-12-14 04:34:26 +00:00
2026-01-30 03:15:10 +01:00
The iOS node uses `NWBrowser` to discover `_openclaw-gw._tcp` .
2025-12-14 04:34:26 +00:00
2026-01-08 23:06:56 +01:00
To capture logs:
2026-01-31 21:13:13 +09:00
2026-01-22 23:07:58 +00:00
- Settings → Gateway → Advanced → **Discovery Debug Logs**
- Settings → Gateway → Advanced → **Discovery Logs** → reproduce → **Copy**
2025-12-14 04:34:26 +00:00
2026-01-08 23:06:56 +01:00
The log includes browser state transitions and result‑ set changes.
2025-12-14 04:34:26 +00:00
2025-12-13 04:28:12 +00:00
## Common failure modes
2026-01-08 23:06:56 +01:00
- **Bonjour doesn’ t cross networks**: use Tailnet or SSH.
- **Multicast blocked**: some Wi‑ Fi networks disable mDNS.
- **Sleep / interface churn**: macOS may temporarily drop mDNS results; retry.
- **Browse works but resolve fails**: keep machine names simple (avoid emojis or
2026-01-22 23:07:58 +00:00
punctuation), then restart the Gateway. The service instance name derives from
2026-01-08 23:06:56 +01:00
the host name, so overly complex names can confuse some resolvers.
## Escaped instance names (`\032`)
2025-12-13 12:28:16 +00:00
2026-01-08 23:06:56 +01:00
Bonjour/DNS‑ SD often escapes bytes in service instance names as decimal `\DDD`
sequences (e.g. spaces become `\032` ).
2025-12-13 12:28:16 +00:00
- This is normal at the protocol level.
2026-01-08 23:06:56 +01:00
- UIs should decode for display (iOS uses `BonjourEscapes.decode` ).
2025-12-13 04:28:12 +00:00
## Disabling / configuration
2026-01-30 03:15:10 +01:00
- `OPENCLAW_DISABLE_BONJOUR=1` disables advertising (legacy: `OPENCLAW_DISABLE_BONJOUR` ).
- `gateway.bind` in `~/.openclaw/openclaw.json` controls the Gateway bind mode.
- `OPENCLAW_SSH_PORT` overrides the SSH port advertised in TXT (legacy: `OPENCLAW_SSH_PORT` ).
- `OPENCLAW_TAILNET_DNS` publishes a MagicDNS hint in TXT (legacy: `OPENCLAW_TAILNET_DNS` ).
- `OPENCLAW_CLI_PATH` overrides the advertised CLI path (legacy: `OPENCLAW_CLI_PATH` ).
2025-12-13 04:28:12 +00:00
## Related docs
2026-01-10 14:51:21 -06:00
- Discovery policy and transport selection: [Discovery ](/gateway/discovery )
- Node pairing + approvals: [Gateway pairing ](/gateway/pairing )