mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-07 07:55:16 +02:00
add FORCE_TURN_RELAY option in docker-compose
This commit is contained in:
parent
c0e8b631c4
commit
e2fe2919bb
6 changed files with 96 additions and 7 deletions
|
|
@ -241,12 +241,10 @@ async def _run_pipeline(
|
|||
raise HTTPException(status_code=400, detail="Workflow run already completed")
|
||||
|
||||
merged_call_context_vars = workflow_run.initial_context
|
||||
# If there is some extra call_context_vars, update them
|
||||
# If there is some extra call_context_vars, fold them in. Persistence
|
||||
# happens once below, after runtime_configuration is also resolved.
|
||||
if call_context_vars:
|
||||
merged_call_context_vars = {**merged_call_context_vars, **call_context_vars}
|
||||
await db_client.update_workflow_run(
|
||||
workflow_run_id, initial_context=merged_call_context_vars
|
||||
)
|
||||
|
||||
# Get user configuration
|
||||
user_config = await db_client.get_user_configurations(user_id)
|
||||
|
|
@ -312,6 +310,36 @@ async def _run_pipeline(
|
|||
llm = create_llm_service(user_config)
|
||||
inference_llm = None
|
||||
|
||||
# Stamp the providers/models actually resolved for this run onto
|
||||
# initial_context so they're available for post-call analytics
|
||||
# (model_overrides may have shifted them away from the org-level
|
||||
# user_config).
|
||||
if is_realtime:
|
||||
# llm_* refers to the side-channel text LLM (variable extraction,
|
||||
# voicemail detection); realtime_* is the speech-to-speech service.
|
||||
runtime_configuration = {
|
||||
"realtime_provider": user_config.realtime.provider,
|
||||
"realtime_model": user_config.realtime.model,
|
||||
"llm_provider": user_config.llm.provider,
|
||||
"llm_model": user_config.llm.model,
|
||||
}
|
||||
else:
|
||||
runtime_configuration = {
|
||||
"stt_provider": user_config.stt.provider,
|
||||
"stt_model": user_config.stt.model,
|
||||
"tts_provider": user_config.tts.provider,
|
||||
"tts_model": user_config.tts.model,
|
||||
"llm_provider": user_config.llm.provider,
|
||||
"llm_model": user_config.llm.model,
|
||||
}
|
||||
merged_call_context_vars = {
|
||||
**merged_call_context_vars,
|
||||
"runtime_configuration": runtime_configuration,
|
||||
}
|
||||
await db_client.update_workflow_run(
|
||||
workflow_run_id, initial_context=merged_call_context_vars
|
||||
)
|
||||
|
||||
workflow_graph = WorkflowGraph(ReactFlowDTO.model_validate(run_workflow_json))
|
||||
|
||||
# Pre-call fetch: fire early so it runs concurrently with remaining setup
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ async def check_dograh_quota(
|
|||
|
||||
logger.info(
|
||||
f"Dograh quota check passed for key ...{api_key[-8:]}: "
|
||||
f"${remaining:.2f} remaining"
|
||||
f"{remaining:.2f} credits remaining"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to check quota for Dograh key: {str(e)}")
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ services:
|
|||
# Uses time-limited credentials via TURN REST API (HMAC-SHA1)
|
||||
TURN_HOST: "${TURN_HOST:-}"
|
||||
TURN_SECRET: "${TURN_SECRET:-}"
|
||||
FORCE_TURN_RELAY: "${FORCE_TURN_RELAY:-false}"
|
||||
|
||||
OSS_JWT_SECRET: "${OSS_JWT_SECRET:-ChangeMeInProduction}"
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,38 @@ http://localhost:3010
|
|||
You can disable telemetry by setting `ENABLE_TELEMETRY=false` in the command above.
|
||||
</Note>
|
||||
|
||||
### Troubleshooting WebRTC Connectivity
|
||||
|
||||
The Quick Start above relies on direct peer-to-peer WebRTC between your browser and the API container. On most single-machine setups this works without any extra configuration. If you hit any of the following, you likely need a TURN server in the path:
|
||||
|
||||
- The call connects but no audio flows in either direction
|
||||
- The browser console reports `iceConnectionState: failed`
|
||||
- You are testing from a phone or another device on your LAN against the laptop running Docker
|
||||
- A VPN, corporate firewall, or strict NAT sits between the browser and Docker
|
||||
|
||||
For these cases, use the alternate local setup script which configures a coturn TURN server alongside the rest of the stack:
|
||||
|
||||
```bash
|
||||
curl -o setup_local.sh https://raw.githubusercontent.com/dograh-hq/dograh/main/scripts/setup_local.sh && chmod +x setup_local.sh && ./setup_local.sh
|
||||
```
|
||||
|
||||
The script will prompt you for:
|
||||
- Whether to enable coturn (answer `y`)
|
||||
- The host browsers should use to reach TURN (press Enter for `127.0.0.1`; use your LAN IP if testing from another device on the same network)
|
||||
- A shared secret for the TURN server (press Enter to generate a random one)
|
||||
|
||||
It creates `docker-compose.yaml`, `turnserver.conf`, and a `.env` file with TURN credentials. Start the stack with the `local-turn` profile so coturn comes up alongside the other services:
|
||||
|
||||
```bash
|
||||
docker compose --profile local-turn up --pull always
|
||||
```
|
||||
|
||||
The application is still available at `http://localhost:3010`.
|
||||
|
||||
<Note>
|
||||
To verify that media is actually traversing TURN (and not silently falling back to a direct path), set `FORCE_TURN_RELAY=true` in `.env` and restart the API. The browser will then only use relay ICE candidates — if TURN is misconfigured or unreachable, the call fails cleanly with `ICE failed` in the console instead of appearing to work. Set it back to `false` once you have verified connectivity.
|
||||
</Note>
|
||||
|
||||
## Option 2: Remote Server Deployment
|
||||
|
||||
Watch the video tutorial below for a step-by-step walkthrough of deploying Dograh AI to a remote server.
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ Dograh uses **MinIO by default**, which is bundled with the self-hosted deployme
|
|||
| `TURN_TLS_PORT` | `5349` | TURN server TLS port |
|
||||
| `TURN_SECRET` | `null` | **Required for WebRTC.** Shared secret for TURN credential generation |
|
||||
| `TURN_CREDENTIAL_TTL` | `86400` | TURN credential validity in seconds (default: 24h) |
|
||||
| `FORCE_TURN_RELAY` | `false` | Diagnostic flag. When `true`, restricts ICE to relay-only candidates on both server (SDP filter) and browser (`iceTransportPolicy: 'relay'`). Use to verify TURN connectivity end-to-end — calls fail cleanly if TURN is misconfigured instead of silently falling back to a direct path. |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -27,12 +27,39 @@ if [[ -z "$ENABLE_COTURN" ]]; then
|
|||
fi
|
||||
|
||||
if [[ "$ENABLE_COTURN" == "true" ]]; then
|
||||
# Pick a TURN_HOST that's reachable from BOTH the browser (running on the
|
||||
# host) and the API container (running in docker). 127.0.0.1 is tempting
|
||||
# but doesn't work for the api container — its own loopback isn't where
|
||||
# coturn lives, so aiortc can't allocate a relay and FORCE_TURN_RELAY
|
||||
# ends up with an empty answer SDP. The host's LAN IP works for both.
|
||||
detect_lan_ip() {
|
||||
local ip=""
|
||||
if command -v ipconfig >/dev/null 2>&1; then
|
||||
for iface in en0 en1 en2 en3 en4; do
|
||||
ip=$(ipconfig getifaddr "$iface" 2>/dev/null)
|
||||
[[ -n "$ip" ]] && { echo "$ip"; return; }
|
||||
done
|
||||
fi
|
||||
if command -v ip >/dev/null 2>&1; then
|
||||
ip=$(ip -4 route get 1.1.1.1 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="src") print $(i+1)}')
|
||||
[[ -n "$ip" ]] && { echo "$ip"; return; }
|
||||
fi
|
||||
if command -v hostname >/dev/null 2>&1; then
|
||||
ip=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||||
[[ -n "$ip" ]] && { echo "$ip"; return; }
|
||||
fi
|
||||
}
|
||||
|
||||
DEFAULT_TURN_HOST="$(detect_lan_ip)"
|
||||
DEFAULT_TURN_HOST="${DEFAULT_TURN_HOST:-127.0.0.1}"
|
||||
|
||||
# Get the host browsers/peers will use to reach the TURN server
|
||||
if [[ -z "$TURN_HOST" ]]; then
|
||||
echo -e "${YELLOW}Enter the host browsers should use to reach TURN (press Enter for 127.0.0.1):${NC}"
|
||||
echo -e "${YELLOW}Enter the host browsers AND the API container will use to reach TURN${NC}"
|
||||
echo -e "${YELLOW}(press Enter for ${DEFAULT_TURN_HOST}):${NC}"
|
||||
read -p "> " TURN_HOST
|
||||
fi
|
||||
TURN_HOST="${TURN_HOST:-127.0.0.1}"
|
||||
TURN_HOST="${TURN_HOST:-$DEFAULT_TURN_HOST}"
|
||||
|
||||
# Validate that TURN_HOST is either an IP or a hostname (basic check)
|
||||
if ! [[ "$TURN_HOST" =~ ^[A-Za-z0-9.-]+$ ]]; then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue