Entwurf:Nextcloud:Signaling-Server

Aus ITWiki
Zur Navigation springen Zur Suche springen

1 High Performance Backend (Signaling Server)

Nextcloud Blog

1.1 Voraussetzungen

1.1.1 Server

  • 4 CPU Cores
  • 16 GB RAM
  • 1 GBit/s Netzwerk (Up und Down)

Darunter ist mit Einbußen bei Geschwindigkeit und Teilnehmerzahl zu rechnen.

1.1.2 Betriebssystem/Distribution

Debian 10

1.1.3 Software/Webserver/Domain

  • Nextcloud Talk Installation mit coturn
  • DNS-Subdomain für den Signaling Server
    • Webserver-Konfiguration, die diese Domain bereits mit einem validen SSL-Zertifikat bedient.

1.1.4 Szenario

Nextcloud-Server

nextcloud.meinedomain.de

TURN-Server (coturn)

turn.meinedomain.de 

Signaling Server

signaling.meinedomain.de

1.2 Signaling Server installieren

Der Signaling Server (das High Performance Backend für Nextcloud) besteht aus mehreren Komponenten:

1.2.1 Notwendigen Keys

Erzeugen

  • Janus API-Key:
openssl rand -base64 16
  • Hash-Key:
openssl rand -hex 16
  • Block-Key:
openssl rand -hex 16
  • Nextcloud Secret Key:
openssl rand -hex 16

Bereitstellen

  • Turn-Server-Key
static-auth-secret aus /etc/turnserver.conf

Im Weiteren wird auf diese Keys verwiesen (zum Beispiel: <Janus API-Key>)

1.2.2 libSRTP

  • Janus benötigt eine aktuelle Version des Pakets libsrtp2-1.
  • Die in den Ubuntu Paketquellen enthaltene Version ist hier leider zu alt, so dass man hier eine manuelle Installation per DEB-Datei (aus dem kommenden Ubuntu-Release) vornehmen muss:
cd /tmp
wget http://de.archive.ubuntu.com/ubuntu/pool/universe/libs/libsrtp2/libsrtp2-1_2.3.0-4_amd64.deb
apt install /tmp/libsrtp2-1_2.3.0-4_amd64.deb
rm libsrtp2-1_2.3.0-4_amd64.deb

1.2.3 Signaling Server

apt install golang-go
cd /etc/
git clone https://github.com/strukturag/nextcloud-spreed-signaling.git
cd /etc/nextcloud-spreed-signaling
make build

1.2.3.1 Konfigurations-Datei angepassen

cd /etc/nextcloud-spreed-signaling
cp server.conf.in server.conf nanoserver.conf 
listen = 127.0.0.1:8080
hashkey = <Hash-Key>
blockkey = <Block-Key>
backends = backend1
[backend1]
# URL of the Nextcloud instance
url = https://cloud.meinedomain.de
​
# Shared secret for requests from and to the backend servers. 
# This must be the same value as configured in the Nextcloud admin ui.
secret = <Nextcloud Secret Key>
# Verbindung zum Websocket von Janus
url = ws://127.0.0.1:8188
apikey = <Janus API-Key>
secret = <Turn-Server-Key>
servers = turn:turn.meinedomain.de:5349?transport=udp,turn:turn.meinedomain.de:5349?transport=tcp
Hinweis: 
Die Variable allowall sollte aus Gründen der Sicherheit in dieser Konfoguration immer auf false gesetzt werden. 
Die einzige Ausnahme besteht zum Testen des Signaling Servers mittels des mitgelieferten Clients (siehe unten).

Bevor wir den Signaling Server nun starten können, müssen die restlichen Programme installiert werden.

1.2.4 Janus

Die Installation erfolgt hier über einen Befehl:

apt install janus

Anschließend müssen hier ebenfalls die Konfigurations-Dateien bearbeitet werden:

vi /etc/janus/janus.jcfg

Hier konfigurieren wir den STUN-Server (coturn), aktivieren die Option „Full Trickle“ und tragen den API-Key ein:

# ...
stun_server = "turn.meinedomain.de"
stun_port = 5349
# ...
full_trickle = true
# ...
turn_rest_api_key = "<Janus API-Key>"
# ...

Anschließend wird Janus so konfiguriert, dass es nur lokal (das heißt nicht über das Netzwerk) angesprochen werden kann:

