From c49d8ea8912005f81c67e95e37753dfcec831699 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 25 Apr 2026 17:11:42 +0200 Subject: [PATCH 1/2] nginx: route /turn (REST) and /webrtc/signaling/ (WS) to selkies The selkies signaling-server exposes two endpoints that the frontend needs but that the bundled nginx config does not currently route: - `GET /turn` returns the WebRTC ICE config (TURN/STUN servers + HMAC credentials) as JSON. The dashboard fetches this on init. - `wss://.../webrtc/signaling/` is the WebSocket upgrade endpoint used in WebRTC mode (selkies-wr-core builds the URL as `${pathname}/signaling/`, the dashboard sets `appName=webrtc`). Without these locations the dashboard logs: - a `JSON.parse: unexpected character` when /turn returns nginx's HTML 404 page, - `NS_ERROR_WEBSOCKET_CONNECTION_REFUSED` on the signaling URL, followed by a stuck loading state. Both endpoints are served by the same selkies process listening on 127.0.0.1:CWS, so the proxy_pass target is unchanged from the existing /websocket location. Tested with `SELKIES_MODE=webrtc` and `SELKIES_ENABLE_DUAL_MODE=true`: fetching /turn returns the expected RTC config JSON, and the WebRTC peer connection is established. --- root/defaults/default.conf | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/root/defaults/default.conf b/root/defaults/default.conf index 2b6258a..a1d36c6 100644 --- a/root/defaults/default.conf +++ b/root/defaults/default.conf @@ -48,6 +48,26 @@ server { add_header X-Content-Type-Options "nosniff"; } } + # Selkies signaling-server (upstream selkies, src/selkies/signaling_server.py) + # exposes a few HTTP endpoints next to the WebSocket upgrade handler: + # /turn returns the TURN/STUN config as JSON, and any path ending in + # /signaling is upgraded to a WebSocket for the WebRTC peer-handshake. + # The selkies-dashboard frontend connects to /webrtc/signaling/ when the + # streamMode is "webrtc", and fetches /turn for TURN credentials. + location SUBFOLDERturn { + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_buffering off; + proxy_pass http://127.0.0.1:CWS; + } + location ~ ^/webrtc/signaling/?$ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_buffering off; + proxy_pass http://127.0.0.1:CWS; + } error_page 500 502 503 504 /50x.html; location = SUBFOLDER50x.html { root /usr/share/selkies/web/; @@ -106,6 +126,26 @@ server { add_header X-Content-Type-Options "nosniff"; } } + # Selkies signaling-server (upstream selkies, src/selkies/signaling_server.py) + # exposes a few HTTP endpoints next to the WebSocket upgrade handler: + # /turn returns the TURN/STUN config as JSON, and any path ending in + # /signaling is upgraded to a WebSocket for the WebRTC peer-handshake. + # The selkies-dashboard frontend connects to /webrtc/signaling/ when the + # streamMode is "webrtc", and fetches /turn for TURN credentials. + location SUBFOLDERturn { + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_buffering off; + proxy_pass http://127.0.0.1:CWS; + } + location ~ ^/webrtc/signaling/?$ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_buffering off; + proxy_pass http://127.0.0.1:CWS; + } error_page 500 502 503 504 /50x.html; location = SUBFOLDER50x.html { root /usr/share/selkies/web/; From 112435d0b4e800d99bf4b06ade1f9c88e744a83e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 25 Apr 2026 18:06:37 +0200 Subject: [PATCH 2/2] nginx: align webrtc/signaling proxy with SUBFOLDERwebsocket, honour SUBFOLDER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues raised in review (both server blocks, :3000 and :3001): 1. The signaling regex was anchored at root: `^/webrtc/signaling/?$`. With a non-default SUBFOLDER deployment (e.g. SUBFOLDER=/foo/), the request path `/foo/webrtc/signaling/` would not match and would fall through to the static handler. Replace the leading `/` with the SUBFOLDER placeholder so the same sed substitution that processes every other location block also applies here. Default `SUBFOLDER=/` keeps the regex equivalent to before. 2. The new WebSocket location was missing the long timeouts and forwarded client headers that `SUBFOLDERwebsocket` already sets. Without them, signaling sessions can be cut by nginx defaults and selkies upstream sees only 127.0.0.1 as the client IP. Mirror the full set: X-Real-IP, X-Forwarded-For, X-Forwarded-Proto, the three 3600s timeouts, and client_max_body_size 10M. /turn gains the same forwarded headers (no timeouts — short HTTP request). --- root/defaults/default.conf | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/root/defaults/default.conf b/root/defaults/default.conf index a1d36c6..8bdcaf1 100644 --- a/root/defaults/default.conf +++ b/root/defaults/default.conf @@ -56,16 +56,26 @@ server { # streamMode is "webrtc", and fetches /turn for TURN credentials. location SUBFOLDERturn { proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_buffering off; proxy_pass http://127.0.0.1:CWS; } - location ~ ^/webrtc/signaling/?$ { + location ~ ^SUBFOLDERwebrtc/signaling/?$ { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + proxy_connect_timeout 3600s; proxy_buffering off; + client_max_body_size 10M; proxy_pass http://127.0.0.1:CWS; } error_page 500 502 503 504 /50x.html; @@ -134,16 +144,26 @@ server { # streamMode is "webrtc", and fetches /turn for TURN credentials. location SUBFOLDERturn { proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_buffering off; proxy_pass http://127.0.0.1:CWS; } - location ~ ^/webrtc/signaling/?$ { + location ~ ^SUBFOLDERwebrtc/signaling/?$ { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + proxy_connect_timeout 3600s; proxy_buffering off; + client_max_body_size 10M; proxy_pass http://127.0.0.1:CWS; } error_page 500 502 503 504 /50x.html;