fix(bonjour): default LAN discovery on macOS only

Summary:
- add manifest-backed platform-specific default enablement for bundled plugins
- auto-start Bonjour LAN discovery on macOS hosts only
- keep Linux, Windows, and containerized Gateway deployments opt-in while preserving explicit enablement

Verification:
- pnpm test extensions/bonjour/src/advertiser.test.ts src/plugins/bundled-plugin-metadata.test.ts src/plugins/manifest-registry.test.ts src/plugins/channel-plugin-ids.test.ts
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md docs/gateway/bonjour.md docs/gateway/configuration-reference.md docs/gateway/discovery.md docs/gateway/security/index.md docs/plugins/manifest.md extensions/bonjour/openclaw.plugin.json src/plugin-sdk/facade-activation-check.runtime.ts src/plugins/bundled-manifest-contract-plugins.ts src/plugins/bundled-plugin-metadata.test.ts src/plugins/channel-presence-policy.ts src/plugins/default-enablement.ts src/plugins/gateway-startup-plugin-ids.ts src/plugins/installed-plugin-index-record-builder.ts src/plugins/installed-plugin-index-store.ts src/plugins/installed-plugin-index-types.ts src/plugins/installed-plugin-index.ts src/plugins/loader.ts src/plugins/manifest-contract-eligibility.ts src/plugins/manifest-owner-policy.ts src/plugins/manifest-registry-installed.ts src/plugins/manifest-registry.test.ts src/plugins/manifest-registry.ts src/plugins/manifest.ts src/plugins/providers.ts
- git diff --check
- Testbox: pnpm check:changed via Blacksmith Testbox tbx_01kqqf3f8rbrt8afjtcg0ck7qs

Refs #74209
This commit is contained in:
Peter Steinberger
2026-05-03 19:07:27 +01:00
committed by GitHub
parent fa98d01aa1
commit ee6052a169
25 changed files with 231 additions and 81 deletions

View File

@@ -8,11 +8,12 @@ title: "Bonjour discovery"
# Bonjour / mDNS discovery
OpenClaw uses Bonjour (mDNS / DNSSD) to discover an active Gateway (WebSocket endpoint).
OpenClaw can use Bonjour (mDNS / DNS-SD) to discover an active Gateway (WebSocket endpoint).
Multicast `local.` browsing is a **LAN-only convenience**. The bundled `bonjour`
plugin owns LAN advertising and is enabled by default. For cross-network discovery,
the same beacon can also be published through a configured wide-area DNS-SD domain.
Discovery is still best-effort and does **not** replace SSH or Tailnet-based connectivity.
plugin owns LAN advertising. It auto-starts on macOS hosts and is opt-in on
Linux, Windows, and containerized Gateway deployments. For cross-network discovery, the same
beacon can also be published through a configured wide-area DNS-SD domain. Discovery
is still best-effort and does **not** replace SSH or Tailnet-based connectivity.
## Wide-area Bonjour (Unicast DNS-SD) over Tailscale
@@ -81,8 +82,8 @@ For tailnetonly setups:
## What advertises
Only the Gateway advertises `_openclaw-gw._tcp`. LAN multicast advertising is
provided by the bundled `bonjour` plugin; wide-area DNS-SD publishing remains
Gateway-owned.
provided by the bundled `bonjour` plugin when the plugin is enabled; wide-area
DNS-SD publishing remains Gateway-owned.
## Service types
@@ -159,13 +160,30 @@ To capture logs:
The log includes browser state transitions and resultset changes.
## When to enable Bonjour
Bonjour auto-starts for empty-config Gateway startup on macOS hosts because the
local app and nearby iOS/Android nodes commonly rely on same-LAN discovery.
Enable Bonjour explicitly when same-LAN auto-discovery is useful on Linux,
Windows, or another non-macOS host:
```bash
openclaw plugins enable bonjour
```
When enabled, Bonjour uses `discovery.mdns.mode` to decide how much TXT metadata
to publish. The default mode is `minimal`; use `full` only when local clients need
`cliPath` or `sshPort` hints, and use `off` to suppress LAN multicast without
changing plugin enablement.
## When to disable Bonjour
Disable Bonjour only when LAN multicast advertising is unavailable or harmful.
The common case is a Gateway running behind Docker bridge networking, WSL, or a
network policy that drops mDNS multicast. In those environments the Gateway is
still reachable through its published URL, SSH, Tailnet, or wide-area DNS-SD,
but LAN auto-discovery is not reliable.
Leave Bonjour disabled when LAN multicast advertising is unnecessary, unavailable,
or harmful. The common cases are non-macOS servers, Docker bridge networking,
WSL, or a network policy that drops mDNS multicast. In those environments the
Gateway is still reachable through its published URL, SSH, Tailnet, or wide-area
DNS-SD, but LAN auto-discovery is not reliable.
Prefer the existing environment override when the problem is deployment-scoped:
@@ -177,8 +195,8 @@ That disables LAN multicast advertising without changing plugin configuration.
It is safe for Docker images, service files, launch scripts, and one-off
debugging because the setting disappears when the environment does.
Use plugin configuration only when you intentionally want to turn off the
bundled LAN discovery plugin for that OpenClaw config:
Use plugin configuration when you intentionally want to turn off the bundled LAN
discovery plugin for that OpenClaw config:
```bash
openclaw plugins disable bonjour
@@ -193,8 +211,8 @@ and the LAN, so advertising from the container rarely makes discovery work.
Important gotchas:
- Disabling Bonjour does not stop the Gateway. It only stops LAN multicast
advertising.
- Bonjour auto-starts on macOS hosts and is opt-in elsewhere. Leaving it
disabled does not stop the Gateway; it only skips LAN multicast advertising.
- Disabling Bonjour does not change `gateway.bind`; Docker still defaults to
`OPENCLAW_GATEWAY_BIND=lan` so the published host port can work.
- Disabling Bonjour does not disable wide-area DNS-SD. Use wide-area discovery
@@ -226,8 +244,8 @@ If a node no longer auto-discovers the Gateway after Docker setup:
- Cross-network clients: Tailnet MagicDNS, Tailnet IP, SSH tunnel, or
wide-area DNS-SD
4. If you deliberately enabled Bonjour in Docker with
`OPENCLAW_DISABLE_BONJOUR=0`, test multicast from the host:
4. If you deliberately enabled the Bonjour plugin in Docker and forced advertising
with `OPENCLAW_DISABLE_BONJOUR=0`, test multicast from the host:
```bash
dns-sd -B _openclaw-gw._tcp local.
@@ -261,13 +279,14 @@ sequences (e.g. spaces become `\032`).
- This is normal at the protocol level.
- UIs should decode for display (iOS uses `BonjourEscapes.decode`).
## Disabling / configuration
## Enabling / disabling / configuration
- macOS hosts auto-start the bundled LAN discovery plugin by default.
- `openclaw plugins enable bonjour` enables the bundled LAN discovery plugin on hosts where it is not default-enabled.
- `openclaw plugins disable bonjour` disables LAN multicast advertising by disabling the bundled plugin.
- `openclaw plugins enable bonjour` restores the default LAN discovery plugin.
- `OPENCLAW_DISABLE_BONJOUR=1` disables LAN multicast advertising without changing plugin config; accepted truthy values are `1`, `true`, `yes`, and `on` (legacy: `OPENCLAW_DISABLE_BONJOUR`).
- `OPENCLAW_DISABLE_BONJOUR=0` forces LAN multicast advertising on, including inside detected containers; accepted falsy values are `0`, `false`, `no`, and `off`.
- When `OPENCLAW_DISABLE_BONJOUR` is unset, Bonjour advertises on normal hosts and auto-disables inside detected containers.
- When the Bonjour plugin is enabled and `OPENCLAW_DISABLE_BONJOUR` is unset, Bonjour advertises on normal hosts and auto-disables inside detected containers.
- `gateway.bind` in `~/.openclaw/openclaw.json` controls the Gateway bind mode.
- `OPENCLAW_SSH_PORT` overrides the SSH port when `sshPort` is advertised (legacy: `OPENCLAW_SSH_PORT`).
- `OPENCLAW_TAILNET_DNS` publishes a MagicDNS hint in TXT when mDNS full mode is enabled (legacy: `OPENCLAW_TAILNET_DNS`).

View File

@@ -687,8 +687,10 @@ Validation and safety notes:
}
```
- `minimal` (default): omit `cliPath` + `sshPort` from TXT records.
- `full`: include `cliPath` + `sshPort`.
- `minimal` (default when the bundled `bonjour` plugin is enabled): omit `cliPath` + `sshPort` from TXT records.
- `full`: include `cliPath` + `sshPort`; LAN multicast advertising still requires the bundled `bonjour` plugin to be enabled.
- `off`: suppress LAN multicast advertising without changing plugin enablement.
- The bundled `bonjour` plugin auto-starts on macOS hosts and is opt-in on Linux, Windows, and containerized Gateway deployments.
- Hostname defaults to the system hostname when it is a valid DNS label, falling back to `openclaw`. Override with `OPENCLAW_MDNS_HOSTNAME`.
### Wide-area (DNS-SD)

View File

@@ -54,7 +54,9 @@ same gateway beacon via a configured wide-area DNS-SD domain, so discovery can c
Target direction:
- The **gateway** advertises its WS endpoint via Bonjour.
- The **gateway** advertises its WS endpoint via Bonjour when the bundled
`bonjour` plugin is enabled. The plugin auto-starts on macOS hosts and is
opt-in elsewhere.
- Clients browse and show a “pick a gateway” list, then store the chosen endpoint.
Troubleshooting and beacon details: [Bonjour](/gateway/bonjour).
@@ -83,12 +85,16 @@ Security notes:
- TLS pinning must never allow an advertised `gatewayTlsSha256` to override 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.
Disable/override:
Enable/disable/override:
- `openclaw plugins enable bonjour` enables LAN multicast advertising.
- `OPENCLAW_DISABLE_BONJOUR=1` disables advertising.
- When `OPENCLAW_DISABLE_BONJOUR` is unset, Bonjour advertises on normal hosts
and auto-disables inside detected containers. Use `0` only on host, macvlan,
or another mDNS-capable network; use `1` to force-disable.
- When the Bonjour plugin is enabled and `OPENCLAW_DISABLE_BONJOUR` is unset,
Bonjour advertises on normal hosts and auto-disables inside detected containers.
Empty-config macOS Gateway startup enables the plugin automatically; Linux,
Windows, and containerized deployments need explicit enablement.
Use `0` only on host, macvlan, or another mDNS-capable network; use `1` to
force-disable.
- `gateway.bind` in `~/.openclaw/openclaw.json` controls the Gateway bind mode.
- `OPENCLAW_SSH_PORT` overrides the SSH port advertised when `sshPort` is emitted.
- `OPENCLAW_TAILNET_DNS` publishes a `tailnetDns` hint (MagicDNS).

View File

@@ -796,7 +796,7 @@ setups: SSH + your reverse proxy ports).
### mDNS/Bonjour discovery
The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
When the bundled `bonjour` plugin is enabled, the Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
- `cliPath`: full filesystem path to the CLI binary (reveals username and install location)
- `sshPort`: advertises SSH availability on the host
@@ -806,7 +806,9 @@ The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353)
**Recommendations:**
1. **Minimal mode** (default, recommended for exposed gateways): omit sensitive fields from mDNS broadcasts:
1. **Keep Bonjour disabled unless LAN discovery is needed.** Bonjour auto-starts on macOS hosts and is opt-in elsewhere; direct Gateway URLs, Tailnet, SSH, or wide-area DNS-SD avoid local multicast.
2. **Minimal mode** (default when Bonjour is enabled, recommended for exposed gateways): omit sensitive fields from mDNS broadcasts:
```json5
{
@@ -816,7 +818,7 @@ The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353)
}
```
2. **Disable entirely** if you don't need local device discovery:
3. **Disable mDNS mode** if you want to keep the plugin enabled but suppress local device discovery:
```json5
{
@@ -826,7 +828,7 @@ The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353)
}
```
3. **Full mode** (opt-in): include `cliPath` + `sshPort` in TXT records:
4. **Full mode** (opt-in): include `cliPath` + `sshPort` in TXT records:
```json5
{
@@ -836,9 +838,9 @@ The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353)
}
```
4. **Environment variable** (alternative): set `OPENCLAW_DISABLE_BONJOUR=1` to disable mDNS without config changes.
5. **Environment variable** (alternative): set `OPENCLAW_DISABLE_BONJOUR=1` to disable mDNS without config changes.
In minimal mode, the Gateway still broadcasts enough for device discovery (`role`, `gatewayPort`, `transport`) but omits `cliPath` and `sshPort`. Apps that need CLI path information can fetch it via the authenticated WebSocket connection instead.
When Bonjour is enabled in minimal mode, the Gateway broadcasts enough for device discovery (`role`, `gatewayPort`, `transport`) but omits `cliPath` and `sshPort`. Apps that need CLI path information can fetch it via the authenticated WebSocket connection instead.
### Lock down the Gateway WebSocket (local auth)

View File

@@ -150,6 +150,7 @@ or npm install metadata. Those belong in your plugin code and `package.json`.
| `id` | Yes | `string` | Canonical plugin id. This is the id used in `plugins.entries.<id>`. |
| `configSchema` | Yes | `object` | Inline JSON Schema for this plugin's config. |
| `enabledByDefault` | No | `true` | Marks a bundled plugin as enabled by default. Omit it, or set any non-`true` value, to leave the plugin disabled by default. |
| `enabledByDefaultOnPlatforms` | No | `string[]` | Marks a bundled plugin as enabled by default only on the listed Node.js platforms, for example `["darwin"]`. Explicit config still wins. |
| `legacyPluginIds` | No | `string[]` | Legacy ids that normalize to this canonical plugin id. |
| `autoEnableWhenConfiguredProviders` | No | `string[]` | Provider ids that should auto-enable this plugin when auth, config, or model refs mention them. |
| `kind` | No | `"memory"` \| `"context-engine"` | Declares an exclusive plugin kind used by `plugins.slots.*`. |