vi /etc/janus/janus.transport.http.jcfg

Das Interface wird dabei auf „lo“ gesetzt:

# ...
interface = "lo" 
# ..

Das gleiche wird auch für den Websocket gemacht:

vi /etc/janus/janus.transport.websockets.jcfg
# ...
ws_interface = "lo"
# ...

1.2.5 NATS

1.2.6 nginx

Nun muss dafür gesorgt werden, dass der Signaling Server durch nginx (oder einen anderen Webserver) erreichbar ist.

  • Hierzu bearbeiten wir den virtuellen Host, der die Signaling-Domain bedient:
vi /etc/nginx/conf.d/signaling.meinedomain.de.conf

Hier werden nun der Upstream zu Signaling Server selbst und zwei location-Blöcke hinzugefügt.

Die erweiterte Konfiguration des vHosts (zum Beispiel SSL- Header-Konfiguration) wird an dieser Stelle nicht weiter behandelt.

upstream signaling {
server 127.0.0.1:8080;
}

​ server {

listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name signaling.meinedomain.de;

​ # SSL and header configuration omitted ​ 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;
}
}

Nach einem Neustart von nginx ist dieser Teil auch abgeschlossen:

service nginx restart

1.3 Starten des Signaling Servers

Nun kommt der spannende Teil: Wir starten zum ersten mal den Signaling Server!Dazu wird erst einmal der Janus-Dienst neu gestartet:

service janus restart

Anschließend wird das Programm für einen ersten Test im Vordergrund aufgerufen:

cd /etc/nextcloud-spreed-signaling 
./bin/signaling --config server.conf

Hier wird sehr viel Output erzeugt, aber es sollten keine Fehler darunter zu finden sein.

1.4 Signaling Server als Systemdienst

  • Damit der Signaling Server nicht jedes Mal über die Konsole im Vordergrund gestartet werden muss, sollte dieser als Systemdienst installiert werden.
  • Dazu stoppen wir erst einmal die Konsolen-Instanz.
  • Zunächst legen wir uns einen speziellen User für den Signaling Server an:
groupadd signaling
useradd --system --gid signaling --shell /usr/sbin/nologin --comment "Standalone signaling server for Nextcloud Talk." signaling
  • Anschließend wird die Konfigurationsdatei des Servers noch an einen anderen Ort kopiert (damit diese zum Beispiel bei Update nicht überschrieben wird).
  • Ebenso werden die entsprechenden Berechtigungen gesetzt:
mkdir -p /etc/signaling
cp server.conf /etc/signaling/server.conf
chmod 600 /etc/signaling/server.conf
chown signaling: /etc/signaling/server.conf
  • Nun editieren wir noch die Datei für den Systemdienst:
vi dist/init/systemd/signaling.service

[Unit]
Description=Nextcloud Talk signaling server
​
[Service]
ExecStart=/etc/nextcloud-spreed-signaling/bin/signaling --config /etc/signaling/server.conf
User=signaling
Group=signaling
Restart=on-failure​
[Install] 
WantedBy=multi-user.target

Der Dienst wird im System registriert und aktiviert:

cp dist/init/systemd/signaling.service /etc/systemd/system/signaling.service
systemctl enable signaling.service systemctl start signaling.service

Anschließend wird der Signaling Server immer beim Systemstart mit geladen.

1.5 Einbinden des Signaling Servers in Nextcloud

Die Konsole packen wir erst einmal bei Seite und hinterlegen den neuen Signaling Server in der Nextcloud-Instanz.

  • Dies geschieht unter Einstellungen > Talk.
  • Ganz unten wird nun ein Signaling Server mit dem Plus-Zeichen hinzugefügt.
  • Die Domain lautet hierfür https://signaling.meinedomain.de/standalone-signaling.
  • Unter Gemeinsames Geheimnis wird nun der Nextcloud Secret Key hinterlegt, den wir ganz am Anfang erzeugt haben:

Hinterlegen des Signaling Servers in der Nextcloud Talk Konfiguration

Die Option SSL Zertifikat überprüfen sollte hier aktiviert werden, wenn der Signaling Server über ein valides Zertifikat verfügt (zum Beispiel Let’s Encrypt).

Anschließend sollte man Talk mit einer Videokonferenz testen.

  • Dazu fragt man am besten einen anderen Cloud-User um Hilfe, oder testet dies einfach über eine Talk-Konferenz mit mehreren Endgeräten (zum Beispiel PC, Notebook, Handy, etc.).
  • Wenn hier Chat- und Videofunktionen gegeben sind, läuft der Signaling Server korrekt.

1.6 Benchmark/Test

Für den Signaling Server gibt es ebenfalls einen mitgelieferten Client, mit dem man den Server testen einen Benchmark ausführen kann.

Dazu muss der Client erst einmal gebaut werden:

cd /etc/nextcloud-spreed-signaling 
make client

Als nächstes muss die Server-Konfiguration noch geändert werden, damit Verbindungen mit den Client möglich sind: vi /etc/signaling/server.conf

Hier muss in der Backend-Sektion die Variable allowall auf true gesetzt werden, damit keine Einschränkung auf bestimmte Domains besteht.
[backend]
# ...
allowall = true # ...

Der Service ist dann noch neu zu starten: service signaling restart Nun kann mit den Client ein Benchmark durchgeführt werden:

cd /etc/nextcloud-spreed-signaling ./bin/client -addr localhost:8080

Der Client baut daraufhin 100 Verbindungen zum Server auf und zeigt den Durchsatz an.

1.6.1 Benchmark des Signaling Servers

Wichtig ist hier v.a., dass sämtliche Verbindungen zu Stande kommen („All connections established“).

  • Im Hintergrund sieht man, dass das System CPU-seitig ordentlich unter Last gesetzt wird.

Wichtig: Aus Sicherheitsgründen sollte die Variable allowall in der server.conf nach dem Test wieder auf false gesetzt werden (Neustart des Services nicht vergessen).

2 Signalisierungsserver für Nextcloud

Vor kurzem wurde die Software zum Betrieb von Nextcloud Talk in größeren Nextcloudumgebungen als Open Source veröffentlicht: man braucht einen eigenen Signalisierungsserver, um mit mehreren parallel Leuten effektiv über Nextcloud Talk arbeiten zu können.

2.1 Voraussetzungen

Ich würde sowohl einen STUN Server als auch den Signalisierungsserver auf eigenen VMs betreiben.

  • Ich würde hier direkt die Hetzner Cloud empfehlen: preiswert, performant und sehr einfach zum Hochskalieren.
  • Zwei kleine Maschinen reichen für den Anfang.
  • Den STUN Server solltest du bereits auf einer anderen Maschine gesondert fertig installiert haben.

Bitte beachte, dass ich bisher auch nur einen laufenden Signalisierungsserver hinbekommen habe, aber noch nicht tiefer getestet und Security Hardening betrieben habe.

  • Es sind die ersten Gehversuche, die ich hier zeigen möchte.

2.2 Installation der Services

Ich gehe hier von Debian 10 aus.

  • Als erstes solltest du Docker, nginx und sonstige Grundprogramme wie git, unzip etc.
  • installiert haben.

Den Signaling Server direkt von Github selbst kompilieren:

apt install git automake golang build-essential certbot nginx apt-transport-https ca-certificates curl gnupg-agent software-properties-common
git clone https://github.com/strukturag/nextcloud-spreed-signaling.git
cd nextcloud-spreed-signaling/
make build
cp bin/signaling /usr/bin/

Nun die Konfigurationsdatei aus dem Repo an die richtige Stelle kopieren.:

mkdir /etc/signaling/
cp server.conf.in /etc/signaling/server.conf
useradd --system --shell /usr/sbin/nologin --comment "Standalone signaling server for Nextcloud Talk." signaling chown signaling: /etc/signaling/server.conf
chmod 600 /etc/signaling/server.conf

Anschließend den Service für den Signaling Server einrichten und vorher natürlich die Systemd Datei entsprechend eurer Pfade anpassen, wenn abweichend:

cp dist/init/systemd/signaling.service /etc/systemd/system/signaling.service
systemctl daemon-reload
systemctl enable signaling

Nun müssen wir die einzelnen Services für den Signaling Server aufsetzen.

  • Zunächst den NATS Server, den ich der Einfachheit halber mit Docker installiert habe, da es kein Repo gibt:
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian \
$(lsb_release -cs) \
stable"
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io
docker run --restart=always --name='natsserver' -d -p 4222:4222 -ti nats:latest

Außerdem brauchen wir einen Janus Server:

apt install janus

Nun muss der Service konfiguriert werden: nano /etc/janus/janus.jcfgHier habe ich mich an diese Anleitung gehalten und folgende Werte gesetzt: turn_rest_api_key (mittels openssl rand -base64 16 erstellen, ist derselbe String wie bei apikey in der signaling conf!), full_trickle = true und die ssl Zeilen auskommentieren.

general: {
configs_folder = "/etc/janus" # Configuration files folder
plugins_folder = "/usr/lib/x86_64-linux-gnu/janus/plugins" # Plugins folder
transports_folder = "/usr/lib/x86_64-linux-gnu/janus/transports" # Transports folder
events_folder = "/usr/lib/x86_64-linux-gnu/janus/events" # Event handlers folder
debug_level = 4 # Debug/logging level, valid values are 0-7
server_name = "Janus Speibox"# Public name of this Janus instance
}
# Certificate and key to use for DTLS (and passphrase if needed).
#certificates: {
# cert_pem = "/etc/ssl/certs/ssl-cert-snakeoil.pem"
# cert_key = "/etc/ssl/certs/ssl-cert-snakeoil.key"
#cert_pwd = "secretpassphrase"
#}
nat: {
nice_debug = false
full_trickle = true
turn_rest_api_key = "apikey from server.conf"
}

Damit kann der Dienst gestartet werden.

Es braucht natürlich noch einen coturn Server.

  • Dieser wird ganz simpel mit apt install coturn installiert und sollte wie bereits erwähnt nach dieser Anleitung schon installiert sein.

2.2.1 Konfiguration des Signaling Servers

Abschließend müssen wir den Signaling Server noch konfigurieren: nano /etc/signaling/server.conf:* hashkey mit openssl rand -hex 16 generieren

  • blockkey mit openssl rand -hex 16 generieren
  • internalsecret ebenfalls mit einem String Generator setzen
  • unter allowed alle Hostnamen eintragen, die dieses Backend verwenden dürfen
  • direkt darunter bei secret ein Secret generieren.
  • Das wird später bei Nextcloud in den Settings eingetragen
  • connectionsperhost sollte adaptiert werden
  • unter nats wird die url so gesetzt: url = nats://localhost:4222
  • bei mcu wird die url so gesetzt: url = ws://0.0.0.0:8188 (Janus läuft nicht localhost, ist noch ein offenes Security Thema)
  • unter turn wird apikey mit dem gleichen Wert vom Janus Server (turn_rest_api_key) gesetzt
  • das secret in der Rubrik turn bekommt den gleichen Wert wie static-auth-secret des Turnserver gesetzt
  • bei servers werden alle Turnserver kommasepariert so gesetzt: turn:116.202.113.XXX:5349?transport=tcp

Nun sollte service signaling start erfolgreich sein.

2.3 nginx vhost

Ich habe meine nginx Installation nicht groß konfiguriert und möchte nur kurz meinen ssl vhost darstellen, den ihr auch 1:1 aus dem offiziellen Repo übernehmen könnt:

upstream signaling {
server 127.0.0.1:8080;
}

server {
listen 443 ssl http2;
server_name signaling.xy.de;
ssl_certificate /etc/letsencrypt/live/signaling.xy.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/signaling.xy.de/privkey.pem;
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;
}
}

Wenn ihr nun alles richtig gemacht habt, sollte curl -i https://signaling.xy.de/standalone-signaling/api/v1/welcome folgende Antwort liefern:

HTTP/1.1 200 OK
Date: Thu, 05 Jul 2018 09:28:08 GMT
Server: nextcloud-spreed-signaling/1.0.0
Content-Type: application/json; charset=utf-8
Content-Length: 59

{"nextcloud-spreed-signaling":"Welcome","version":"1.0.0"}

2.4 Nextcloud Integration

Installiert die Beta Version von Nextcloud Talk – am besten zum Testen mal in einer eigenen Installation auf dem Beta Release Channel für Nextcloud 19 (für Nextcloud 18 habe ich das nicht probiert).

  • In den Einstellungen von Nextcloud im Reiter Talk nun folgende Konfiguration setzen:

STUN und Signaling Server laufen bei mir auf getrennten Maschinen.

  • Das Gemeinsame Geheimnis ist das secret aus der Signaling Server conf.

Quelle: https://nichteinschalten.de/signalisierungsserver-fuer-nextcloud-aufsetzen-how-to/

3 How to Install Nextcloud Talk High Performance Backend with Stun/Turnserver on Ubuntu

3.1 Anforderungen

  • Ubuntu 18.04 or 20.04 LTS minimal
  • Image installed
    • 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 signaling.example.com for all three services in this guide
  • Optional
    • a second DNS A and possibly AAAA record for stun/turnserver

3.1.1 Hardware Anforderungen

  • 4 CPU
  • 8 GB RAM
  • 32 GB Disk-Space

See also

  1. Nextcloud Portal

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

3.2 Arbeitsschritte

3.2.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 and 22 (ssh) 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 5349/tcp ufw allow 5349/udp ufw enable

Accept with „y“

3.2.2 Install and config stun/turnserver

you have to install the package coturn:

apt install coturn

enable daemonizing for your turnserver:

sed -i '/TURNSERVER_ENABLED/c\TURNSERVER_ENABLED=1' /etc/default/coturn

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

openssl rand -hex 32

and copy it for later use, then edit /etc/turnserver.conf:

mv /etc/turnserver.conf /etc/turnserver.conf.bak && nano /etc/turnserver.conf

copy, paste and adjust the following code:

listening-port=5349
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=output_of_openssl rand -hex 32
realm=signaling.example.com
total-quota=100
bps-capacity=0
stale-nonce
no-loopback-peers
no-multicast-peers

and last, restart and enable coturn:

systemctl restart coturn && systemctl enable coturn

3.2.3 Install and config janus

The Version of janus in official repository of Ubuntu 18.04 is 0.2.6-1build2, so if you use 18.04 try Gitlab Repository.

  • of morph27 instead.
  • If you use 20.04 the version is suitable.

Ubuntu 18.04add repo key:

curl -sL -o /etc/apt/trusted.gpg.d/morph027-janus.asc https://packaging.gitlab.io/janus/gpg.key

add repo:

. /etc/lsb-release; echo "deb [arch=amd64] https://packaging.gitlab.io/janus/$DISTRIB_CODENAME $DISTRIB_CODENAME main" | tee /etc/apt/sources.list.d/morph027-janus.list
apt update

Ubuntu 20.04 and 18.04:

apt install janus

Now generate a random api key for turnserver:

openssl rand -base64 16

and copy the output for later use.

vi /etc/janus/janus.jcfg

go to section nat and enter your stunserver and port, uncomment full_trickle = true, turn_server with port and type and the generated api key.

You can copy, paste and adjust the following:

stun_server = "signaling.example.com"
stun_port = 5349
full_trickle = true
turn_server = "signaling.example.com"
turn_port = 5349
turn_type = "udp"
turn_rest_api_key = "output_from_openssl rand -base64 16"

then comment the following lines:

  1. certificates: {# cert_pem = „/etc/ssl/certs/ssl-cert-snakeoil.pem“# cert_key = „/etc/ssl/private/ssl-cert-snakeoil.key“#cert_pwd = „secretpassphrase“#}

next edit /etc/janus/janus.transport.http.jcfg:

vi /etc/janus/janus.transport.http.jcfg

and set in section general the interface to lo:

interface = "lo"

same in /etc/janus/janus.transport.websockets.jcfg:

vi /etc/janus/janus.transport.websockets.jcfg
interface = "lo"
  • janus will now only listen on lo-interface (127.0.0.1)

enable and restart janus:

systemctl restart janus && systemctl enable janus

3.2.4 Running or Install NATS Server

If your VPS support docker, then you can use docker to run NATS Server:

Install docker if not installed:
curl -sSL https://get.docker.com/ | CHANNEL=stable sh
systemctl enable docker.service
systemctl start docker.service

then run NATS Server:

docker run --restart=always --name=NATSSERVER -d -p 4222:4222 -ti --restart=always nats:latest

when you want to run NATS Server without docker, there is another Repository of morph27.

you have to add its key and its repo:

curl -sL -o /etc/apt/trusted.gpg.d/morph027-nats-server.asc https://packaging.gitlab.io/nats-server/gpg.key
echo "deb [arch=amd64] https://packaging.gitlab.io/nats-server nats main" | tee /etc/apt/sources.list.d/morph027-nats-server.list

install NATS Server:

apt update
apt install nats-server

generate config under /etc/nats/nats.conf

install -d -o nats -g nats /etc/nats
sudo -u nats echo "listen: 127.0.0.1:4222" > /etc/nats/nats.conf
start and enable NATS-Server:
systemctl start nats-server && systemctl enable nats-server

3.2.5 Install nextcloud-spreed-signaling Server

now we can install the nextcloud-spreed-signaling server, first of all, we have to install the packages we need to built:

apt install git automake golang build-essential python3 -y

then we clone the git repository and start the build process:

cd /opt
git clone https://github.com/strukturag/nextcloud-spreed-signaling.git
cd nextcloud-spreed-signaling/
make build

then copy the binary to /usr/bin

cp bin/signaling /usr/bin/

now create a dedicated user:

useradd --system --shell /usr/sbin/nologin --comment "Standalone signaling server for Nextcloud Talk." signaling
create the server.conf in /etc/signaling/

mkdir /etc/signaling/
touch /etc/signaling/server.conf
chown signaling: /etc/signaling/server.conf
chmod 600 /etc/signaling/server.conf

and copy the systemd file:

cp dist/init/systemd/signaling.service /etc/systemd/system/signaling.service
systemctl daemon-reload
systemctl enable signaling
  • create keys for config:

Nextcloud Secret Key

openssl rand -hex 16
Block-Key
openssl rand -hex 16
Hash-Key
openssl rand -hex 16

Now we have five keys at all, as example (do not use these keys)

Turn-Key from Step 2

api-key from Step 3:Nextcloud-Secret-Key Block-Key Hash-Key

vi /etc/signaling/server.conf

then copy, paste and adjust (change keys to yours) the following config

[http]
listen = 127.0.0.1:8080
[app]
debug = false

[sessions]
hashkey = db61d5a8c6bd2b47a3cb0abce3545040
blockkey = f702adbf248ab0e752fa76cb46bcba12

[backend]
allowed = nextcloud.example.com
allowall = false
secret = 692cdc99256135bcb7849ca1886e2ed6
timeout = 10
connectionsperhost = 8

[nats]
url = nats://localhost:4222

[mcu]
type = janus
url = ws://127.0.0.1:8188

[turn]
apikey = Z6ZkKhjwCFa6RMpFU854Fw==
secret = 2309a206fc4de0f511ce9da52c088171f69193d1f701323d5ab4f733c9853445
servers = turn:signaling.example.com:5349?transport=udp,turn:signaling.example.com:5349?transport=tcp

then start signaling:

systemctl start signaling

and check staus of the service:

systemctl status signaling

and if it listens on port 8080:

netstat -tulpen | grep 8080

3.2.6 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:

vi /etc/nginx/sites-available/signaling

copy, paste and adjust:

server {
listen 80;
server_name signaling.example.com; 
}

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 signaling.example.com --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 127.0.0.1:8080;
}

server { server_name signaling.example.com;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/signaling.example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/signaling.example.com/privkey.pem; # 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 = signaling.example.com) {
return 301 https://$host$request_uri; } # managed by Certbot
listen 80;
server_name signaling.example.com; return 404; # managed by Certbot
}

and check an reload nginx:

nginx -t
if ok
systemctl reload nginx

3.2.7 Configure nextcloud to use stun/turn and signaling server

Go to Settings, Talk and enter the following:




4 Spreed standalone signaling server

This repository contains the standalone signaling server which can be used for Nextcloud Talk (https://apps.nextcloud.com/apps/spreed).

See https://nextcloud-talk.readthedocs.io/en/latest/standalone-signaling-api-v1/ for further information on the API of the signaling server.

4.1 Building

The following tools are required for building the signaling server.* git

  • go >= 1.10
  • make


All other dependencies are fetched automatically while building.

$ make build

or on FreeBSD

$ gmake build

Afterwards the binary is created as bin/signaling.

4.2 Configuration

A default configuration file is included as server.conf.in. Copy this to server.conf and adjust as necessary for the local setup. See the file for comments about the different parameters that can be changed.

4.3 Running

The signaling server connects to a NATS server (https://nats.io/) to distribute messages between different instances. See the NATS documentation on how to set up a server and run it.

Once the NATS server is running (and the URL to it is configured for the signaling server), you can start the signaling server.

$ ./bin/signaling

By default, the configuration is loaded from server.conf in the current directory, but a different path can be passed through the --config option.

$ ./bin/signaling --config /etc/signaling/server.conf

4.3.1 Running as daemon

4.3.1.1 systemd

Create a dedicated user:

sudo useradd --system \

   --gid signaling \
   --shell /usr/sbin/nologin \
   --comment "Standalone signaling server for Nextcloud Talk." \
   signaling

Copy server.conf.in to /etc/signaling/server.conf and fix permissions:

sudo chmod 600 /etc/signaling/server.conf sudo chown signaling: /etc/signaling/server.conf

Copy dist/init/systemd/signaling.service to /etc/systemd/system/signaling.service (adjust abs. path in ExecStart to match your binary location!)

Enable and start service:

systemctl enable signaling.service systemctl start signaling.service

4.3.2 Running with Docker

4.3.2.1 Docker Compose

You will likely have to adjust the Janus command line options depending on the exact network configuration on your server. Refer to Setup of Janus and the Janus documentation for how to configure your Janus server.

Copy server.conf.in to server.conf and adjust it to your liking.

If you're using the docker-compose.yml configuration as is, the MCU Url must be set to ws://localhost:8188, the NATS Url must be set to nats://localhost:4222, and TURN Servers must be set to turn:localhost:3478?transport=udp,turn:localhost:3478?transport=tcp.

docker-compose build docker-compose up -d

4.4 Setup of NATS server

There is a detailed description on how to install and run the NATS server available at http://nats.io/documentation/tutorials/gnatsd-install/

You can use the gnatsd.conf file as base for the configuration of the NATS server.

4.5 Setup of Janus

A Janus server (from https://github.com/meetecho/janus-gateway) can be used to act as a WebRTC gateway. See the documentation of Janus on how to configure and run the server. At least the VideoRoom plugin and the websocket transport of Janus must be enabled.

The signaling server uses the VideoRoom plugin of Janus to manage sessions. All gateway details are hidden from the clients, all messages are sent through the signaling server. Only WebRTC media is exchanged directly between the gateway and the clients.

Edit the server.conf and enter the URL to the websocket endpoint of Janus in the section [mcu] and key url. During startup, the signaling server will connect to Janus and log information of the gateway.

The maximum bandwidth per publishing stream can also be configured in the section [mcu], see properties maxstreambitrate and maxscreenbitrate.

4.5.1 Use multiple Janus servers

To scale the setup and add high availability, a signaling server can connect to one or multiple proxy servers that each provide access to a single Janus server.

For that, set the type key in section [mcu] to proxy and set url to a space-separated list of URLs where a proxy server is running.

Each signaling server that connects to a proxy needs a unique token id and a public / private RSA keypair. The token id must be configured as token_id in section [mcu], the path to the private key file as token_key.

4.5.2 Setup of proxy server

The proxy server is built with the standard make command make build as bin/proxy binary. Copy the proxy.conf.in as proxy.conf and edit section [tokens] to the list of allowed token ids and filenames of the public keys for each token id. See the comments in proxy.conf.in for other configuration options.

When the proxy process receives a SIGHUP signal, the list of allowed token ids / public keys is reloaded. A SIGUSR1 signal can be used to shutdown a proxy process gracefully after all clients have been disconnected. No new publishers will be accepted in this case.

4.6 Setup of frontend webserver

Usually the standalone signaling server is running behind a webserver that does the SSL protocol or acts as a load balancer for multiple signaling servers.

The configuration examples below assume a pre-configured webserver (nginx or Apache) with a working HTTPS setup, that is listening on the external interface of the server hosting the standalone signaling server.

After everything has been set up, the configuration can be tested using curl:

$ curl -i https://myserver.domain.invalid/standalone-signaling/api/v1/welcome HTTP/1.1 200 OK Date: Thu, 05 Jul 2018 09:28:08 GMT Server: nextcloud-spreed-signaling/1.0.0 Content-Type: application/json; charset=utf-8 Content-Length: 59

{"nextcloud-spreed-signaling":"Welcome","version":"1.0.0"}

4.6.1 nginx

Nginx can be used as frontend for the standalone signaling server without any additional requirements.

The backend should be configured separately so it can be changed in a single location and also to allow using multiple backends from a single frontend server.

Assuming the standalone signaling server is running on the local interface on port 8080 below, add the following block to the nginx server definition in /etc/nginx/sites-enabled (just before the server definition):

upstream signaling {

   server 127.0.0.1:8080;

}

To proxy all requests for the standalone signaling to the correct backend, the following location block must be added inside the server definition of the same file:

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;

}

Example (e.g. /etc/nginx/sites-enabled/default):

upstream signaling {

   server 127.0.0.1:8080;

}

server {

   listen 443 ssl http2;
   server_name myserver.domain.invalid;
   # ... other existing configuration ...
   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;
   }

}

4.6.2 Apache

To configure the Apache webservice as frontend for the standalone signaling server, the modules mod_proxy_http and mod_proxy_wstunnel must be enabled so WebSocket and API backend requests can be proxied:

# a2enmod proxy
# a2enmod proxy_http
# a2enmod proxy_wstunnel

Now the Apache VirtualHost configuration can be extended to forward requests to the standalone signaling server (assuming the server is running on the local interface on port 8080 below):

<VirtualHost *:443>

   # ... existing configuration ...

   # Enable proxying Websocket requests to the standalone signaling server.
   ProxyPass "/standalone-signaling/"  "ws://127.0.0.1:8080/"

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

   # ... existing configuration ...

</VirtualHost>

4.6.3 Caddy

4.6.3.1 v1

Caddy (v1) configuration:

myserver.domain.invalid {
 proxy /standalone-signaling/ http://127.0.0.1:8080 {
   without /standalone-signaling
   transparent
   websocket
 }
}

4.6.3.2 v2

Caddy (v2) configuration:

myserver.domain.invalid {
 route /standalone-signaling/* {
   uri strip_prefix /standalone-signaling
   reverse_proxy /standalone-signaling/* http://127.0.0.1:8080
 }
}

4.7 Setup of Nextcloud Talk

  • Login to your Nextcloud as admin and open the additional settings page.
  • Scroll down to the "Talk" section and enter the base URL of your standalone signaling server in the field "External signaling server".
  • Please note that you have to use https if your Nextcloud is also running on https.
  • Usually you should enter https://myhostname/standalone-signaling as URL.
  • The value "Shared secret for external signaling server" must be the same as the property secret in section backend of your server.conf.
  • If you are using a self-signed certificate for development, you need to uncheck the box Validate SSL certificate so backend requests from Nextcloud to the signaling server can be performed.

4.8 Benchmarking the server

A simple client exists to benchmark the server. Please note that the features that are benchmarked might not cover the whole functionality, check the implementation in src/client for details on the client.

To authenticate new client connections to the signaling server, the client starts a dummy authentication handler on a local interface and passes the URL in the hello request. Therefore the signaling server should be configured to allow all backend hosts (option allowall in section backend).

The client is not compiled by default, but can be using the client target:

$ make client
Usage:
$ ./bin/client
Usage of ./bin/client:
 -addr string
       http service address (default "localhost:28080")
 -config string
       config file to use (default "server.conf")
 -maxClients int
       number of client connections (default 100)

4.9 Running multiple signaling servers

IMPORTANT
This is considered experimental and might not work with all functionality of the signaling server, especially when using the Janus integration.
  • The signaling server uses the NATS server to send messages to peers that are not connected locally.
  • Therefore multiple signaling servers running on different hosts can use the same NATS server to build a simple cluster, allowing more simultaneous connections and distribute the load.
  • To set this up, make sure all signaling servers are using the same settings for their session keys and the secret in the backend section.
  • Also the URL to the NATS server (option url in section nats) must point to the same NATS server.
  • If all this is setup correctly, clients can connect to either of the signaling servers and exchange messages between them.

5 Links

5.1 Intern

TODO

5.2 Extern

  1. https://github.com/strukturag/nextcloud-spreed-signaling
  2. https://de.wikipedia.org/wiki/WebRTC
  3. https://decatec.de/home-server/nextcloud-talk-mit-eigenem-signaling-server-high-performance-backend/
  4. https://decatec.de/home-server/nextcloud-auf-ubuntu-server-20-04-lts-mit-nginx-mariadb-php-lets-encrypt-redis-und-fail2ban/
  5. https://decatec.de/home-server/nextcloud-talk-mit-eigenem-turn-server-coturn/
  6. https://decatec.de/linux/lets-encrypt-zertifikate-mit-acme-sh-und-nginx/
  7. https://decatec.de/home-server/rsa-und-ecdsa-zertifikate-mit-nginx-hybrid-loesung/
  8. https://decatec.de/home-server/tlsv1-3-unter-ubuntu-server-18-04-lts-mit-nginx/
  9. https://decatec.de/home-server/docker-auf-ubuntu-server/