docs(turn,livekit): Small changes

* Small wording changes on calls.mdx
* Add env var sample for livekit foci
* Simplify TURNS-over-443 Caddyfile (livekit + turn)
* Improve TURNS-over-443 wordings (livekit + turn)
* Link to MRTC room on turn documentation
This commit is contained in:
stratself authored and Ellis Git committed 2026-08-04 18:18:54 +00:00
1 parent e14a86026a
commit a73cdbeff2
3 files changed
+55 -59

No files matched your search

+3 -3
View File
@@ -3,11 +3,11 @@
Matrix supports two types of calls: Matrix supports two types of calls:
- Element Call powered by [MatrixRTC](https://half-shot.github.io/msc-crafter/#msc/4143) and [LiveKit](https://github.com/livekit/livekit) - Element Call powered by [MatrixRTC](https://half-shot.github.io/msc-crafter/#msc/4143) and [LiveKit](https://github.com/livekit/livekit)
- Legacy calls, sometimes using Jitsi - Legacy calls, supported by a STUN/TURN server.
Both types of calls are supported by different sets of clients, but most clients are moving towards MatrixRTC / Element Call. Both types of calls are supported by different sets of clients, but most clients are moving towards MatrixRTC / Element Call.
For either one to work correctly, you have to do some additional setup. For either one to work correctly, you have to do some additional setup:
- For legacy calls to work, you need to set up a TURN/STUN server. [Read the TURN guide for tips on how to set up coturn](./calls/turn.mdx) - For legacy calls to work, you need to set up a TURN/STUN server. [Read the TURN guide for tips on how to set up coturn](./calls/turn.mdx)
- For MatrixRTC / Element Call to work, you have to set up the LiveKit backend (foci). LiveKit also uses TURN/STUN to increase reliability - you can set up its built-in TURN server, or integrate with an existing one. [Read the LiveKit guide](./calls/livekit.mdx) - For MatrixRTC / Element Call to work, you have to set up the LiveKit backend. LiveKit also uses TURN/STUN to increase reliability - you can set up its built-in TURN server, or integrate with an existing one. [Read the LiveKit guide](./calls/livekit.mdx)
+23 -14
View File
@@ -1,8 +1,6 @@
# Matrix RTC/Element Call Setup # Matrix RTC/Element Call Setup
:::info
This guide assumes that you are using docker compose for deployment. LiveKit only provides Docker images. This guide assumes that you are using docker compose for deployment. LiveKit only provides Docker images.
:::
:::tip :::tip
You can find help setting up MatrixRTC in our dedicated room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org) You can find help setting up MatrixRTC in our dedicated room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org)
@@ -104,6 +102,12 @@ foci = [
] ]
``` ```
If you configure Continuwuity via environment variables, use the following:
```bash
CONTINUWUITY_MATRIX_RTC__FOCI=[{ type = "livekit", livekit_service_url = "https://livekit.example.com" }]
```
This will expose LiveKit information on the following endpoints for clients to discover: This will expose LiveKit information on the following endpoints for clients to discover:
- `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` (MSC4143 unstable, behind auth) - `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` (MSC4143 unstable, behind auth)
@@ -441,7 +445,7 @@ Other:
### Additional TURNS-over-443 configuration ### Additional TURNS-over-443 configuration
In most situations, LiveKit [does not need TURN][sspaeth-matrix-voip-turn] to function. However, when clients are in very restrictive networks where UDP traffic and non-standard ports are disallowed, a TURN-over-TLS server on port `:443` could be employed to relay traffic. Most of the time, LiveKit [**does not need TURN**][sspaeth-matrix-voip-turn] to function. However, there are situations where clients are in very restrictive networks that disallows non-standard ports and UDP. In these cases, a TURN-over-TLS server on port :443 could be employed to relay traffic for them.
[sspaeth-matrix-voip-turn]: https://sspaeth.de/2026/04/matrix-voip-and-livekit/#turn [sspaeth-matrix-voip-turn]: https://sspaeth.de/2026/04/matrix-voip-and-livekit/#turn
@@ -457,43 +461,48 @@ First, set up LiveKit's built-in TURN server with its own domain - we'll use `li
## add this to `livekit.yaml` ## ## add this to `livekit.yaml` ##
turn: turn:
enabled: true enabled: true
# note: the TLS port will always be advertised as :443
tls_port: 5349 tls_port: 5349
# optional: configure an extra UDP port on :3478
# udp_port: 3478
relay_range_start: 50300 relay_range_start: 50300
relay_range_end: 50400 relay_range_end: 50400
domain: livekit-turn.example.com domain: livekit-turn.example.com
# replace these with your actual cert/key files # replace these with your actual cert/key files
cert_file: /path/to/livekit-turn.example.com.crt cert_file: /path/to/livekit-turn.example.com.crt
key_file: /path/to/livekit-turn.example.com.key key_file: /path/to/livekit-turn.example.com.key
``` ```
```yaml ```yaml
### add these to livekit's docker-compose ### ### add these ports to livekit's docker-compose ###
### if you're using `network_mode: host`, you can skip this part
ports: ports:
- "127.0.0.1:5349:5349/tcp" - "127.0.0.1:5349:5349/tcp"
- "50300-50400:50300-50400/udp" - "50300-50400:50300-50400/udp"
### if you're using `network_mode: host`, you can skip this part # "3478:3478/udp" # (optional UDP port)
``` ```
Recreate the LiveKit container (with `docker-compose up -d livekit`) to apply these changes. Remember to allow the new `50300:50400/udp` ports through your firewall. Recreate the LiveKit container (with `docker-compose up -d livekit`) to apply these changes. Remember to allow the new `50300:50400/udp` ports through your firewall.
Then, we will configure a route from port 443 of the host back to our `livekit-turn.example.com` service on port 5349. To both **multiplex** this and LiveKit's websocket on the same port, we will use a layer-4 reverse proxy with **SNI routing** capabilities, such as [caddy-l4][caddy-l4]. Then, we will configure a route from port 443 of the host back to our `livekit-turn.example.com` service on port 5349. To both **multiplex** this and LiveKit's websocket on the same port, we will use a layer-4 reverse proxy with **SNI routing** capabilities, such as [caddy-l4][caddy-l4] on the host system.
``` ```
## in your Caddyfile ## ## in your Caddyfile ##
{ {
servers { servers {
listener_wrappers { listener_wrappers {
# intercept packets meant for the TURN domain first # intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners # before forwarding other packets to "normal" HTTP listeners
layer4 { layer4 {
@turn { @turn tls sni livekit-turn.example.com
tls {
sni livekit-turn.example.com
}
}
route @turn { route @turn {
proxy { proxy 127.0.0.1:5349 # forward to normal TURNS port
upstream 127.0.0.1:5349 # forward to normal TURNS port
} }
} }
} }
@@ -517,7 +526,7 @@ https://livekit.example.com {
</details> </details>
<details> <details>
<summary>Using an external TURN server</summary> <summary>Using an external TURN server (coturn)</summary>
Before continuing, make sure coturn's `min-port` and `max-port` do not overlap with LiveKit's port range: Before continuing, make sure coturn's `min-port` and `max-port` do not overlap with LiveKit's port range:
+29 -42
View File
@@ -2,7 +2,11 @@
[TURN][turn] and [STUN][stun] are used as a component in many calling systems. Matrix uses them directly for legacy calls and indirectly for MatrixRTC via Livekit. [TURN][turn] and [STUN][stun] are used as a component in many calling systems. Matrix uses them directly for legacy calls and indirectly for MatrixRTC via Livekit.
Continuwuity recommends using [Coturn][coturn] as your TURN/STUN server, which is available as a Docker image or a distro package. Continuwuity recommends using [Coturn][coturn] as your TURN/STUN server, which is available as a Docker image or a distro package. This guide assumes that you are using docker compose for deployment.
:::tip
You can find help setting up TURN/STUN in our MatrixRTC room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org)
:::
[turn]: https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT [turn]: https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT
[stun]: https://en.wikipedia.org/wiki/STUN [stun]: https://en.wikipedia.org/wiki/STUN
@@ -50,8 +54,6 @@ Next, we will start the Coturn container with the [official image][coturn-image]
[coturn-image]: https://hub.docker.com/r/coturn/coturn [coturn-image]: https://hub.docker.com/r/coturn/coturn
[coturn-docker-docs]: https://github.com/coturn/coturn/blob/master/docker/coturn/README.md#why-so-many-ports-opened [coturn-docker-docs]: https://github.com/coturn/coturn/blob/master/docker/coturn/README.md#why-so-many-ports-opened
#### With Docker Compose (recommended)
Create a `docker-compose.yml` file as follows and run `docker compose up -d`: Create a `docker-compose.yml` file as follows and run `docker compose up -d`:
```yaml ```yaml
@@ -68,15 +70,6 @@ services:
- /path/to/certs:/etc/letsencrypt - /path/to/certs:/etc/letsencrypt
``` ```
#### With Docker
```bash
docker run -d --network=host \
-v $(pwd)/coturn.conf:/etc/coturn/turnserver.conf \
-v /path/to/certs:/etc/letsencrypt # replace this with actual paths to your certificates
coturn/coturn
```
### 4. Opening ports ### 4. Opening ports
By default, coturn uses the following ports: By default, coturn uses the following ports:
@@ -165,9 +158,9 @@ You should receive a response like this:
"username": "1752792167:@jade:example.com", "username": "1752792167:@jade:example.com",
"password": "KjlDlawdPbU9mvP4bhdV/2c/h65=", "password": "KjlDlawdPbU9mvP4bhdV/2c/h65=",
"uris": [ "uris": [
"turns:coturn.example.com?transport=tcp", "turns:coturn.example.com:3478?transport=tcp",
"turn:coturn.example.com?transport=udp", "turn:coturn.example.com:3478?transport=udp",
"turn:coturn.example.com?transport=tcp" "turn:coturn.example.com:5349?transport=tcp"
], ],
"ttl": 86400 "ttl": 86400
} }
@@ -187,10 +180,13 @@ If you see `relay` candidates in the results, your TURN/STUN server is working c
## Troubleshooting ## Troubleshooting
To gather debug logs while troubleshooting Coturn, add `verbose` to your `coturn.conf`. You can then view these logs with `docker-compose logs --follow coturn`.
### Errors with Trickle ICE ### Errors with Trickle ICE
- `code=701` - the TURN server is not reachable - `code=701` - the TURN server is not reachable
- Verify firewall rules allow the necessary ports (3478, 5349, and your media port range) - Verify firewall rules allow the necessary ports (3478, 5349, and your media port range)
- Verify via logs that coturn is exposed on the correct addresses and interfaces
- Check that DNS resolves correctly for your TURN domain - Check that DNS resolves correctly for your TURN domain
- `code=401` - unauthorized credentials - `code=401` - unauthorized credentials
- Ensure your `turn_secret` matches coturn's `static-auth-secret` - Ensure your `turn_secret` matches coturn's `static-auth-secret`
@@ -227,11 +223,11 @@ If you instead prefer to use [eturnal][eturnal], you can refer to the guides bel
### TURNS-over-443 ### TURNS-over-443
In very restrictive networks where UDP traffic and non-standard ports are disallowed, normal TURN servers are not reachable. To establish connectivity in these scenarios, a common solution is to host a TURN-over-TLS server on port 443, and allow clients to connect to it like any other web traffic. Normally, TURN would work on their default setups. However, there are situations where clients are in very restrictive networks that disallows non-standard ports and UDP. In these cases, a TURN-over-TLS server on port :443 could be employed to relay traffic for them.
However, port 443 is usually utilized by other HTTPS services. Therefore, one would need to **multiplex** both the TURN and the HTTPS services, and filter packets to them via **SNI routing**. A layer-4 load balancer such as caddy-l4 can serve this function. However, port 443 is usually utilized by other HTTPS services. Therefore, one would need to **multiplex** both TURN HTTPS on these ports, and filter packets to them via **SNI routing**.
Below are Caddyfile examples to multiplex both the TURNS service and LiveKit on port 443. It requires the [caddy-l4][caddy-l4] plugin to be compiled with your Caddy binary. Below are examples to multiplex Coturn and [LiveKit](./livekit.mdx) on port 443, using [caddy-l4][caddy-l4] on the host system.
<details> <details>
@@ -248,20 +244,16 @@ Please note that all traffic from Coturn's perspective will be coming from caddy
{ {
servers { servers {
listener_wrappers { listener_wrappers {
# intercept packets meant for the TURN domain first # intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners # before forwarding other packets to "normal" HTTP listeners
layer4 { layer4 {
@turn { @turn tls sni turn.example.com
tls {
sni turn.example.com
}
}
route @turn { route @turn {
proxy { proxy 127.0.0.1:5349 # forward to normal TURNS port
upstream 127.0.0.1:5349 # forward to normal TURNS port
}
} }
} }
tls tls
} }
} }
@@ -296,7 +288,6 @@ First, enable coturn's PROXY-protocol accepting port by adding this:
```ini ```ini
# in coturn.conf # in coturn.conf
tcp-proxy-port=5555 tcp-proxy-port=5555
``` ```
Then, in the Caddyfile: Then, in the Caddyfile:
@@ -305,14 +296,12 @@ Then, in the Caddyfile:
{ {
servers { servers {
listener_wrappers { listener_wrappers {
# intercept packets meant for the TURN domain first # intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners # before forwarding other packets to "normal" HTTP listeners
layer4 { layer4 {
@turn { @turn tlssni turn.example.com
tls {
sni turn.example.com
}
}
route @turn { route @turn {
tls # terminate TLS for the turn.example.com packets tls # terminate TLS for the turn.example.com packets
proxy { proxy {
@@ -320,7 +309,6 @@ Then, in the Caddyfile:
upstream 127.0.0.1:5555 upstream 127.0.0.1:5555
proxy_protocol v2 proxy_protocol v2
} }
} }
} }
tls tls
@@ -337,27 +325,30 @@ https://livekit.example.com {
reverse_proxy http://127.0.0.1:7880 reverse_proxy http://127.0.0.1:7880
} }
# placeholder block to obtain certs for turn.example.com
# placeholder server block to obtain certs for turn.example.com
https://turn.example.com { https://turn.example.com {
respond "OK" 200 respond "OK" 200
} }
``` ```
**Note**: the setup will disable TURN-over-TLS functionality on port 5349/tcp.
</details> </details>
After configuration and spin-up, the destination `turns:turn.example.com:443?transport=tcp` should work with Trickle ICE tests. You can now advertise it as an address in your `turn_uris` as well as LiveKit. After configuration and spin-up, the destination `turns:turn.example.com:443?transport=tcp` should work with Trickle ICE tests. You can now advertise it as an address in your `turn_uris` as well as [LiveKit](./livekit#additional-turns-over-443-configuration).
[caddy-l4]: https://github.com/mholt/caddy-l4 [caddy-l4]: https://github.com/mholt/caddy-l4
### Unsafe TURN setups (not recommended) ### Unsafe TURN setups (not recommended)
These TURN setups are available, but **not recommended** due to security issues. They are only included for completeness.
<details> <details>
<summary>Using static credentials</summary> <summary>Using static credentials</summary>
:::caution
Static credentials are less secure than shared secrets because they don't expire and must be configured in coturn separately. It is strongly advised you use [shared secret authentication](#2-configuration).
:::
If you prefer static username/password credentials instead of shared secrets: If you prefer static username/password credentials instead of shared secrets:
```ini ```ini
@@ -382,8 +373,4 @@ turn_username = "your_username"
turn_password = "your_password" turn_password = "your_password"
``` ```
:::caution
Static credentials are less secure than shared secrets because they don't expire and must be configured in coturn separately. It is strongly advised you use shared secret authentication.
:::
</details> </details>