Skip to main content
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.

What to set

Behind one domain, leave it empty on every one of them: the browser then uses the address it loaded the page from.

Resolution order

For the curious, this is the order the browser follows. The first match wins. A trailing slash on the address is ignored, and the browser asks /api/config at most once per page load. The same response also carries commit, the source revision the client was deployed from (SOURCE_COMMIT in the client’s environment, null when unset). It plays no part in resolution and exists so the version a running instance serves can be checked; see the HTTP API reference.
GET /api/config is served by the client, not the signaling server. If both sit behind one reverse proxy, do not route all of /api/ to the server, or step 3 always returns 404 and any SOCKET_URL you set is silently discarded in favor of step 4. See Run behind one domain for the exact-path rule that keeps /api/config on the client, and for a check that shows where it went.

Changing the address

Set it in .env and recreate the container. No rebuild:
Terminal
Docker Compose maps your NEXT_PUBLIC_SOCKET_URL value to the container’s SOCKET_URL, so the variable name in .env has not changed. Outside Compose (the Unraid template, docker run, a direct Node run) nothing does that mapping, so set SOCKET_URL itself. 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. Under Compose, empty means the line NEXT_PUBLIC_SOCKET_URL= with nothing after it: with the line removed, Compose falls back to http://localhost: and the port in PORT (3001 unless you changed it).

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. A shared image cannot carry it, because it would have to know which domain it will be served from before anyone downloads it. So the published image leaves its own address out rather than pointing those tags at floe.one, which would mean every self-hosted instance advertising somebody else’s site as its canonical. Canonical links stay relative, and the share-preview image and the sitemap entries are left out. Container images has the full list. To put your own domain in them, build the client yourself. This needs a clone of the repository, because the build reads its client folder and docker-compose.build.yml: see Building from source. Run it from the repository root:
Terminal
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.
Last modified on October 14, 2026