> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bricks.tools/llms.txt
> Use this file to discover all available pages before exploring further.

# LAN auto-discovery

> How Foundation devices find Buttress servers on the local network

Foundation launchers don't need a hardcoded server URL. Each Buttress server announces itself on the LAN, and bound launchers pick the strongest matching server for each generator type.

## How it works

Every Buttress server runs a UDP transport on port `8089`:

* **ANNOUNCE** — broadcast every 5 seconds with the server's `serverInfo` (capabilities, generators, auth status).
* **QUERY** — a launcher can broadcast a query and the server unicasts a **RESPONSE** back. Response delays are randomized to avoid storms when many servers reply at once.

The transport binds a receive socket on `0.0.0.0:8089` for incoming queries, and one send socket per local broadcast interface so each subnet broadcast leaves on the right NIC.

## Announcement payload

`serverInfo` includes a `generators[]` array with per-backend hardware capabilities computed once at startup:

```json theme={null}
{
  "id": "buttress-mac-studio",
  "name": "Studio LLM",
  "version": "2.25.0-beta.9",
  "authentication": {
    "required": true,
    "type": "workspace-jwt",
    "kid": "<key id>",
    "bound": true
  },
  "generators": [
    { "type": "ggml-llm", "score": 57, "hasGpu": true, "usableBytes": 21474836480 },
    { "type": "ggml-stt", "score": 57, "hasGpu": true, "usableBytes": 21474836480 }
  ]
}
```

Foundation launchers filter announcements by generator type (LLM vs STT vs MLX) and prefer the highest-scoring server that runs the requested backend.

### Capability score

The score is a 0-100 number combining:

| Component           | Max points | Source                                      |
| ------------------- | ---------- | ------------------------------------------- |
| GPU presence        | 40         | `hasGpu`                                    |
| Backend variant     | 20         | CUDA = 20, Metal = 15, Vulkan = 10, CPU = 5 |
| GPU memory          | 20         | Scaled against a 12 GB reference            |
| CPU memory          | 10         | Scaled against a 32 GB reference            |
| Server availability | 10         | `ok` health flag                            |

A laptop with no GPU scores around 15-25; a workstation with an RTX 4090 lands near 80-90.

## Trust model

Bound servers and unbound servers both announce, but launchers treat them differently:

* **Unbound servers** (`authentication.required = false`) appear as untrusted endpoints. They are still usable from manual / public clients, but bound launchers ignore them.
* **Bound servers** (`authentication.required = true`) are trusted only when their `serverId` is in the workspace's bound-server list **and** the announcement is signed by the matching per-server announce key the workspace registered at bind time.

### Signed announcements

Each Buttress server has its own Ed25519 announce keypair, generated by `bricks buttress bind`. The public half is registered with the BRICKS cloud and surfaced to launchers via `myWorkspaceButtress.buttressServers[].serverPublicKey`; the private half stays in `~/.bricks-cli/buttress/state.json` on the server host.

Every UDP `ANNOUNCE` and `RESPONSE` from a bound server carries a signature over `{ t, d, ts }`. Launchers verify the signature against the registered key with a 30-second replay window — packets without a valid signature never enter the endpoint pool. This closes the spoof vector where a LAN peer could re-announce a bound `serverId` and try to receive a workspace bearer token.

The wire protocol version bumped to **2.0** for signed traffic. Launchers and servers running protocol 1.0 silently drop 2.0 packets and vice versa, so old/new combinations co-exist by going dark rather than swapping unsigned trust. To upgrade an existing bound server, re-run `bricks buttress bind` (which mints a new announce keypair) and restart `bricks-buttress`.

## Manual override

When auto-discovery is impractical (devices on a different subnet, or a cloud-hosted Buttress server), each LLM/STT brick in BRICKS Controller's Config Editor lets you switch from **Auto** to **Manual** and type the WebSocket URL directly. See [Use Buttress from Foundation](/foundation/buttress).

## HTTP fallback

A launcher can also query a known IP directly over HTTP:

```bash theme={null}
curl http://<server-host>:2080/buttress/info
```

The endpoint returns the same `serverInfo` payload as the UDP `ANNOUNCE`. Foundation launchers use this path internally when UDP broadcast is blocked (some enterprise Wi-Fi networks).

## Troubleshooting

| Symptom                                                   | Likely cause                                             | Fix                                                                                 |
| --------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| Devices never find the server                             | UDP broadcast blocked by switch or AP                    | Switch to a wired network, allow `udp/8089` broadcast, or use a manual URL          |
| iOS device finds the server only over Cellular, not Wi-Fi | iOS `IP_BOUND_IF` quirk on the broadcast socket          | Already handled — the launcher rebinds active queries to the Wi-Fi IP automatically |
| Server announces but devices ignore it                    | The server is unbound, or bound to a different workspace | Run `bricks buttress status` and re-bind if needed                                  |
| `serverInfo.generators[]` is empty                        | No generators in the TOML config or all failed to load   | Check the server log for download or hardware probe errors                          |

## Next steps

<CardGroup cols={2}>
  <Card title="Workspace binding" icon="key" href="/buttress/workspace-binding">
    How a server's `kid` and bound-server list are issued.
  </Card>

  <Card title="Use from Foundation" icon="mobile" href="/foundation/buttress">
    Per-brick connection settings: Auto vs Manual, strategy, fallback.
  </Card>
</CardGroup>
