For organizations with specific regulatory, scaling, or network control requirements, self-hosted STUN/TURN servers can be a more suitable option than relying on managed service providers to set up and maintain your WebRTC connections. Those seeking cost optimization or increased customization may also benefit from exploring self-hosted solutions.

In this post, we’ll outline best practices for provisioning self-hosted STUN/TURN servers, as recommended by our WebRTC experts. We’ll also explore how to install, run and configure three popular self-hosted implementations that offer both flexibility and control: Coturn, Rel, and STUNner.

This article builds upon a recent post—Mastering STUN & TURN Servers: A Guide to Proper Integration for WebRTC Applications, which you may want to review before diving in here. 

Still interested in a managed service? Check out Selecting and Deploying Managed STUN/TURN Servers.

Ready to begin? Let’s get started.

Overview of Self-Hosted STUN/TURN Integration

Self-hosted STUN/TURN servers work similar to managed servers. The main difference is that it is your job to provision and maintain them, giving you full control—and responsibility—over them. 

As with managed servers, you’ll still need a backend service to handle authentication for WebRTC clients and provide them with ephemeral credentials to interact with STUN/TURN servers.

Self-Hosted STUN/TURN WebRTC Architecture
  1. WebRTC clients request the backend service a set of ephemeral credentials for the STUN/TURN infrastructure.
  2. WebRTC clients use ephemeral credentials to set ICE configuration while establishing WebRTC connection.
  3. WebRTC clients establish connection to the media server infrastructure, if any, or directly to other clients in Mesh architectures.

Regardless of the tools you use to deploy your servers, you can use the Trickle ICE demo page to test their functionality. There you can add your servers’ IP addresses and authentication details to ensure if they generate ICE candidates correctly. This is the first step on debugging connection issues when using self-hosted ICE servers.

Once you have a set of functioning ICE servers, you can make your clients start using them following the same approach as described in our post for managed servers. For now, let’s review the available options for deploying such servers.

Coturn TURN Server

Let’s start with ol’ reliable Coturn, which is right now the more popular option for deploying STUN/TURN servers.

Installing/Running

Getting started with Coturn is as easy as installing it through Linux distribution’s repository (if available) or as a Docker container. For the latter, keep in mind that it requires binding a large set of ports in order to work, so using network=host mode is recommended. 

# installing coturn on Ubuntu or other Debian-based distros
apt install coturn

# installing on Fedora
dnf install coturn

# running using docker
docker run -d -p 3478:3478 -p 3478:3478/udp -p 5349:5349 
-p 5349:5349/udp -p 49152-65535:49152-65535/udp coturn/coturn

# or using network=host
docker run -d --network=host coturn/coturn

Configuring

You can configure the server through a configuration file, or passing parameters to the turnserver binary. To make things simple, it is better to do so using the file, which is usually located at /etc/turnserver.

Configuration will depend on your specific requirements, and its Github repository features a well documented example that you can use as a reference. However, here are a couple of things you’d want to consider in any case:

  • If you’re deploying on EC2 or similar, be sure to set the public IP address associated with the instance to the external-ip option.
# /etc/turnserver
... # more options go here

external-ip=60.70.80.91 # your public IP address
  • Be sure to enable the use-auth-secret flag, and set a secret value either through the static-auth-secret option or in a turn_secret table if integrating with a database. This enables using ephemeral credentials, which is a more secure way to authenticate requests than setting static usernames and passwords.
# /etc/turnserver
... # more options go here

use-auth-secret
static-auth-secret=north # or use a turn_server table in a db for setting it dynamically
  • Set up a server side service that generates ephemeral credentials for your clients, using the secret value as shown below:
## create username and password for coturn
# usercombo -> "timestamp:userid"
# turn user -> usercombo
# turn password -> base64(hmac(secret key, usercombo))

import hmac
import hashlib
import base64
import time
import random
import string
import os

def generate_turn_credentials(secret):
    # Generate a random username
    timestamp = int(time.time()) + 86400  # Valid for 24 hours
    username = f"{timestamp}:{''.join(random.choices(string.ascii_letters + string.digits, k=8))}"

    # Generate the HMAC-SHA1 password
    password = base64.b64encode(hmac.new(secret.encode(), username.encode(), hashlib.sha1).digest()).decode()

    return username, password

# Example usage
shared_secret = os.getenv('YOUR_SECRET_KEY')
username, password = generate_turn_credentials(shared_secret)
print(f"Username: {username}")
print(f"Password: {password}")

Rel

Rel is an alternative to Coturn written in Elixir, although it is still in the early phase of development and lacks many of the features of the former. That being said, it’s a great option when you only need pure STUN & TURN functionality and nothing else. They even have a publicly available TURN server to be used for testing purposes at no cost.

Installing/Running

The easiest way to install Rel is using Docker. Keep in mind that to do so you need to set network mode to host. You can also compile from source.

# running using docker
docker run --network=host ghcr.io/elixir-webrtc/rel:latest

# compiling from source
git clone https://github.com/elixir-webrtc/rel.git
cd rel
mix deps.get
mix run --no-halt

Configuring

You configure Rel using environment variables. Similar to Coturn, its Github repository features a well documented sample env file that you can use as an example to tweak it to your requirements.

It comes with a bundled authentication provider service that generates temporary credentials by default with just a POST request.

curl -X POST "http://1.2.3.4:4000?service=turn&username=hector"
{"password":"8NPSx4KrIAol36vmhXq36zystbc=","ttl":1728,
"uris":["turn:1.2.3.4:3478?transport=udp"],"username":"1736893111:hector"}

STUNner

Unlike the options described so far, STUNner is a STUN/TURN server built specifically to run on Kubernetes clusters. It acts as a gateway that allows WebRTC services to take advantage of the resiliency, scalability and high availability nature of such environments, which up to now has been a big challenge when using any of the above mentioned.

Installing/Running

As of writing this post, you need Kubernetes 1.22 or higher, with kubectl configured, to install STUNner. The easiest way to do so is through Helm as shown below:

# Register the STUNner repository with Helm
helm repo add stunner https://l7mp.io/stunner
helm repo update

# Install the STUNner control plane in its own namespace
helm install stunner-gateway-operator stunner/stunner-gateway-operator \
 --create-namespace \
 --namespace=stunner-system

Configuring

You configure STUNner in the same way as you do with other K8s resources: through YAML manifests. Available options are explained in their documentation.

One thing you need to be mindful of when running STUNner in production environments is to set authentication mode to ephemeral, as this will allow you to generate temporary credentials that clients can use to authenticate ICE requests.

The first thing you need to do to enable such mode is to add an authRef value to your GatewayConfig that references a Secret resource.

apiVersion: stunner.l7mp.io/v1
kind: GatewayConfig
metadata:
  name: stunner-gatewayconfig
  namespace: stunner
spec:
  realm: stunner.l7mp.io
  authRef:
    name: stunner-auth-secret
    namespace: stunner

Next, you set the ephemeral type and assign a secret key to such a Secret resource.

apiVersion: v1
kind: Secret
metadata:
  name: stunner-auth-secret
  namespace: stunner
type: Opaque
stringData:
  type: ephemeral
  secret: my-shared-secret

Choosing the Right Self-Hosted STUN/TURN Server: A Summary and Final Thoughts

In this post, we’ve explored the approach for running self-hosted STUN/TURN servers and examined some popular implementations that offer flexibility and control. From Coturn to STUNner, each server has its unique features and strengths.

Want to take your WebRTC-based application to the next level with a scalable and reliable STUN/TURN server infrastructure? Our team at WebRTC.ventures is here to help! We’ll work closely with you to set up a custom solution that meets your specific needs and requirements. Contact us today about your next project. Let’s Make it Live!

Recent Blog Posts