From d0c32f1ac61ef43b7e6e090729a7599cab3f9899 Mon Sep 17 00:00:00 2001 From: Hans van Zijst Date: Wed, 8 Jan 2025 14:51:11 +0100 Subject: [PATCH] Changed TURN documentation so we can use both legacy and Element Call. Fixed a few broken internal links. --- matrix/README.md | 6 +-- matrix/coturn/README.md | 40 ++++++++++------- matrix/coturn/turnserver.conf | 10 ++++- matrix/element-call/README.md | 84 +++++++++++++++++++++-------------- matrix/firewall/README.md | 22 +++++---- matrix/nginx/README.md | 2 +- 6 files changed, 100 insertions(+), 64 deletions(-) diff --git a/matrix/README.md b/matrix/README.md index a47e8e6..780f501 100644 --- a/matrix/README.md +++ b/matrix/README.md @@ -95,7 +95,7 @@ how to [setup and configure it](element-call). # Element Web This is the fully-fledged web client, which is very [easy to set -up](element-call). +up](element-web). # TURN @@ -104,8 +104,8 @@ We may need a TURN server, and we'll use [coturn](coturn) for that. It's apparently also possible to use the built-in TURN server in Livekit, -which we'll use if we use [Element Call](call). It's either/or, so make sure -you pick the right approach. +which we'll use if we use [Element Call](element-call). It's either/or, so make +sure you pick the right approach. You could possibly use both coturn and LiveKit, if you insist on being able to use both legacy and Element Call functionality. This is not documented here diff --git a/matrix/coturn/README.md b/matrix/coturn/README.md index 44368a2..4468f0d 100644 --- a/matrix/coturn/README.md +++ b/matrix/coturn/README.md @@ -5,16 +5,22 @@ include_toc: true # TURN server -You need an TURN server to connect participants that are behind a NAT firewall. +You need a TURN server to connect participants that are behind a NAT firewall. Because IPv6 doesn't really need TURN, and Chrome can get confused if it has to use TURN over IPv6, we'll stick to a strict IPv4-only configuration. Also, because VoIP traffic is only UDP, we won't do TCP. -IMPORTANT! TURN can also be offered by [LiveKit](../element-call#livekit), in -which case you should probably not run coturn (unless you don't use LiveKit's -built-in TURN server, or want to run both to support legacy calls too). +TURN-functionality can be offered by coturn and LiveKit alike: coturn is used +for legacy calls (only one-on-one, supported in Element Android), whereas +Element Call (supported by ElementX, Desktop and Web) uses LiveKit. +In our documentation we'll enable both, which is probably not the optimal +solution, but at least it results in a system that supports old and new +clients. + +Here we'll describe coturn, the dedicated ICE/STUN/TURN server that needs to +be configured in Synapse, [LiveKit](../element-call#livekit) has its own page. # Installation @@ -73,24 +79,23 @@ certbot certonly --nginx -d turn.example.com This assumes you've already setup and started nginx (see [nginx](../nginx)). {#fixssl} -The certificate files reside under `/etc/letsencrypt/live`, but coturn -doesn't run as root, and can't read them. Therefore we create the directory +The certificate files reside under `/etc/letsencrypt/live`, but coturn and +LiveKit don't run as root, and can't read them. Therefore we create the directory `/etc/coturn/ssl` where we copy the files to. This script should be run after each certificate renewal: ``` #!/bin/bash -# This script is hooked after a renewal of the certificate, so -# that it's copied and chowned and made readable by coturn: +# This script is hooked after a renewal of the certificate, so that the +# certificate files are copied and chowned, and made readable by coturn: cd /etc/coturn/ssl cp /etc/letsencrypt/live/turn.example.com/{fullchain,privkey}.pem . chown turnserver:turnserver *.pem -# We should restart either coturn or LiveKit, they cannot run both! -systemctl restart coturn -#systemctl restart livekit-server +# Make sure you only start/restart the servers that you need! +systemctl try-reload-or-restart coturn livekit-server ``` @@ -102,7 +107,8 @@ renew_hook = /etc/coturn/fixssl ``` Yes, it's a bit primitive and could (should?) be polished. But for now: it -works. +works. This will copy and chown the certificate files and restart coturn +and/or LiveKit, depending on if they're running or not. # Configuration {#configuration} @@ -121,9 +127,13 @@ Now that we have this, we can configure our configuration file under `/etc/coturn/turnserver.conf`. ``` +# We don't use the default ports, because LiveKit uses those +listening-port=3480 +tls-listening-port=5351 + # We don't need more than 10000 connections: -min-port=50000 -max-port=60000 +min-port=40000 +max-port=49999 use-auth-secret static-auth-secret= @@ -133,7 +143,7 @@ user-quota=12 total-quota=1200 # Of course: substitute correct IPv4 address: -listening-ip=185.206.232.60 +listening-ip=111.222.111.222 # VoIP traffic is only UDP no-tcp-relay diff --git a/matrix/coturn/turnserver.conf b/matrix/coturn/turnserver.conf index 8e1c6d7..3b99ef7 100644 --- a/matrix/coturn/turnserver.conf +++ b/matrix/coturn/turnserver.conf @@ -3,11 +3,17 @@ # Only IPv4, IPv6 can confuse some software listening-ip=111.222.111.222 +# Listening port for TURN (UDP and TCP): +listening-port=3480 + +# Listening port for TURN TLS (UDP and TCP): +tls-listening-port=5351 + # Lower and upper bounds of the UDP relay endpoints: # (default values are 49152 and 65535) # -min-port=50000 -max-port=60000 +min-port=40000 +max-port=49999 use-auth-secret static-auth-secret= diff --git a/matrix/element-call/README.md b/matrix/element-call/README.md index 365b99b..8ccf5ce 100644 --- a/matrix/element-call/README.md +++ b/matrix/element-call/README.md @@ -11,7 +11,7 @@ here's what you need. * **lk-jwt**. This authenticates Synapse users to LiveKit. * **LiveKit**. This is the "SFU", which actually handles the audio and video, and does TURN. -* **Element Call widget**. This is basically the webapplication, the part you see. +* **Element Call widget**. This is basically the webapplication, the user interface. As mentioned in the [checklist](../checklist.md) you need to define these three entries in DNS and get certificates for them: @@ -20,6 +20,9 @@ three entries in DNS and get certificates for them: * `livekit.example.com` * `call.example.com` +You may already have DNS and TLS for `turn.example.com`, as it is also used +for [coturn](../coturn). + For more inspiraten, check https://sspaeth.de/2024/11/sfu/ @@ -97,8 +100,7 @@ turn: udp_port: 3478 external_tls: true keys: - # KEY: SECRET were autogenerated by livekit/generate - # in the lk-jwt-service environment variables + # KEY: SECRET were generated by "livekit-server generate-keys" : ``` @@ -109,6 +111,15 @@ chown root:turnserver /etc/livekit/livekit.yaml chmod 640 /etc/livekit/livekit.yaml ``` +Port `7880` is forwarded by nginx: authentication is also done there, and that +bit has to be forwarded to `lk-jwt-service` on port `8080`. Therefore, we +listen only on localhost. + +The TURN ports are the normal, default ones. If you also use coturn, make sure +it doesn't use the same ports as LiveKit. Also, make sure you open the correct +ports in the [firewall](../firewall). + + ## TLS certificate The TLS-certificate files are not in the usual place under @@ -124,7 +135,7 @@ read them there too. If you don't have coturn installed, you should create a directory under `/etc/livekit` and copy the files to there. Modify the `livekit.yaml` file and the [script to copy the files](../coturn/README.md#fixssl) to use that -directory. Don't forget to update the `renew_hook` in Letsencrypt. +directory. Don't forget to update the `renew_hook` in Letsencrypt if you do. The LiveKit API listens on localhost, IPv6, port 7880. Traffic to this port is forwarded from port 443 by nginx, which handles TLS, so it shouldn't be reachable @@ -158,14 +169,6 @@ WantedBy=multi-user.target Enable and start it. -<<<<< -IMPORTANT! - -LiveKit is configured to use its built-in TURN server, using the same ports as -[coturn](../coturn). Obviously, LiveKit and coturn are mutually exclusive in -this setup. Shutdown and disable coturn if you use LiveKit's TURN server. ->>>>> - Clients don't know about LiveKit yet, you'll have to give them the information via the `.well-known/matrix/client`: add this bit to it to point them at the SFU: @@ -183,26 +186,13 @@ Make sure it is served as `application/json`, just like the other .well-known files. -lk-jwt-service is a small Go program that handles authorization tokens. You'll need a -Go compiler, so install that: - -``` -apt install golang -``` - - # lk-jwt-service {#lkjwt} -Get the latest source code and comile it (preferably *NOT* as root): - -``` -git clone https://github.com/element-hq/lk-jwt-service.git -cd lk-jwt-service -go build -o lk-jwt-service -``` - -You'll then notice that you need a newer compiler, so we'll download that and add it to -our PATH (again not as root): +lk-jwt-service is a small Go program that handles authorization tokens for use with LiveKit. +You'll need a Go compiler, but the one Debian provides is too old (at the time +of writing this, at least), so we'll install the latest one manually. Check +[the Go website](https://go.dev/dl/) to see which version is the latest, at +the time of writing it's 1.23.3, so we'll install that: ``` wget https://go.dev/dl/go1.23.3.linux-amd64.tar.gz @@ -212,6 +202,18 @@ export PATH=`pwd`:$PATH cd ``` +This means you now have the latest Go compiler in your path, but it's not +installed system-wide. If you want that, copy the whole `go` directory to +`/usr/local` and add `/usr/local/go/bin` to everybody's $PATH. + +Get the latest lk-jwt-service source code and comile it (preferably *NOT* as root): + +``` +git clone https://github.com/element-hq/lk-jwt-service.git +cd lk-jwt-service +go build -o lk-jwt-service +``` + Now, compile: ``` @@ -226,6 +228,7 @@ cp ~user/lk-jwt-service/lk-jwt-service /usr/local/sbin chown root:root /usr/local/sbin/lk-jwt-service ``` + ## Systemd Create a service file for systemd, something like this: @@ -258,8 +261,8 @@ else. ``` mkdir /etc/lk-jwt-service vi /etc/lk-jwt-service/config -chgrp -R www-data /etc/lk-jwt-service -chmod -R o-rwx /etc/lk-jwt-service +chgrp -R root:www-data /etc/lk-jwt-service +chmod 750 /etc/lk-jwt-service ``` This is what you should put into that config file, @@ -273,12 +276,20 @@ LIVEKIT_KEY=xxx LK_JWT_PORT=8080 ``` +Change the permission accordingly: + +``` +chown root:www-data /etc/lk-jwt-service/config +chmod 640 /etc/lk-jwt-service/config +``` + Now enable and start this thing: ``` systemctl enable --now lk-jwt-service ``` + # Element Call widget {#widget} This is a Node.js thingy, so start by installing yarn. Unfortunately both npm @@ -305,6 +316,9 @@ sudo apt install yarnpkg /usr/share/nodejs/yarn/bin/yarn install ``` +Yes, this whole Node.js, yarn and npm thing is a mess. Better documentation +could be written, but for now this will have to do. + Now clone the Element Call repository and "compile" stuff (again: not as root): @@ -315,8 +329,10 @@ cd element-call /usr/share/nodejs/yarn/bin/yarn build ``` -After that, you can find the whole shebang under "dist". Copy that to -`/var/www/element-call` and point nginx to it ([see nginx](../nginx#callwidget)). +If it successfully compiles (warnings are more or less ok, errors aren't), you will +find the whole shebang under "dist". Copy that to `/var/www/element-call` and point +nginx to it ([see nginx](../nginx#callwidget)). + ## Configuring diff --git a/matrix/firewall/README.md b/matrix/firewall/README.md index 461c957..9e1ba33 100644 --- a/matrix/firewall/README.md +++ b/matrix/firewall/README.md @@ -1,21 +1,25 @@ # Firewall -This page is mostly a placeholder for now, but configuration of the firewall -is -of course- very important. +Several ports need to be opened in the firewall, this is a list of all ports +that are needed by the components we describe in this document. -First idea: the ports that need to be opened are: +Those for nginx are necessary for Synapse to work, the ones for coturn and +LiveKit only need to be opened if you run those servers. | Port(s) / range | IP version | Protocol | Application | | :-------------: | :--------: | :------: | :--------------------- | | 80, 443 | IPv4/IPv6 | TCP | nginx, reverse proxy | | 8443 | IPv4/IPv6 | TCP | nginx, federation | -| 7881 | IPv4/IPv6 | TCP/UDP | coturn/LiveKit TURN | -| 3478 | IPv4 | UDP | coturn/LiveKit TURN | -| 5349 | IPv4 | TCP | coturn/LiveKit TURN | -| 50000-60000 | IPv4 | TCP/UDP | coturn/LiveKit TURN | +| 3478 | IPv4 | UDP | LiveKit TURN | +| 5349 | IPv4 | TCP | LiveKit TURN TLS | +| 7881 | IPv4/IPv6 | TCP | LiveKit RTC | +| 50000-60000 | IPv4/IPv6 | TCP/UDP | LiveKit RTC | +| 3480 | IPv4 | TCP/UDP | coturn TURN | +| 5351 | IPv4 | TCP/UDP | coturn TURN TLS | +| 40000-49999 | IPv4 | TCP/UDP | coturn RTC | -The ports necessary for TURN depend very much on the specific configuration -[coturn](../coturn#configuration) or [LiveKit](../element-call#livekit). +The ports necessary for TURN depend very much on the specific configuration of +[coturn](../coturn#configuration) and/or [LiveKit](../element-call#livekit). diff --git a/matrix/nginx/README.md b/matrix/nginx/README.md index 63afd7f..1c2e466 100644 --- a/matrix/nginx/README.md +++ b/matrix/nginx/README.md @@ -49,7 +49,7 @@ list-timers` lists `certbot.timer`. However, renewing the certificate means you'll have to restart the software that's using it. We have 2 or 3 pieces of software that use certificates: -[coturn](../cotorun) and/or [LiveKit](../livekit), and [nginx](../nginx). +[coturn](../coturn) and/or [LiveKit](../element-call#livekit), and [nginx](../nginx). Coturn/LiveKit are special with regards to the certificate, see their respective pages. For nginx it's pretty easy: tell Letsencrypt to restart it