Troubleshooting
Symptom-first fixes for the failures that come up wiring a container behind a reverse proxy: cross-origin breakage, broker secret mismatches, dead-on-load rooms, and stale sessions.
Start here by symptom. Most of these trace back to the reverse proxy
contract or the config.yml keys covering
host, broker_host, subfolder and broker_secret.
This page is scoped to reverse-proxy and cross-origin failures. For other setup problems (the container won't start, the stream stays black, a specific game won't launch), see Troubleshooting.
Camera/microphone denied instantly, or invite links say "Could not create an invite link"
You get no permission prompt at all, and the invite buttons fall back to a
manual copy box instead of copying the link automatically. This is a
cross-origin problem: browsers only fully trust a page when it's served
from the same website address ("origin") as the page around it. Here,
host in config.yml points at a different origin than RomM's (its own
domain, or RomM's host on another port or scheme), so the browser treats the room as a different
website and blocks it from ever asking for camera, microphone, or clipboard
access. No reverse-proxy setting can fix this. See the callout at the top
of Reverse proxy for why, and the
RomM-side section there for the config change that actually fixes it
(serving the container from a subfolder of RomM's own origin).
Room loads, then just sits there dead
The page and its assets are all loading fine, so this isn't a URL-prefix problem. It's the websocket connection (the live, two-way link the room uses for chat and game controls) failing to open. Check:
- Make sure your proxy is actually forwarding the
UpgradeandConnection: upgradeheaders on this specific route, not just for the site as a whole. This trips people up especially in Nginx Proxy Manager: turning on the Proxy Host's Websockets Support toggle doesn't reliably carry over to a Custom Location you've added, so paste the upgrade headers into that location's own Advanced box too, whether or not the toggle is on. See the Nginx Proxy Manager tab for the exact lines to paste. - Check that
proxy_read_timeout(or whatever your proxy calls the same setting) is set long enough that it won't cut off an idle session's connection in the middle of a game.
Assets 404, or the page loads with a broken layout
Your reverse proxy is stripping off the mount path (the URL prefix, such as
/streaming) before it forwards the request. This is exactly the problem
the contract page warns
about: most proxies strip that prefix by default. On nginx, that usually
means an extra path piece got added to proxy_pass. On Traefik, it's a
stripPrefix middleware. On Caddy, it's using handle_path instead of
handle. Run the curl checks under
Verifying to see which side is
wrong: if the asset src links on the page are missing the prefix,
SUBFOLDER isn't set; if they have the prefix but still 404, the proxy is
stripping it.
RomM says "This container's host has no scheme, so it can never be claimed"
This means host in config.yml is just a bare path (/streaming), with
no https:// and domain name in front of it. Give it a full URL on RomM's
own domain instead, for example https://romm.example.com/streaming. That
keeps everything on the same origin, so none of the cross-origin problems
described above apply, while still satisfying RomM's check. Leave
subfolder and broker_host as they were. Only host needs to change.
Session looks claimed but nothing responds, even after fixing config.yml
Two separate things can cause this. It's worth ruling out both:
- RomM only reads
config.ymlwhen it starts up, not on every request. You need to restart RomM for it to pick up any edit tohost,broker_host,subfolder, orbroker_secret. - A session that was claimed under the old settings is still using the old address. After restarting, end that session from RomM's streaming settings (or wait for it to expire), instead of expecting the new config to fix a session that's already in progress.
Traefik sends /streaming/ to RomM, or answers with an intermittent 502
Both symptoms come from the Traefik labels rather than the container.
- RomM's page loads at
/streaming/instead of the room. RomM's router matches every path on the domain, and it is winning over the container's. Give the container's router a higherprioritythan RomM's. - Some requests work and others return
502 Bad Gateway. The service is attached to more than one Docker network and Traefik is sometimes using an address on a network it isn't part of. Settraefik.docker.networkto the network Traefik shares with the service.
The Traefik tab has a full example with both settings.
Activate/join/exit calls fail with 403, and the broker log shows rejected request: bad or missing broker secret
BROKER_SECRET on the container and broker_secret in RomM's config.yml
entry for that container are two separate settings, and they both need to
be set to the same value. Setting one and not the other, or setting them to
different values, produces this exact log line. If BROKER_SECRET isn't
set on the container at all, this check doesn't run at all, so seeing this
warning tells you it is set, and the two sides just disagree. See
BROKER_SECRET and the config.yml example in
Wiring it into RomM. If RomM has
STREAMING_BROKER_SECRET set in its environment, that value is used instead
of broker_secret for every container, so check it too.
Where to look next
- The broker's own logs are the best source of truth for anything happening server-to-server (activate, join, exit, the secret check above). Your browser's console only shows what actually reaches the browser.
- In your browser's developer tools, the network tab filtered to WS (short for websocket) is the fastest way to tell two failure modes apart: "the websocket never upgraded" (you never see a 101 response) versus "it upgraded and then dropped" (usually a proxy timeout).
- Reverse proxy has the full contract and per-proxy recipes if none of the symptoms above match what you're seeing.