Skip to content

Commit 2bba87f

Browse files
committed
fix: allow using sfu in the same domain
1 parent fe26958 commit 2bba87f

6 files changed

Lines changed: 54 additions & 87 deletions

File tree

deploy/.env.example

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99
# ==============================================================================
1010

1111
# === Domain & SSL =============================================================
12-
# Main domain for the Frappe Meet app (A record must point to this server).
12+
# Domain for Frappe Meet (A record must point to this server).
13+
# The SFU is served at https://DOMAIN/sfu/ — no separate subdomain needed.
1314
DOMAIN=meet.example.com
1415

15-
# Subdomain for the SFU server (A record must point to this server).
16-
SFU_DOMAIN=sfu.meet.example.com
17-
1816
# Email for Let's Encrypt certificate notifications.
1917
SSL_EMAIL=admin@example.com
2018

deploy/deploy.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ check_env() {
9696
local errors=false
9797

9898
# Required fields
99-
for var in DOMAIN SFU_DOMAIN SSL_EMAIL DB_ROOT_PASSWORD DB_PASSWORD ADMIN_PASSWORD SITE_NAME; do
99+
for var in DOMAIN SSL_EMAIL DB_ROOT_PASSWORD DB_PASSWORD ADMIN_PASSWORD SITE_NAME; do
100100
if [ -z "${!var:-}" ]; then
101101
err "$var must be set in .env"
102102
errors=true
@@ -122,8 +122,8 @@ check_env() {
122122
fi
123123

124124
ok "DOMAIN = $DOMAIN"
125-
ok "SFU_DOMAIN = $SFU_DOMAIN"
126125
ok "WEBRTC_ANNOUNCED_IP = $WEBRTC_ANNOUNCED_IP"
126+
ok "SFU served at https://$DOMAIN/sfu/"
127127
ok "Configuration is valid"
128128
}
129129

@@ -185,7 +185,7 @@ cmd_setup() {
185185
fi
186186

187187
# Set SFU config on site
188-
run_bench --site "$SITE_NAME" set-config sfu_server_url "https://$SFU_DOMAIN"
188+
run_bench --site "$SITE_NAME" set-config sfu_server_url "https://$DOMAIN/sfu"
189189
run_bench --site "$SITE_NAME" set-config sfu_secret "$SFU_SECRET"
190190
ok "SFU configuration applied"
191191

@@ -210,7 +210,7 @@ cmd_setup() {
210210
echo ""
211211
header "Setup complete!"
212212
ok "Meet is live at https://$DOMAIN"
213-
ok "SFU is running at https://$SFU_DOMAIN"
213+
ok "SFU endpoint: https://$DOMAIN/sfu/"
214214
info "Login: Administrator / <your ADMIN_PASSWORD>"
215215
echo ""
216216
}

deploy/docker-compose.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ services:
148148
- certbot-certs:/etc/letsencrypt:ro
149149
environment:
150150
DOMAIN: ${DOMAIN}
151-
SFU_DOMAIN: ${SFU_DOMAIN}
152151
FRAPPE_UPSTREAM: frappe-frontend:8080
153152
SFU_UPSTREAM: ${WEBRTC_ANNOUNCED_IP:-127.0.0.1}:${SFU_PORT:-3000}
154153
depends_on:

deploy/nginx/certbot-init.sh

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ set -a
2121
source "$DEPLOY_DIR/.env"
2222
set +a
2323

24-
if [ -z "${DOMAIN:-}" ] || [ -z "${SFU_DOMAIN:-}" ]; then
25-
echo "[-] DOMAIN and SFU_DOMAIN must be set in .env"
24+
if [ -z "${DOMAIN:-}" ]; then
25+
echo "[-] DOMAIN must be set in .env"
2626
exit 1
2727
fi
2828

@@ -31,7 +31,7 @@ if [ -z "${SSL_EMAIL:-}" ]; then
3131
exit 1
3232
fi
3333

34-
echo "[*] Provisioning SSL certificates for: $DOMAIN, $SFU_DOMAIN"
34+
echo "[*] Provisioning SSL certificate for: $DOMAIN"
3535
echo "[*] Registration email: $SSL_EMAIL"
3636
echo ""
3737

@@ -72,20 +72,18 @@ echo "▶ Starting nginx for ACME challenge..."
7272
$COMPOSE_CMD up -d nginx
7373
sleep 3
7474

75-
# Step 3: Request certificates
76-
for CERT_DOMAIN in "$DOMAIN" "$SFU_DOMAIN"; do
77-
echo "▶ Requesting certificate for $CERT_DOMAIN..."
78-
$COMPOSE_CMD \
79-
run --rm --entrypoint certbot certbot \
80-
certonly \
81-
--webroot \
82-
--webroot-path=/var/www/certbot \
83-
--email "$SSL_EMAIL" \
84-
--agree-tos \
85-
--no-eff-email \
86-
--force-renewal \
87-
-d "$CERT_DOMAIN"
88-
done
75+
# Step 3: Request certificate
76+
echo "▶ Requesting certificate for $DOMAIN..."
77+
$COMPOSE_CMD \
78+
run --rm --entrypoint certbot certbot \
79+
certonly \
80+
--webroot \
81+
--webroot-path=/var/www/certbot \
82+
--email "$SSL_EMAIL" \
83+
--agree-tos \
84+
--no-eff-email \
85+
--force-renewal \
86+
-d "$DOMAIN"
8987

9088
# Step 4: Restore real nginx config
9189
if [ -f "$BACKUP_CONF" ]; then

deploy/nginx/templates/default.conf.template

Lines changed: 18 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
# Frappe Meet — Nginx Configuration
33
# ==============================================================================
44
# Variables substituted at container start by nginx:alpine entrypoint:
5-
# $DOMAIN, $SFU_DOMAIN, $FRAPPE_UPSTREAM, $SFU_UPSTREAM
5+
# $DOMAIN, $FRAPPE_UPSTREAM, $SFU_UPSTREAM
6+
#
7+
# Routing:
8+
# https://DOMAIN/sfu/ → SFU server (path prefix stripped)
9+
# https://DOMAIN/ → Frappe
610
# ==============================================================================
711

812
map $http_upgrade $connection_upgrade {
@@ -14,7 +18,7 @@ map $http_upgrade $connection_upgrade {
1418
server {
1519
listen 80;
1620
listen [::]:80;
17-
server_name ${DOMAIN} ${SFU_DOMAIN};
21+
server_name ${DOMAIN};
1822

1923
location /.well-known/acme-challenge/ {
2024
root /var/www/certbot;
@@ -25,7 +29,7 @@ server {
2529
}
2630
}
2731

28-
# ── HTTPS: Frappe Meet ───────────────────────────────────────────────────────
32+
# ── HTTPS ────────────────────────────────────────────────────────────────────
2933
server {
3034
listen 443 ssl;
3135
listen [::]:443 ssl;
@@ -43,40 +47,11 @@ server {
4347

4448
client_max_body_size 50m;
4549

46-
location / {
47-
proxy_pass http://${FRAPPE_UPSTREAM};
48-
proxy_http_version 1.1;
49-
proxy_set_header Upgrade $http_upgrade;
50-
proxy_set_header Connection $connection_upgrade;
51-
proxy_set_header Host $host;
52-
proxy_set_header X-Real-IP $remote_addr;
53-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
54-
proxy_set_header X-Forwarded-Proto $scheme;
55-
proxy_read_timeout 120s;
56-
proxy_send_timeout 120s;
57-
proxy_buffering off;
58-
}
59-
}
60-
61-
# ── HTTPS: SFU Server ────────────────────────────────────────────────────────
62-
server {
63-
listen 443 ssl;
64-
listen [::]:443 ssl;
65-
server_name ${SFU_DOMAIN};
66-
67-
ssl_certificate /etc/letsencrypt/live/${SFU_DOMAIN}/fullchain.pem;
68-
ssl_certificate_key /etc/letsencrypt/live/${SFU_DOMAIN}/privkey.pem;
69-
ssl_protocols TLSv1.2 TLSv1.3;
70-
ssl_prefer_server_ciphers off;
71-
ssl_session_cache shared:SFU_SSL:10m;
72-
ssl_session_timeout 1d;
73-
ssl_session_tickets off;
74-
75-
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
76-
77-
# Socket.IO / WebSocket
78-
location /socket.io/ {
79-
proxy_pass http://${SFU_UPSTREAM};
50+
# ── SFU Server (path-based routing, prefix stripped) ──────────────────
51+
# /sfu/socket.io/... → SFU socket.io
52+
# /sfu/health → SFU health check
53+
location /sfu/ {
54+
proxy_pass http://${SFU_UPSTREAM}/;
8055
proxy_http_version 1.1;
8156
proxy_set_header Upgrade $http_upgrade;
8257
proxy_set_header Connection $connection_upgrade;
@@ -89,25 +64,18 @@ server {
8964
proxy_buffering off;
9065
}
9166

92-
# HTTP API & Health
67+
# ── Frappe (everything else) ──────────────────────────────────────────
9368
location / {
94-
proxy_pass http://${SFU_UPSTREAM};
69+
proxy_pass http://${FRAPPE_UPSTREAM};
9570
proxy_http_version 1.1;
71+
proxy_set_header Upgrade $http_upgrade;
72+
proxy_set_header Connection $connection_upgrade;
9673
proxy_set_header Host $host;
9774
proxy_set_header X-Real-IP $remote_addr;
9875
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9976
proxy_set_header X-Forwarded-Proto $scheme;
100-
proxy_set_header Upgrade $http_upgrade;
101-
proxy_set_header Connection $connection_upgrade;
102-
proxy_read_timeout 86400s;
103-
proxy_send_timeout 86400s;
77+
proxy_read_timeout 120s;
78+
proxy_send_timeout 120s;
10479
proxy_buffering off;
10580
}
106-
107-
location = /health {
108-
proxy_pass http://${SFU_UPSTREAM}/health;
109-
proxy_http_version 1.1;
110-
proxy_set_header Host $host;
111-
access_log off;
112-
}
11381
}

frontend/src/utils/sfu-client.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,27 +120,30 @@ class SFUClient {
120120
};
121121
}
122122

123-
async getSFUEndpoint() {
123+
getSFUEndpoint() {
124124
const { sfuUrl, sfuPort } = this.connectionDetails;
125125

126-
let sfuEndpoint;
127126
const urlObj = new URL(sfuUrl);
128127
const isSecured = urlObj.protocol === "https:";
129128

130-
if (isSecured) {
131-
sfuEndpoint = urlObj.origin;
132-
} else {
133-
sfuEndpoint = `${urlObj.protocol}//${urlObj.hostname}:${sfuPort}`;
134-
}
129+
const origin = isSecured
130+
? urlObj.origin
131+
: `${urlObj.protocol}//${urlObj.hostname}:${sfuPort}`;
132+
133+
// If the URL has a pathname (e.g. /sfu), use it as the socket.io path prefix.
134+
// Otherwise fall back to the default /socket.io/.
135+
const basePath = urlObj.pathname.replace(/\/$/, ""); // strip trailing slash
136+
const socketPath = basePath ? `${basePath}/socket.io` : "/socket.io";
135137

136-
return sfuEndpoint;
138+
return { origin, socketPath };
137139
}
138140

139141
async establishSocketConnection() {
140-
const sfuEndpoint = await this.getSFUEndpoint();
142+
const { origin, socketPath } = this.getSFUEndpoint();
141143
const { authToken } = this.connectionDetails;
142144

143-
this.socket = io(sfuEndpoint, {
145+
this.socket = io(origin, {
146+
path: socketPath,
144147
auth: { token: authToken },
145148
reconnection: true,
146149
reconnectionAttempts: 5,
@@ -167,7 +170,8 @@ class SFUClient {
167170
description: error.description,
168171
context: error.context,
169172
type: error.type,
170-
endpoint: sfuEndpoint,
173+
endpoint: origin,
174+
path: socketPath,
171175
});
172176
this.connected = false;
173177
reject(new Error(`SFU connection failed: ${error.message || error}`));

0 commit comments

Comments
 (0)