Coturn Operator Guide

To make voice and video calls through urbit we use a protocol called WebRTC which allows ships to connect directly to each other. Most times one or both ships are behind NATs and firewalls and often they are unable to connect. To get around this, instead of connecting directly to each other the ships can all connect to a TURN server (Transversal Using Relays around NATs) which will relay all the data between all the participants. Since this is relaying a bunch of data there are no free TURN servers on the internet. Thus a nice service that a star can provide is to run a TURN server and allow it's sponsored planets to use it. This guide will show you how to set one up.

The server you want to run is called coturn.

coturn requires a server to run on, a domain, and a certificate. It can run on the same machine as your star or a separate machine.

Getting a server, domain, and certificate

If you need a server or domain follow the Cloud Hosting guide until the section 'Installing Urbit.' Stop there since you don't need to install urbit on the coturn machine. Follow this guide to install certbot and use it to aquire a certificate.

Note the instructions below assume an Ubuntu server. If your server runs a different distribution, you may need to substitute apt-get and ufw with your distro's package manager and firewall.

Installing docker

We will install docker and run the coturn docker container with our own certificate and configuration file.

Install Docker with these commands taken from this guide:

$ sudo apt-get update
$ sudo apt-get install \
ca-certificates \
curl \
gnupg \
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli docker-compose-plugin

Verify that Docker is installed correctly with this command:

$ sudo docker run hello-world

Configure firewall to open up coturn ports

Coturn requires ports 3478 and 5349 to talk to it plus ports 49152-65535 to relay data. (I know this is a ton of ports but it IS a relay server).

$ sudo ufw allow 3478
$ sudo ufw allow 5349
$ sudo ufw allow 49152:65535/udp

Turn on the firewall:

$ sudo ufw enable
  • Check the status
$ sudo ufw status

Install coturn

  • First create a directory for it
$ mkdir ~/coturn
  • Copy your cert into the directory so coturn can use it.
$ mkdir ~/coturn/certs
$ sudo cp /etc/letsencrypt/live/<YOUR-DOMAIN>/cert.pem /etc/letsencrypt/live/<YOUR-DOMAIN>/privkey.pem ~/coturn/certs
  • Generate a secret which will be shared by both coturn and the uturn gall agent.
$ sudo apt install pwgen
$ pwgen -s 64 1

The output of the pwgen command is your secret. Anyone with it can access your coturn server so keep it safe.

  • Create a config file
$ touch ~/coturn/coturn.conf
$ nano ~/coturn/coturn.conf
  • Copy these contents into your coturn.conf
# STUN server port is 3478 for UDP and TCP, and 5349 for TLS.
# Allow connection on the UDP port 3478
# and 5349 for TLS (secure)
# Require authentication
static-auth-secret=<YOUR SECRET YOU GENERATED>
server-name=<YOUR DOMAIN>
# Path to the SSL certificate and private key.
# Specify the allowed OpenSSL cipher list for TLS/DTLS connections
  • Make sure to put the secret you generated into the static-auth-secret line.

  • Make sure the paths to your certificate are correct.

  • Make sure to set realm and domain to your domain (ie

  • Run coturn

$ sudo docker run -d --network=host \
-v ~/coturn:/coturn \
instrumentisto/coturn -c /coturn/turnserver.conf

Test that coturn is working

First you need to generate credentials for it using this python program. The credentials are created with a username, which can be anything, a TTL, which is how long they last, and the secret you put in the config file earlier.

$ touch
$ nano
  • Copy this into and replace SECRET with your secret. The user doesn't matter at all (it's only used to match connections with users in the logs) so just leave it as user1.
import hashlib
import hmac
import base64
from time import time
user = 'user1'
secret = b'SECRET'
ttl = 24 * 3600 # Time to live
timestamp = int(time()) + ttl
username = str(timestamp) + ':' + user
dig =, bytes(username, 'latin-1'), hashlib.sha1).digest()
password = base64.b64encode(dig).decode()
print('username: %s' % username)
print('password: %s' % password)
  • Now run it to generate credentials
$ python

This will spit out a username and password.

Configure uturn

  • Now you should go to your ship (either your star or a moon) and poke uturn with the URL and secret of your turn server. Make sure to begin the URL with 'turn:' and put in your secret.
> :uturn &set-server-config [%server url='' secret='mysecret']