How to run Nextcloud Talk High Performance Backend with Stun/Turnserver on Ubuntu with docker-compose

Since Nextcloud has released the High Performance Backend as OpenSource under AGPL License, i tried my luck to install it on Ubuntu without docker, but many people had problems or run other OS as Ubuntu/Debian and asked „what about docker?“. Ok, without is a little bit tricky, so let us go with docker:


– a VPS with docker and docker-compose (Tested on Ubuntu 18.04 and 20.04 LTS) (you can get one here @netcup with 5€ Discount or start at Hetzner Cloud with 20€ start credits)
– shell access and appropriate rights
– One DNS A and possibly AAAA record for our nginx vhost and stun/turn-server (I use for all three services in this guide)
– Optional – a second DNS A and possibly AAAA record for stun/turnserver

Hardware Requirements:

32 GB Disk-Space

See also: Nextcloud Portal

You can also test a smaller server if you don’t have that many users

Step 1: Install Firewall and other packages

First of all, you should install a firewall to secure your VPS (if not installed) and allow incoming traffic to port 80/443, 22 (ssh) and for coturn on port 3478tcp/udp only. For Securing ssh-access you can use fail2ban and passwordless authentication. Many guides for this are out there.

apt install ufw -y
ufw allow http
ufw allow https
ufw allow ssh
ufw allow 3478/tcp
ufw allow 3478/udp
ufw enable

Accept with „y“

Step 2: Install git, docker and docker-compose

Install docker:

curl -sSL | CHANNEL=stable sh
systemctl enable docker.service
systemctl start docker.service

and now docker-compose and git with:

sudo apt install -y docker-compose git

Step 3: Clone git-Repository and build Images

we clone the git-Repository to /opt

cd /opt/
git clone && cd nextcloud-spreed-signaling

create a random hex key (STATIC_SECRET) for your nextcloud talk app and signaling server with:

openssl rand -hex 32

and a hashkey:

openssl rand -base64 16

a blockkey:

openssl rand -base64 16

a Nextcloud SHARED_SECRET for Signaling:

openssl rand -hex 16


openssl rand -base64 16

and copy all for later use, then edit docker-compose.yml

nano docker-compose.yml

adjust the following entries REALM and STATIC_SECRET:

version: '3'

    build: .
      - ./server.conf:/config/server.conf
    network_mode: host
    restart: unless-stopped
      - nats
      - janus
      - coturn
    image: nats:2.1
      - ./gnatsd.conf:/config/gnatsd.conf
    command: ["-c", "/config/gnatsd.conf"]
    network_mode: host
    restart: unless-stopped
    build: docker/janus
    command: ["janus", "--full-trickle"]
    network_mode: host
    restart: unless-stopped
    build: docker/coturn
    network_mode: host
      STATIC_SECRET: openssl rand -hex 32
    restart: unless-stopped

then generate server.conf:

nano server.conf

and copy and paste the following (please adjust your backends and secrets):

listen =
debug = false

hashkey = openssl rand -base64 16
blockkey = openssl rand -base64 16

backends = backend-1 #here you can add more backends commaseparated backend-1, backend-2, backend-3
allowall = false
timeout = 10
connectionsperhost = 8

url =
secret = openssl rand -hex 16

#url =
#secret = openssl rand -hex 16

#url =
#secret = openssl rand -hex 16

url = nats://localhost:4222

type = janus
url = ws://localhost:8188

apikey = openssl rand -base64 16
secret = openssl rand -hex 32
servers = turn:localhost:3478?transport=udp,turn:localhost:3478?transport=tcp

save file and change rights to 644:

chmod 644 server.conf

and then build the images:

docker-compose build

you have to wait a little bit before you can continue.

then bring the complete stack up with:

docker-compose up -d

now you should have at least 4 containers running:

docker ps

then go to next step.

Step 4: Install nginx and create vHost for signaling server

Now we will install nginx as reverse proxy for our high performance backend:

apt install nginx python3-certbot-nginx -y

and create the vHost:

nano /etc/nginx/sites-available/signaling

copy, paste and adjust:

server {
    listen 80;

and activate vhost:

ln -s /etc/nginx/sites-available/signaling /etc/nginx/sites-enabled/signaling

then check with:

nginx -t

and reload

systemctl reload nginx

now use certbot to obtain a certificate:

certbot --authenticator standalone --installer nginx -d --pre-hook "service nginx stop" --post-hook "service nginx start"

then paste the following config in the vHost-conf:

mv /etc/nginx/sites-available/signaling /tmp/signaling.bak && nano /etc/nginx/sites-available/signaling
upstream signaling {

server {

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

location /standalone-signaling/ {
        proxy_pass http://signaling/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location /standalone-signaling/spreed {
        proxy_pass http://signaling/spreed;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

server {
    if ($host = {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    return 404; # managed by Certbot


and check an reload nginx:

nginx -t

if ok

systemctl reload nginx

Step 5: Configure nextcloud to use stun/turn and signaling server

Now we are ready to add turn/stun- and signaling-server to our Nextcloud

Go to Settings, Talk and enter the following:

And then enjoy your High Performance Backend.

Problems with the tutorial? Then comment below or contact me per Mail or Mastodon.

I will be happy if you would support my work here.

Happy nextclouding and do not forget to share ?

If you want to try an easier solution look at this deeztek @ github

Picture from Alexandra_Koch on Pixabay
Struktur AG
Tested on netcup
Tested on Hetzner Cloud

21 Gedanken zu „How to run Nextcloud Talk High Performance Backend with Stun/Turnserver on Ubuntu with docker-compose

  1. Danke Markus! Das Hilft 🙂 Ich habe es mit einem kleinen Dev VM bei Scaleway getestet (2GB RAM, 20GB SSD (DEV1-S) mit 300Mbps Anbindung.

    Thank you, Markus. That’s helpful. I successfully tested this on a DEV1-S instance at Scaleway (2GB RAM, 20GB SSD, 300Mbps connection).

  2. Hallo,

    ich bekomme in meiner Nextcloud angezeigt, dass der Turn Server keine funktionierenden ICE-Kandidaten zurücksendet.

    Wo hab ich da eventuell einen Fehler gemacht?

    Beste Grüße,

  3. Hallo Markus,
    nach mehreren erfolglosen Versuchen einen Signalingserver einzurichten stehe ich nun mit einem großen ? über dem Kopf da.
    Ausgangslage: Eine „nackte“ VPS mit ubuntu 20.04 LTS.
    Ich bin Schritt für Schritt nach deine Anleitung vorgegangen., bekomme aber auf der Nextcloud-Seite beim „Hochleistungs-Backend“ die Meldung „Fehler: Der Server antwortet mit: 404“. Hast du eine Idee wo ich anfangen kann zu suchen?

  4. Hi Markus,
    Danke für deine Anleitung!
    Ich komme leider bei Schritt 4 nicht weiter, da ich noch nie mit nginx gearbeitet habe und gerne weiterhin apache2 verwenden würde.
    Weißt du wie ich das als apache config dateien umsetzen kann?
    Würdest mir sehr weiterhelfen!

    1. Hi Dominik,

      Apache2 sieht so aus:


      DocumentRoot /var/www/html

      # Enable proxying Websocket requests to the standalone signaling server.
      ProxyPass „/standalone-signaling/“ „ws://“

      RewriteEngine On
      # Websocket connections from the clients.
      RewriteRule ^/standalone-signaling/spreed$ – [L]
      # Backend connections from Nextcloud.
      RewriteRule ^/standalone-signaling/api/(.*)$1 [L,P]

      SSLCertificateFile /etc/letsencrypt/live/
      SSLCertificateKeyFile /etc/letsencrypt/live/
      Include /etc/letsencrypt/options-ssl-apache.conf


      1. Hi Markus,

        Danke dir für die schnelle Antwort! Leider klappt es immer noch nicht ganz.

        Port 8080 ist belegt, also habe ich in der server.conf und der apache signaling conf den Port auf 8086 gelegt. Das sollte ja keine Problem sein, oder?

        Wenn ich in den nextcloud Einstellungen nun den signaling-server hinzufüge kommt lediglich
        „Fehler: Der Server antwortete mit: 503“.
        Im apache error file heißt es:
        (111)Connection refused: AH00957: HTTP: attempt to connect to (*) failed
        AH01114: HTTP: failed to make connection to backend:
        lsof -i:8086 liefert kein Ergebnis.

        Hast du eine Idee, woran das liegen kann?

          1. Ach, sorry, im ersten Kommentar hatte ich überlesen, dass Du den Port schon geprüft hattest.

            Da scheint der Container nicht richtig zu laufen.
            docker logs nextcloud-spreed-signaling_spreedbackend_1

          2. Hi Markus,
            docker logs liefert:
            2021-01-23 11:00:04.346995 I | natsclient.go:101: Could not create connection (nats: no servers available for connection), will retry in 8s

            nats läuft jedoch und sudo netstat -tulpen | grep 4222 liefert:
            tcp6 0 0 :::4222 :::* LISTEN 0 2325896 20969/nats-server

  5. Hallo Markus, vielen Dank für die tolle Anleitung.
    Ich würde gern verstehen, warum die Docker Container das Host Netzwerk verwenden. Können diese nicht in einem eigenen Docker Netzwerk kommunizieren und nur Port 80 und 3478 exposen?
    Den nginx würde ich gerne über den jwilder/nginx-proxy laufen lassen, da auch noch andere Services auf dem Server darüber laufen und auch https mit letsencrypt darüber laufen.
    Wäre super, wenn du dazu deine Einschätzung geben könntest, ob das funktionieren müßte.

  6. Danke für die gute und übersichtliche Anleitung! Das hat bei meiner Cloud gut funktioniert und Talk endlich sinnvoll nutzbar gemacht.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert