If you are hosted by us, this is already pre-configured on your site. This guide is for admins self-hosting Discourse.
Discourse Voice uses WebRTC for voice and video calls. It ships with public STUN servers to help participants connect directly. Admins can replace those servers and add TURN to support networks where direct connections fail.
For a server dedicated to your community, we recommend TURN with shared-secret authentication and an empty STUN setting. This provides public-address discovery and a relay fallback without distributing a permanent TURN password.
This guide applies to Voice’s peer-to-peer calls. Rooms using LiveKit use LiveKit’s own ICE/TURN configuration instead. Learn about Voice’s LiveKit configuration.
What do STUN and TURN do?
- STUN helps a browser discover its public IP address and port so it can attempt a direct connection.
- TURN relays media when a direct connection cannot be established.
An authenticated TURN allocation also returns the browser’s public address. WebRTC can use this as a server-reflexive candidate, providing the address-discovery benefit of STUN without a separate STUN server. TURN specification.
With shared-secret TURN configured, Voice allows both direct and relayed connections even when its STUN setting is empty. Configuring only TURN servers does not force every call through the relay. Voice’s ICE configuration.
1. Prepare a TURN server
You can use a managed TURN service that supports TURN REST API shared-secret authentication, or run coturn yourself.
For a self-hosted setup, prepare:
- A server with a public IP address and sufficient bandwidth for relayed calls.
- A hostname such as
turn.example.com, pointing directly to that server. - Firewall access for its TURN listener and UDP relay port range.
- A valid certificate if you offer TURN over TLS.
Participants’ browsers connect to TURN directly. An ordinary HTTP reverse proxy or CDN proxy cannot carry TURN traffic.
Example coturn configuration
Generate a random secret:
openssl rand -hex 32
Keep the result private. You will enter the same value in coturn and Discourse.
On a server with a directly assigned public IP, use the following as a starting point in /etc/turnserver.conf:
listening-port=3478
fingerprint
realm=turn.example.com
use-auth-secret
static-auth-secret=REPLACE_WITH_YOUR_RANDOM_SECRET
# Disable standalone STUN requests.
# Authenticated TURN allocations still return the client's public address.
no-stun
min-port=49152
max-port=65535
no-multicast-peers
# This example starts without TLS.
no-tls
no-dtls
Replace the hostname and secret, protect the configuration file, and restart coturn. Remove any conflicting no-auth or static user= configuration. Coturn’s shared-secret mode enables the authentication mechanism it needs internally. Coturn configuration reference.
Allow inbound traffic to:
| Port | Protocol | Purpose |
|---|---|---|
3478 |
UDP and TCP | Browser connections to TURN |
49152–65535 |
UDP | Relayed media |
Allow the corresponding outbound traffic too. The relay range must match min-port and max-port.
If the server sits behind NAT, configure coturn’s external-ip=PUBLIC_IP/PRIVATE_IP mapping and forward the listener and relay ports. Relay ports must retain their port numbers through NAT. Coturn deployment options.
Add TLS for restrictive networks
TURN over TLS provides another connection option for participants whose networks block UDP.
Remove no-tls and configure:
tls-listening-port=5349
cert=/path/to/fullchain.pem
pkey=/path/to/privkey.pem
Open 5349/TCP, ensure coturn can read the certificate and key, and restart it after certificate renewals.
You can use 443/TCP instead if that port is available on the TURN server. This may help on restrictive networks, although some networks also inspect and block non-HTTP traffic on port 443. The UDP relay range is still required when browsers reach TURN over TCP or TLS. Coturn server documentation.
2. Configure Discourse
In Admin → Settings, search for these Voice settings:
| Setting | Value |
|---|---|
voice_stun_servers |
Empty — remove the default entries |
voice_turn_secret |
The value used for coturn’s static-auth-secret |
voice_turn_secret_servers |
Your TURN URIs, separated by | |
voice_turn_servers |
Empty |
voice_turn_username |
Empty |
voice_turn_credential |
Empty |
For the configuration above, enter this in voice_turn_secret_servers:
turn:turn.example.com:3478?transport=udp|turn:turn.example.com:3478?transport=tcp
If you enabled TLS, add its endpoint:
turn:turn.example.com:3478?transport=udp|turn:turn.example.com:3478?transport=tcp|turns:turn.example.com:5349?transport=tcp
Use turn: and turns: URIs, without //. Only list endpoints your server actually supports.
The voice_turn_secret_servers list uses credentials generated from the shared secret. The separate voice_turn_servers list uses a fixed username and password. Voice setting definitions.
Save the settings, then have participants leave and rejoin calls to obtain the new configuration.
3. Verify the setup
Test with two participants on different networks, such as home broadband and mobile data. Confirm audio works in both directions, then test video and screen sharing.
In Chromium browsers, open chrome://webrtc-internals before joining:
- A
srflxcandidate represents a discovered public address. - A
relaycandidate represents an available TURN relay. - The selected candidate pair shows the connection actually carrying media.
A successful direct call does not prove relaying works. Also test from a network that requires TURN, or use a WebRTC test client with iceTransportPolicy: "relay" and temporary credentials.
Check coturn’s logs for successful authenticated allocations. Requests without valid credentials must not obtain a relay allocation. An initial 401 authentication challenge is normal; repeated authentication failures need investigation.
Keep the server dedicated to your community
The shared secret stays on Discourse and the TURN server. Participants receive temporary credentials instead. Voice currently generates credentials valid for creating allocations for 12 hours; an established allocation can continue while it is refreshed. Voice’s credential generation.
This prevents an anonymous open relay, but TURN credentials are not tied to a browser origin: a participant can copy and reuse their temporary credentials. To limit abuse:
- Restrict Voice access to the intended groups.
- Monitor relay bandwidth and allocation counts.
- Set coturn allocation quotas and bandwidth limits appropriate to your community.
- Block relay access to private, link-local, and other internal destinations reachable from the TURN host.
- Keep coturn updated and rotate the shared secret if it is exposed.
Use a dedicated secret for this Discourse deployment. With no-stun enabled, the server also stops offering anonymous standalone STUN service. Coturn authentication and access controls.
Alternatives
Replace only the public STUN servers
Set voice_stun_servers to your own STUN URIs, separated by |:
stun:stun.example.com:3478
Leave the TURN settings empty if you do not need a relay. STUN alone cannot make calls work on every network. A coturn server configured with no-stun cannot serve this endpoint.
Use TURN with a fixed username and password
If your provider does not support shared-secret authentication, configure voice_turn_servers, voice_turn_username, and voice_turn_credential. Leave the shared-secret settings empty.
Participants receive those fixed credentials, which makes them easier to reuse outside your site. Also, Voice currently forces relay connections when static TURN servers are configured and the STUN list is empty. Prefer shared-secret authentication when your provider supports it. Voice’s ICE configuration.