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

# How the Client Finds the Signaling Server

> How a self-hosted Floe web client resolves its signaling server address at runtime with SOCKET_URL, and when a rebuild is still required.

The browser needs to know where your signaling server is. It works that out when the
page loads, so changing the address takes effect on a restart with no image rebuild.

## Resolution order

The first match wins.

| Order | Source                                                                      | When it applies                                                                                      |
| ----- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| 1     | `NEXT_PUBLIC_SOCKET_URL` baked in at build time                             | Only if you deliberately built an image with a URL compiled in. Empty in the published image.        |
| 2     | `http://localhost:3001`                                                     | Development builds only (`pnpm dev`).                                                                |
| 3     | `SOCKET_URL` on the running client container, served from `GET /api/config` | The normal path for a self-hosted instance.                                                          |
| 4     | The page's own origin                                                       | When `SOCKET_URL` is empty, which is what you want [behind one domain](/docs/self-hosting/reverse-proxy). |

## Changing the address

Set it in `.env` and recreate the container. No rebuild:

```bash theme={null}
docker compose up -d
```

Docker Compose maps your `NEXT_PUBLIC_SOCKET_URL` value to the container's
`SOCKET_URL`, so the variable name in `.env` has not changed.

<Note>
  Leave the value **empty** when the client and the signaling server share one
  origin behind a reverse proxy. The browser then talks to whatever host it was
  loaded from, so there is nothing to configure and nothing to keep in sync.
</Note>

## The address is used by the browser, not the server

Whatever you set has to be reachable **from your users' browsers**, not from inside
the container. `http://localhost:3001` only works when the browser runs on the same
machine as the server. For anything else use the server's LAN IP or public domain.

## What is still build-time

`NEXT_PUBLIC_SITE_URL` is genuinely build-time. It feeds canonical links, Open
Graph tags, and the sitemap, which are rendered into the page rather than fetched.

That is the one value a shared image cannot carry, because it would have to know
which domain it will be served from before anyone downloads it. So the published
image **omits** those tags rather than pointing them at floe.one, which would mean
every self-hosted instance advertising somebody else's site as its canonical.

To put your own domain in them, build the client yourself:

```bash theme={null}
NEXT_PUBLIC_SITE_URL=https://files.example.com \
  docker compose -f docker-compose.yml -f docker-compose.build.yml build client
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d
```

This affects only SEO and link previews. Transfers, signaling, and the relay are
unaffected, and all of those are configured at runtime. See
[Container Images](/docs/self-hosting/images).
