We recently had an support inquiry from one of our Nextcloud customers at Netways Web Services. He told us that he had installed the Nextcloud Video Calls app from the Nextcloud Appstore but was not able to make any video calls. He and the person on the other end always got a black video screen when attempting to call each other.
After some research I identified the potential cause of the problem. It turned out that a TURN server was required (pardon the pun).
TURN – what is that?
The Nextcloud Video Calls app contains a WebRTC-based server called spreed. WebRTC uses the ICE (Interactive Connectivity Establishment) framework to overcome networking complexities (like NATs) where connecting the participating clients directly isn’t possible. But it will need at least a STUN server to accomplish that. STUN standing for „Session Traversal Utilities for NAT“ will enable the clients to discover their public IP addresses and the NAT where they are behind. Note that this server is only used to initially establish the connection. Once the connection is set up the media will stream directly between the clients. The Nextcloud Video Calls app is preconfigured with „stun.nextcloud.com:443“ as STUN server. But this doesn’t always work – just like our customer experienced it, for some clients a STUN server won’t be enough to establish the connection. That might be the case if one or multiple participants are behind a symmetric NAT where UDP hole punching does not work. And that’s where the TURN server comes in. „Traversal Using Relay NAT“ (TURN) extends STUN capabilities to make media traversal possible even if the clients are behind symmetric NATs. But that means that the whole traffic will flow through the TURN server since it is acting as a relay. Therefore most TURN servers use credential or shared secret mechanisms to authenticate the clients. So after all you end up having two options: either you find a TURN server provider that you can trust and who is willing to grant you access to his service or you set up your own TURN server.
How to set up a TURN Server
We decided to set up our own TURN. Like most of the tutorials recommend we installed Coturn. Our „TURN-VM“ is running Ubuntu 16.04 and has a public IP address – this is actually quite important since the TURN server needs at least one dedicated public IP address to work properly. In order to have full STUN/TURN server functionality it’s even required to have two public IP addresses.
Now let’s start – first install coturn:
apt-get install coturn
Next enable coturn as service (use the editor of your choice):
Now uncomment the last line, save and close the file:
# # Uncomment it if you want to have the turnserver running as # an automatic system service daemon # TURNSERVER_ENABLED=1
We will have a look at the config file of Coturn. It has a lot of lines so I will only go over settings that are relevant in conjunction with Nextcloud’s spreed video calls. Open the turnserver.conf with an editor
and have a look at the following lines
Those are the default listening ports coturn will use. In my case I changed them to
because I don’t have a webserver running on the VM and I already had the ports open in the firewall. This is important – make sure that the server is reachable on these ports and no firewall is blocking them.
Note that the tls-listening-port is only relevant if you plan on using TLS-encrypted connections.
You’ll find the following line a couple of lines below the tls-listening-port:
If you leave it as a comment then Coturn will listen on all the IP addresses available for this host. I uncommented it and changed it to the actual public IP address of this server
Further down I did the same for the relay-ip:
Now look for „fingerprint“ and „lt-cred-mech“ and uncomment:
A couple of lines below you’ll find
uncomment both, then open up another shell window and generate a secret for example with
openssl rand -hex 32 751c45cae60a2839711a94c8d6bf0089e78b2149ca602fdXXXXXXXXXXXXXXXXX
copy the generated secret string and paste it into the turnserver.conf
Enabling „use-auth-secret“ and setting a „static-auth-secret“ will prevent unauthorized usage of your TURN server and is highly recommended!
Head further down and look for
then uncomment and change it to the FQDN of the TURN server
The next line to uncomment and change is
If you want to use TLS then you should get a SSL certificate and key for example via Letsencrypt and then set the following lines of the turnserver.conf to the path where those files are located, in my case:
also set cipher-list to
If you don’t plan on using this TURN server as STUN then you can uncomment
Now some last uncommenting
and you should be ready to start your coturn server. Save the file and close the editor.
Start/restart coturn for example with
service coturn restart
You may want to watch the logfile to see if everthing is fine
tail -f /var/log/turn_YYYY-MM-DD.log
0: log file opened: /var/log/turn_2017-08-15.log 0: pid file created: /var/run/turnserver.pid 0: IO method (main listener thread): epoll (with changelist) 0: WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided 0: Wait for relay ports initialization... 0: relay 185.XX.XXX.XXX initialization... 0: relay 185.XX.XXX.XXX initialization done 0: Relay ports initialization done 0: IO method (general relay thread): epoll (with changelist) 0: IO method (general relay thread): epoll (with changelist) 0: turn server id=0 created 0: turn server id=2 created 0: IPv4. TLS/SCTP listener opened on : 185.XX.XXX.XXX:80 0: IPv4. TLS/TCP listener opened on : 185.XX.XXX.XXX:80 0: IO method (general relay thread): epoll (with changelist) 0: IPv4. TLS/SCTP listener opened on : 185.XX.XXX.XXX:443 0: IPv4. TLS/TCP listener opened on : 185.XX.XXX.XXX:443 .. .
So now we are ready to test if it is working.
How to test my TURN Server
Visit this page and see if you can get a proper response from your Coturn server.
The field for „STUN or TURN URI“ should look something like this:
but you can also use the IP:
adding the part „?transport=tcp“ is important as I was not able to get my TURN server to respond without TCP only.
Next click on „Gather candidates“.
What you would want as a result should look similar to this:
Time Component Type Foundation Protocol Address Port Priority 0.006 1 host 0 UDP 10.0.10.144 60925 126 | 32512 | 255 0.009 1 host 1 TCP 10.0.10.144 63376 125 | 32640 | 255 0.010 1 host 1 TCP 10.0.10.144 9 125 | 32704 | 255 0.015 2 host 0 UDP 10.0.10.144 47302 126 | 32512 | 254 0.016 2 host 1 TCP 10.0.10.144 64892 125 | 32640 | 254 0.016 2 host 1 TCP 10.0.10.144 9 125 | 32704 | 254 0.031 1 srflx 2 TCP XXX.XX.XX.XX 3362 99 | 32607 | 255 0.051 2 srflx 2 TCP XXX.XX.XX.XX 3364 99 | 32607 | 254 0.069 Done
If you get a timeout with „Not reachable?“ then probably a firewall is blocking the connection. Check again if the ports for the TURN server are open and if you can reach it externally via Telnet or something similar.
If everything works as expected you can continue and enter FQDN, port and shared secret in the video calls settings of your Nextcloud:
Also make sure that „TURN server protocols“ is set to „TCP only“.
Finally test if video calls work with participants from different networks, through NAT’s and firewalls.
Well, that’s at least how I got it working and our NWS Nextcloud customer confirmed that he was able to make video calls without black screens as soon as he added in the TURN server details that I sent him.
Feel free to check out our Software as a Service platform NWS where you can test Nextcloud 30 days for free.