fix: use config for turn

This commit is contained in:
Abhishek Kumar 2025-12-22 14:06:17 +05:30
parent 17409998d2
commit 4ddb144dd0
4 changed files with 846 additions and 769 deletions

View file

@ -156,9 +156,10 @@ services:
SENTRY_DSN: "https://d9387fed5f80e90781f1dbd9b2c0994c@o4509486225096704.ingest.us.sentry.io/4510124708200448"
# TURN server configuration (for WebRTC NAT traversal in remote server)
NEXT_PUBLIC_TURN_HOST: "${TURN_HOST:-}"
NEXT_PUBLIC_TURN_USERNAME: "${TURN_USERNAME:-}"
NEXT_PUBLIC_TURN_PASSWORD: "${TURN_PASSWORD:-}"
# Fetched at runtime via /api/config/turn endpoint
TURN_HOST: "${TURN_HOST:-}"
TURN_USERNAME: "${TURN_USERNAME:-}"
TURN_PASSWORD: "${TURN_PASSWORD:-}"
ports:
- "3010:3010"
depends_on:

1546
ui/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
/*
Route to provide TURN server configuration at runtime.
This allows OSS users to configure TURN servers via docker-compose.yaml
environment variables, since NEXT_PUBLIC_* keys are injected at build time.
*/
import { NextResponse } from 'next/server';
export async function GET() {
const host = process.env.TURN_HOST || '';
const username = process.env.TURN_USERNAME || '';
const password = process.env.TURN_PASSWORD || '';
// Only return enabled: true if all required fields are set
const enabled = !!(host && username && password);
return NextResponse.json({
enabled,
host,
username,
password,
});
}

View file

@ -39,11 +39,13 @@ export const useWebSocketRTC = ({ workflowId, workflowRunId, accessToken, initia
const useAudio = true;
const audioCodec = 'default';
// TURN server configuration from environment variables (matching backend pattern)
const turnHost = process.env.NEXT_PUBLIC_TURN_HOST;
const turnUsername = process.env.NEXT_PUBLIC_TURN_USERNAME;
const turnPassword = process.env.NEXT_PUBLIC_TURN_PASSWORD;
const useTurn = !!(turnHost && turnUsername && turnPassword);
// TURN server configuration fetched at runtime from /api/config/turn
const turnConfigRef = useRef<{
enabled: boolean;
host: string;
username: string;
password: string;
} | null>(null);
const audioRef = useRef<HTMLAudioElement>(null);
const pcRef = useRef<RTCPeerConnection | null>(null);
@ -80,18 +82,19 @@ export const useWebSocketRTC = ({ workflowId, workflowRunId, accessToken, initia
iceServers.push({ urls: ['stun:stun.l.google.com:19302'] });
}
if (useTurn && turnHost && turnUsername && turnPassword) {
// Add TURN server with credentials from environment variables
// Add TURN server if configured (fetched from /api/config/turn)
const turnConfig = turnConfigRef.current;
if (turnConfig?.enabled) {
iceServers.push({
urls: [
`turn:${turnHost}:3478`, // TURN over UDP
`turn:${turnHost}:3478?transport=tcp`, // TURN over TCP
`turn:${turnConfig.host}:3478`, // TURN over UDP
`turn:${turnConfig.host}:3478?transport=tcp`, // TURN over TCP
],
username: turnUsername,
credential: turnPassword
username: turnConfig.username,
credential: turnConfig.password
});
logger.info(`TURN server configured: ${turnHost}:3478`);
logger.info(`TURN server configured: ${turnConfig.host}:3478`);
}
const config: RTCConfiguration = {
@ -329,6 +332,19 @@ export const useWebSocketRTC = ({ workflowId, workflowRunId, accessToken, initia
setConnectionStatus('connecting');
try {
// Fetch TURN configuration at runtime
try {
const turnResponse = await fetch('/api/config/turn');
if (turnResponse.ok) {
turnConfigRef.current = await turnResponse.json();
if (turnConfigRef.current?.enabled) {
logger.info('TURN server enabled via runtime config');
}
}
} catch (e) {
logger.warn('Failed to fetch TURN config, continuing without TURN:', e);
}
// Validate API keys
const response = await validateUserConfigurationsApiV1UserConfigurationsUserValidateGet({
headers: {