HowTo: Setup Nextcloud Talk with TURN server

Thanks for your remarks, very informative. As said, I have a hosted NextCloud, so all calls between users are external to the NextCloud’s local network (at my provider). All my clients used so far are Win10. I have now my own TURN server (set up by my provider), which is in a different local network than my NextCloud.

I could meanwhile establish communication with video and sound using Opera, however I had to manully enable the "Use any suitable network interface " option in “Privacy/Security / WebRTC”, which was for some reason (I have no recollection of having changed it) set to “Disable Non-proxied UDP”. With Firefox still no luck, although WebRTC is enabled (I checked in about:config) and the H.264 add-on present and enabled.

Someone any hints for Firefox and other browsers, also Safari on the Mac?

A year ago Microsoft moved from the old P2P architecture of Skype to a cloud based approach. As they always did in the past, old clients (still relying on P2P) were killed off and cannot be used anymore with Skype. Here is more info on that:

https://support.skype.com/en/faq/FA12381/what-does-it-mean-that-skype-is-moving-from-peer-to-peer-to-the-cloud

A TURN server basically does the same, routing everything through the server if the clients cannot connect directly (P2P) because of NAT or firewalls between them.

1 Like

Meanwhile tested and working Opera/Win10 to Chrome/MAC…Firefox - still searching the right tweak…

After all there are several layers of differences between Skype and Nextcloud Talk and possible reasons why Nextcloud Talk indeed needs some manual/additional install steps to work over www like Skype, WhatsApp and comparable other solutions.

Open-source WebRTC
Nextcloud Talk is based on the open-source WebRTC standard. This means basically any system/software can be a client/peer, as long as it fulfills the standards definitions/API, although in the first place it was created for web browsers and is mostly used there, AFAIK. While this provides a great flexibility, as no one is forced to use a special client and one can even build it’s own, on the other hand it means that you have a wide range of different specific implementations. I have no detailed insights here, but I guess it is always an issue that certain browsers handle the connections slightly different (in a degree of details, that might be outside of the standards definitions, wanted or unwanted). Also one cannot just add a feature that is not part of the WebRTC standard, at least not without adding e.g. a second API/protocol outside of the WebRTC connection.

  • Skype and other closed solutions can tune their protocol and client software more tight and “freely” add or remove features etc. In combination with a horde of well payed developers and many years of development, I guess a more “smooth” and complete seeming solution is possible.
    But: The downside is, that you are bound to the clients offered by Skype and that you need to trust those in security questions (How transparent is MS about security wholes within Skype?) and the company/Microsoft about their intentions and use of e.g. collected usage data etc.

Peer-to-Peer
WebRTC is in the first place a Peer-to-Peer standard, which means that no 3rd relay/server is involved in the connection that could listen to what you are talking. This also makes sense for an open standard like this, since API definitions simply cannot provide/assure any 3rd party relay/server being available :laughing:. This brings the limitations in combination in combination with NAT/firewall/www connections, where you then need additional software to solve. TURN server like coturn generally work fine here, but again their are not build for WebRTC only, thus provide a rich set of settings and features to chose, where some might be needed for WebRTC and others not, again some for the specific Nextcloud Talk implementations, others not. So the “maybe most-compatible” default settings of e.g. coturn do not work with Nextcloud Talk.

  • As mentioned by the others (great, since I have no idea how Skype works, just assumed it is no real P2P), Skype has an integrated solution for this and own/MS server are included.

I am sometimes thinking if it would be beneficial to bundle Talk+STUN+TURN, like e.g. Pi-hole integrated dnsmasq into their FTL service, to avoid some manual config file adjustments, automated the secret exchange etc. On the other hand this means always additional effort for maintaining the fork or bundle (depending on how far the integration should go), talking developers capacity from concentrating on the clients. I think a good step by step guide (as hopefully above) should be working for everyone who already managed to setup an own Nextcloud server, right? :smile:

Browsers
Jep, Opera (I guess chromium based browsers in general) need to allow WebRTC connections on “non standard public and/or private” networks, which ever standard is meant here. While Browsers are strongly rated and reviewed in terms of security, thus are forced to add such settings (which is great from my point of view), Skype will never ask, if you trust the network you are currently connected to. Security vs comfort… However I think marking one switch is not too hard :laughing:. Hmm with Firefox it is not that easy?
€: Hmm: https://webrtc.org/web-apis/firefox/

We don’t have TURN support yet, but we plan to support it soon.

But the page seems outdated… Also not sure if this applies in case of Nextcloud Talk.

1 Like

Thanks for this great descriptions, gives good insight.

As regards FF, I think I will just try with a fresh installation. All my FF installations are pretty dated and have undergone tons of udates to reach the recent version. Maybe one of the many media.xxx parameters in the config has not been flipped correctly during this process…

I stopped short of fresh installations and had a look into the about:config, especially to non-standard entries.

One might be obvious: The plugin OpenH264 must be active, it is standard installation and active with recent FF installations, however it could have been fallen prey to experiments with security add-ons that advertise to protect from IP address leakages and which are less bluntly and obviously named as e.g. WebRTC Control.
The about:config media.xxx section might contain an entry media.gmp-gmpopenh254.enabled which should be set to true. Apparently this entry does not exist in installations, where the plug-in had not been deactivated ever, so its absence should be fine.
On top, a deactivation of the H.264 support should give a message that WebRTC is not supported and that you should use other browsers like FF, Chrome…slightly deconcerting, but a clear hint that something is wrong.

The less obvious problem I found with the parameter media.peerconnection.enabled. It should be set to True by default, but for a reason not known to me it was set to false in two of my installations. Enabling it resolved my issue and calls from and to FF now work as well as with Opera and Chrome (the latter I only use for testing, by personal taste, strictly).

I think that after change of above config options a restart of FF or possibly Windows should be done.

Well, my stuff is working so far, will see, how many of my Talk partners will have to make the above or possibly other tweaks.

1 Like

Thanks for sharing the solution.

Maybe I can add a “Known issues and solutions” header above to collect such information?

Can the TURN server settings in the Nextcloud Talk admin settings be scripted somehow? Where does that setting reside? Config file? Database? …?

1 Like

Very good question!

Can’t find the settings in the database, just temporary info about open rooms, guests etc.

I remember the Spreed.ME app indeed stored info in a file somewhere inside the Nextcloud install dir, but can’t find that right now.

Would make sense to store it in <nextcloud_data>/appdata_<ID>/..., if not in database, but can’t find them there either :thinking:.

If someone knows where the settings are stored, please en-light us, as I also need to be able to adjust them via script.

Thanks for the great HowTo!

With this example configuration however, I was not able to use the TURN server for relaying. I believe the following line in the example tunrserver.conf

bps-capacity=0

disables relaying. I am pretty sure it limits the allowed bandwidth to 0.

In an older Spreed HowTo, the author references this line as an example setting to avoid unexpected high traffic, which relaying might cause (see Spreed HowTo here, warning at the end)

If you want Talk to use be able to use the TURN server for relaying, this setting must be commented out,

# bps-capacity=0

or set to a value bigger than 0.

I always though, bps-capacity=0 means the limit is disabled. From the description otherwise I would derive that it cannot do any job at all. Can’t find some hint why this should only apply to TURN servers with relay-ip configured or any other condition.

But I am not too good in digging into the c code to prove my assumption: https://github.com/coturn/coturn/search?q=bps-capacity

But in your case, you are sure that with bps-capacity=0, the TURN server does not work, with this commented, it does? In this case I would open some issue on their GitHub page for clarification, adjustment of Wiki/example config comments, or fix code to handle this according to Wiki/comments.

My first assumption was also that bps-capacity=0 would disable the limit.

Alas, the comment above the bps-capacity line in tunrserver.conf reads

#
# Maximum server capacity.
# Total bytes-per-second bandwidth the TURN server is allowed to allocate
# for the sessions, combined (input and output network streams are treated separately).
#
# bps-capacity=0

so the comment in the .conf-file is arguably clear, if it adheres to my theory.

SInce you’ve linked to the code, I’ve tried to follow it also, but I did not have enough time.

Here’s what I think happens; to be sure I would have to be more thorough:

The .conf file is read in read_config_file in mainrelay.c and calls set_option which sets the internal struct member turn_params.bps_capacity which is used in the allocate_bps function in netengine.c.

Sorry, since I can have only 4 links per post, I had to spit it: Part2:

This function is instrumental: if bps_capacity is not set, it will allow capacity allocation; otherwise it will check if turn_params.bps_capacity_allocated < turn_params.bps_capacity, and if not (which it won’t be with bps_capacity = 0), it will return 0.

Part 3:
A pointer to this function is used in a call to init_turn_server which is defined here where it’s assigned to a function pointer var named allocate_bps_func. This function is used in handle_turn_allocate.
handle_turn_allocate will fail here if allocate_bps_func, i.e. it cannot allocate bandwidth.

1 Like

Thanks for digging into this :+1:. I am too tired to exactly follow it in the code (will try tomorrow), but still wondering, why my TURN server works well then, even that bps-capacity=0 is set :thinking:.

It does not make any sense to allow limit the bandwidth to zero and effectively deactivate functioning of the TURN server. And how to disable the limit completely then? Totally common to use zero values to disable in such cases.

But again, if you can verify that switching between bps-capacity=0 and commenting it, also switches functioning of your TURN server, then we should open an GitHub issue, as this is definitely not how it should be and how everyone expects, even with the explanation in example conf.

Hm. You are right. I re-tested with uncommented bps-capacity, restarted coturn, and still could use the TURN-server.
(My testcase is a make-shift corporate-like firewall - I allow one PC to only access the Internet via a Proxy on tcp port 443, no udp).
I think the error in my short code analysis above might be that this line in the allocate_bps function will not distinguish between bps_capacity not being set, or it being 0. So 0 is probably OK (?).
Now I wonder what else I have changed that made my setup work, when it did not before…
Thanks for your persistence in pushing me to re-test!

1 Like

Guess so. But I am no c coder :wink:.
But seems that disabled limit is default then, so commenting works as well.

1 Like

@j12t
Found the TURN server settings within database:
mysql -uroot -p -e "select * from nextcloud.oc_appconfig where appid='spreed'"
Replace “nextcloud” by your actual database name of course.

Output:

+--------+-------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| appid  | configkey         | configvalue                                                                                                                            |
+--------+-------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| spreed | enabled           | yes                                                                                                                                    |
| spreed | installed_version | 4.0.0                                                                                                                                  |
| spreed | stun_servers      | ["my.domain.org:5349"]                                                                                                              |
| spreed | turn_servers      | [{"server":"my.domain.org:5349","secret":"<my_secret_string>","protocols":"udp,tcp"}] |
| spreed | types             | prevent_group_restriction                                                                                                              |
+--------+-------------------+----------------------------------------------------------------------------------------------------------------------------------------+

So to update settings via script e.g.:

mysql -uroot -p<password> -e "update <nextcloud_db_name>.oc_appconfig set configvalue='[\"your.domain.org:5349\"]' where configkey='stun_servers'"
mysql -uroot -p<password> -e "update <nextcloud_db_name>.oc_appconfig set configvalue='[{\"server\":\"your.domain.org:5349\",\"secret\":\"<your_secret_string>\",\"protocols\":\"udp,tcp\"}]' where configkey='turn_servers'"

But didn’t test syntax in this case with all the quotations :wink:. Testing pending…


EDIT:

To not risk messing with MySQL tables, occ can be also used to apply settings:

sudo -u www-data php /path/to/nextcloud/occ config:app:set spreed stun_servers --value='["my.domain.org:1234"]'
sudo -u www-data php /path/to/nextcloud/occ config:app:set spreed turn_servers --value='[{"server":"my.domain.org:1234","secret":"XXXX","protocols":"udp,tcp"}]'
2 Likes

One idea for this warning message:

Dec 19 09:08:17 srvr turnserver: 0: WARNING: cannot find private key file: /etc/ssl/acme/private/mydomain.net.privkey.pem (1)
Dec 19 09:08:17 srvr turnserver: 0: WARNING: cannot start TLS and DTLS listeners because private key file is not set properly

Cert generated by Letsencrypt on OpenBSD 6.4!
Right on private key is 0400, only for root and group wheel.

The turnserver start with _turnserver user.

how can i resolve _turnserver user read this file?

Ah okay on Raspbian/Debian certbot APT install, it runs as root user, to allow bind to restricted ports as well.

Somehow makes sense to run it as separate user on a permitted port.

There are two ways to grant access to private key files:

  • Copy the key + certs somewhere to a turnserver related dir and chown _turnserver:_turnserver && chmod 400. But this then needs to be done on every certificate renewal, e.g. via cron job or by adding these steps to the renewal job.
  • Create an “ssl” group, add _turnserver to this group and chown the key to this group with 440 permissions then. Then you can add any other user that requires cert+key access for TLS to this group. But this as well most likely needs to be redone on certificate renewal, depending on how (with which user) the renewal is done. Perhaps you can run the related renewal process/service with “ssl” group as well to have this done automatically.
1 Like