--- title: "Configure Rocket.Chat Voice via Standard WebRTC" slug: "configure-voice-via-standard-webrtc" description: "Enable and configure Rocket.Chat Voice using Standard WebRTC for secure voice calls" tags: ["Premium"] status: "update" updated: 2026-11-06T17:06:25Z published: 2026-11-06T17:06:25Z canonical: "docs.rocket.chat/configure-voice-via-standard-webrtc" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.rocket.chat/llms.txt > Use this file to discover all available pages before exploring further. # Configure Rocket.Chat Voice via Standard WebRTC ![](https://cdn.us.document360.io/6ae79a05-7252-45d0-96e8-8f375e07b1b2/Images/Documentation/Premium(1).svg) The standard WebRTC configuration offers the simplest way to enable voice calls directly within your Rocket.Chat workspace. It uses the built-in WebRTC capabilities of modern browsers, allowing users to make and receive voice calls without needing external telephony or SIP infrastructure. It’s ideal for teams that want a quick and easy voice call solution for internal communication. This guide explains how to enable and configure Rocket.Chat Voice for intra-workspace calls using the standard WebRTC configuration. ## How Rocket.Chat Voice Works with WebRTC Rocket.Chat Voice uses WebRTC to establish a secure, direct, peer-to-peer media link between the calling and receiving users’ browsers. Once this connection is established, it enables the direct exchange of audio data between users. The Rocket.Chat server acts as a signaling server, managing the call setup process. It coordinates the call request, notifies the recipient, and facilitates the exchange of WebRTC parameters (such as ICE candidates) for connection negotiation. After signaling is complete, the two user clients establish a direct peer-to-peer WebRTC connection, allowing them to exchange audio without the Rocket.Chat server ever handling or relaying the media stream. ### Overcoming network challenges (NAT traversal) One of the main technical challenges in peer-to-peer communication is Network Address Translation (NAT), since users are often located behind firewalls or private networks. NAT can prevent browsers from discovering each other’s real network addresses, making direct communication difficult. To ensure a reliable connection, Rocket.Chat strongly recommends servers for ICE (Interactive Connectivity Establishment) to negotiate a network path. ICE includes two key servers: 1. **STUN (Session Traversal Utilities for NAT):** Helps a client discover its own public IP address and port when behind a NAT, allowing it to attempt a direct, low-latency connection to another peer. 2. **TURN (Traversal Using Relays around NAT):** When a direct P2P connection is impossible (e.g., due to restrictive firewalls), the TURN server acts as an **audio relay**, routing the entire media stream to guarantee the call connects. > [!NOTE] > By default, STUN is enabled using the public service provided by Google. For better control and reliability, configure your own STUN servers in **ICE servers** and your TURN servers in **TURN servers**, as described in [Configure WebRTC settings](/docs/configure-voice-via-standard-webrtc#configure-webrtc-settings). ## Prerequisites Before you begin, confirm you have the following: - An active [premium plan](/v1/docs/our-plans). - The **Rocket.Chat Voice add-on** If you don’t have these, contact the [Sales Team](https://www.rocket.chat/sales-contact). ## Configure WebRTC settings Once the prerequisites are met, the next step is to configure the WebRTC network settings in your workspace. 1. In your Rocket.Chat workspace, navigate to **Manage → Workspace** → **Settings** → **Team voice calls (VoIP)**. 2. Go to **WebRTC settings** and update the following fields: | Field | Description | | --- | --- | | **Screen sharing** | Enable users to share their screen during voice calls for improved collaboration. Visit the [Screen sharing guide](/v1/docs/team-voice-calls-user-guide#screen-sharing) for more details. | | **Mobile ringing** ![](https://cdn.us.document360.io/6ae79a05-7252-45d0-96e8-8f375e07b1b2/Images/Documentation/Beta.svg) | Allow users to make and receive voice calls using the mobile app. Visit the [Configure voice calls on mobile guide](/v1/docs/team-voice-calls-user-guide#configure-voice-calls-on-mobile) for more details. | | **ICE servers** | Enter a comma-separated list of STUN and/or TURN servers used to gather network address candidates for Voice calls. Only one working address is needed for a call, but all configured servers are contacted before the call starts. - **Format**: `[username:password@]stun:host:port` or `[username:password@]turn:host:port` - Usernames and passwords may be HTML-encoded. By default, STUN is enabled using the public service provided by Google. This setting is readable by anyone who can reach your workspace. Enter TURN servers that need credentials in **TURN servers** instead. See [Configure private TURN servers](/docs/configure-voice-via-standard-webrtc#configure-private-turn-servers). | | **ICE gathering timeout** | Specify how long (in milliseconds) the system should wait for ICE candidate gathering to complete before starting a call. A longer timeout ensures TURN servers have time to respond, but may delay call setup. For local or STUN-only setups, a shorter timeout may reduce call startup delays. | | **TURN servers** | Enter a JSON list of TURN servers and their credentials. The field is empty by default. Unlike **ICE servers**, this setting isn't public. See [Configure private TURN servers](/docs/configure-voice-via-standard-webrtc#configure-private-turn-servers) for the format. | 3. Click **Save changes**. After saving the configuration, your workspace is now ready to handle voice calls using the standard WebRTC engine. ## Configure private TURN servers Use the **TURN servers** setting in **WebRTC settings** to keep TURN servers and their credentials out of public settings. The setting appears directly after **ICE gathering timeout**. The workspace sends the servers in **TURN servers**, with the credentials for that user, only to the users on a call, when the call starts. Users who aren't on a call never receive them. During a call, clients use the servers in **ICE servers** first, followed by the servers in **TURN servers**. Workspace admins see the stored usernames, credentials, and secrets in plain text, both in the field and through the REST API. Users with the default **user** role and people who aren't signed in can't read the setting. When the setting changes, the settings audit log records the change with the value masked. > [!WARNING] > Anyone who can reach your workspace can read **ICE servers**, including people who aren't signed in. **ICE servers** accepts TURN entries with a username and password without any warning, and those credentials become readable too. Keep only STUN servers there, and move every TURN server with a username and password to **TURN servers**. ### TURN servers format Enter a JSON list. Each entry has a `urls` field and an optional `auth` field: - `urls`: required. One `stun:`, `stuns:`, `turn:`, or `turns:` address, or a list of addresses. - `auth`: optional. The credentials for the server. Each entry uses one type only. The following table describes each type. | `auth` value | Description | | --- | --- | | No `auth` | The server address with no credentials. | | `{ "type": "static", "username": "...", "credential": "..." }` | Fixed credentials. Enter the `username` and `credential` your TURN server expects. An entry without `credential` isn't saved. Every user on a call receives the same long-lived credentials and can reuse them until you change them on the TURN server. If your TURN server supports it, use `shared-secret` instead. | | `{ "type": "shared-secret", "secret": "...", "ttl": 3600 }` | Credentials issued for each user from `secret`, which must match the secret on your TURN server. `secret` is required and is never sent to users. `ttl` is optional and sets, as a number of seconds, how long the issued credentials stay valid. The default is 86400 seconds (24 hours) and the minimum is 60 seconds. See [Choose a credential lifetime](/docs/configure-voice-via-standard-webrtc#choose-a-credential-lifetime). | The following example adds one server with fixed credentials and one server that uses a shared secret: ```json [  { "urls": "turn:legacy.example.com:3478", "auth": { "type": "static", "username": "rocketchat", "credential": "your-turn-password" } },  {    "urls": ["turn:turn.example.com:3478", "turns:turn.example.com:443?transport=tcp"],    "auth": { "type": "shared-secret", "secret": "your-shared-secret", "ttl": 3600 }  } ] ``` The workspace checks the value before saving it: - If the field doesn't contain valid JSON, **Invalid JSON** appears under the field and **Save changes** is unavailable. - If the JSON is valid but doesn't match this format, clicking **Save changes** shows an error message and the setting keeps its previous value. For example, a single object instead of a list, a `shared-secret` entry without `secret`, a `ttl` lower than 60, or a `static` entry that also has `secret` isn't saved. - If an invalid value reaches the workspace another way, for example through an environment variable, the workspace ignores it, logs an error, and sends no servers from **TURN servers** to users. ### Use time-limited credentials with a shared secret To use a shared secret, your TURN server must support shared-secret authentication, also known as the TURN REST API. For example, coturn supports it with the `use-auth-secret` option. The secret in **TURN servers** must match `static-auth-secret` on the TURN server. For each user on a call, the workspace issues a username in the format `<expiry timestamp>:<user ID>` and a password calculated from that username and the secret (HMAC-SHA1, Base64-encoded). The TURN server checks these credentials on its own, without contacting Rocket.Chat, and rejects them after they expire. Because the secret is a workspace setting, every Rocket.Chat instance in a multi-instance deployment issues credentials the TURN server accepts. 1. On your TURN server, turn on shared-secret authentication and set `static-auth-secret` to your secret. See [Example coturn configuration](/docs/configure-voice-via-standard-webrtc#example-coturn-configuration). 2. In **TURN servers**, add an entry for the server with `"auth": { "type": "shared-secret", "secret": "<your secret>" }`. Use the same secret as on the TURN server. 3. In **ICE servers**, remove every entry in the `username:password@turn:host:port` format, so that only STUN servers remain. 4. Click **Save changes**. After you save, the public **ICE servers** setting holds only STUN servers, and the TURN server and its secret are stored only in **TURN servers**. ### Example coturn configuration The following coturn configuration uses a shared secret, listens for TURN over TLS on port 443, and blocks relaying to private and loopback addresses so the TURN server can't be used to reach your internal network: ```ini listening-port=3478 tls-listening-port=443 cert=/etc/coturn/fullchain.pem pkey=/etc/coturn/privkey.pem realm=turn.example.com use-auth-secret static-auth-secret= fingerprint no-cli no-multicast-peers # Never relay into private or loopback ranges denied-peer-ip=0.0.0.0-0.255.255.255 denied-peer-ip=10.0.0.0-10.255.255.255 denied-peer-ip=100.64.0.0-100.127.255.255 denied-peer-ip=127.0.0.0-127.255.255.255 denied-peer-ip=169.254.0.0-169.254.255.255 denied-peer-ip=172.16.0.0-172.31.255.255 denied-peer-ip=192.168.0.0-192.168.255.255 denied-peer-ip=::1 denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff # Limit what a single credential can consume user-quota=12 total-quota=1200 ``` - TURN over TLS on port 443 (`turns:` addresses) can get through restrictive networks that allow outbound TLS on port 443. Proxies that inspect HTTPS traffic still block it. - If your media servers are on a private network that the TURN server must reach, add an `allowed-peer-ip` line for exactly those addresses instead of removing the denied ranges. ### Choose a credential lifetime The `ttl` value controls how long the credentials issued from a shared secret stay valid. Consider the following when you choose it: - The workspace issues credentials when a call starts, and again when a user's app reconnects and resyncs the call. A connection that already exists keeps the credentials it started with. - A relay that's already in use keeps working after its credentials expire. However, if a user's network changes after the credentials expire, for example when they switch from Wi-Fi to mobile data, the call can't reconnect. Set `ttl` longer than your longest expected call. - A deactivated user's credentials stay valid until they expire. A shorter lifetime makes this window smaller. - The workspace and the TURN server compare an absolute timestamp, so keep both clocks in sync, for example with NTP. This matters most with short lifetimes. The default is 86400 seconds (24 hours). For a more secure setup, use a lifetime between one and a few hours, for example 3600 to 14400 seconds. ### Verify the TURN configuration After you configure a shared secret, start a call and check the following: - In the browser's developer tools, the WebSocket message that starts the call includes `iceServers` with a username in the `<timestamp>:<user ID>` format. The shared secret never appears. - With coturn, running `turnutils_uclient -u '<username>' -w '<credential>' turn.example.com` with the credentials from that message succeeds. After the timestamp passes, coturn responds with `401 Unauthorized`. - With the browser limited to relayed connections, `chrome://webrtc-internals` shows a selected candidate pair of type `relay`. ## Next steps After configuring WebRTC, [Set up Rocket.Chat Voice Permissions](/v1/docs/set-up-voice-permissions) to define which users can access calling features. Once permissions are set, end users can follow the [Rocket.Chat Voice User Guide](/v1/docs/team-voice-calls-user-guide) to start making calls.