diff --git a/docs/matrix_rtc.md b/docs/matrix_rtc.md new file mode 100644 index 00000000..a941ca1f --- /dev/null +++ b/docs/matrix_rtc.md @@ -0,0 +1,215 @@ +This is a basic "step by step" guide to setting up Element Call/MatrixRTC for Tuwunel. The aim is to provide the minimum amount of information necessary to get Element Call working, in a way that can be followed by anyone regardless of technical experience. Each step provides a brief description of what it is doing, followed by a suggested command to complete it. +This guide is inspired by [this blog post](https://sspaeth.de/2024/11/sfu/). For further information on setting up Element Call, please refer to that guide. + +***The following is very much based on my own experience of setting up Element Call for Tuwunel. Any amendments or additions are gratefully received.*** + +## Requirements +- A Linux server. +- A working Tuwunel installation. +- Docker and Docker Compose installed on the server. +- A Caddy or Nginx reverse proxy. +- A basic knowledge of how the above components work. + +## Notes +- My installation is on a Debian server. These instructions should work on other distributions, but I may have missed something. +- I use Caddy as a reverse proxy, and my Nginx knowledge is a bit rusty, so there is a chance that there are errors in the Nginx configuration provided. +- `yourdomain.com` is whatever you have set as `server_name` in your tuwunel.toml. This needs to be replaced with the actual domain. It is assumed that you will be hosting MatrixRTC at `matrix-rtc.yourdomain.com`. If you wish to host this service at a different subdomain, this needs to be replaced as well. + +## 1. Set Up DNS +Create a DNS record for `matrix-rtc.yourdomain.com` pointing to your server. + +e.g. an `A` record for `matrix-rtc` pointing to `your.server.ip.address`. + +## 2. Create Docker Containers +1. Create a directory for your MatrixRTC setup: `mkdir /opt/matrix-rtc`. +2. Change directory to your new directory: `cd /opt/matrix-rtc`. +3. Create and open a compose.yaml file for MatrixRTC: `nano compose.yaml`. +4. Add the following. `mrtckey` and `mrtcsecret` should be random strings. It is suggested that `mrtckey` is 20 characters and `mrtcsecret` is 64 characters. +```yaml +services: + matrix-rtc-jwt: + image: ghcr.io/element-hq/lk-jwt-service:latest + container_name: matrix-rtc-jwt + environment: + - LIVEKIT_JWT_PORT=8081 + - LIVEKIT_URL=https://matrix-rtc.yourdomain.com/livekit/sfu + - LIVEKIT_KEY=mrtckey + - LIVEKIT_SECRET=mrtcsecret + - LIVEKIT_FULL_ACCESS_HOMESERVERS=yourdomain.com + restart: unless-stopped + ports: + - "8081:8081" + + matrix-rtc-livekit: + image: livekit/livekit-server:latest + container_name: matrix-rtc-livekit + command: --config /etc/livekit.yaml + ports: + - 7880:7880/tcp + - 7881:7881/tcp + - 50100-50200:50100-50200/udp + restart: unless-stopped + volumes: + - ./livekit.yaml:/etc/livekit.yaml:ro +``` +4. Close the file: `Ctrl+x`. +5. Create and open a livekit.yaml file: `nano livekit.yaml`. +6. Add the following. `mrtckey` and `mrtcsecret` should be the same as those from the compose.yaml. +```yaml +port: 7880 +bind_addresses: + - "" +rtc: + tcp_port: 7881 + port_range_start: 50100 + port_range_end: 50200 + use_external_ip: true + enable_loopback_candidate: false +keys: + mrtckey: "mrtcsecret" +``` +7. Close the file: `Ctrl+x`. + +## 3. Configure .well-known +### 3.1. .well-known served by Tuwunel +***Follow this step if your .well-known configuration is served by tuwunel. Otherwise follow Step 3.2*** +1. Open your tuwunel.toml file: e.g. `nano /etc/tuwunel/tuwunel.toml`. +2. Find the line reading `#rtc_transports = []` and edit it to be: +```toml +rtc_transports = [ + { + type = "livekit", + livekit_service_url = "https://matrix-rtc.yourdomain.com" + } +] +``` +3. Close the file: `Ctrl+x`. + +### 3.2. .well-known served independently +***Follow this step if you serve your .well-known/matrix files directly. Otherwise follow Step 3.1*** +1. Open your .well-known/matrix/client file: e.g. `nano /var//www/.well-known/matrix/client`. +2. Add the following: +```json + "org.matrix.msc4143.rtc_foci": [ + { + "type": "livekit", + "livekit_service_url": "https://matrix-rtc.yourdomain.com" + } + ] +``` +The final file should look something like this: +```json +{ + "m.homeserver": { + "base_url":"https://matrix.yourdomain.com" + }, + "org.matrix.msc4143.rtc_foci": [ + { + "type": "livekit", + "livekit_service_url": "https://matrix-rtc.yourdomain.com" + } + ] +} + +``` +3. Close the file: `Ctrl+x`. + +## 4. Configure Firewall +You will need to allow ports `7881/tcp` and `50100:50200/udp` through your firewall. If you use UFW, the commands are: `ufw allow 7881/tcp` and `ufw allow 50100:50200/udp`. + +## 5. Configure Reverse Proxy +As reverse proxies can be installed in different ways, I am not giving step by step instructions for this section. +If you use Caddy as your reverse proxy, follow step 5.1. If you use Nginx, follow step 5.2. + +### 5.1. Caddy +1. The following needs to be added to your Caddyfile. If you are running Caddy in Docker, replace `localhost` with `matrix-rtc-jwt` in the first instance, and `matrix-rtc-livekit` in the second. +``` +matrix-rtc.yourdomain.com { + # This is matrix-rtc-jwt + @jwt_service { + path /sfu/get* /healthz* + } + handle @jwt_service { + reverse_proxy localhost:8081 { + header_up Host {host} + header_up X-Forwarded-Server {host} + header_up X-Real-IP {remote} + header_up X-Forwarded-For {remote} + header_up X-Forwarded-Proto {scheme} + } + } + # This is livekit + handle { + reverse_proxy localhost:7880 { + header_up Connection "upgrade" + header_up Upgrade {http.request.header.Upgrade} + header_up Host {host} + header_up X-Forwarded-Server {host} + header_up X-Real-IP {remote} + header_up X-Forwarded-For {remote} + header_up X-Forwarded-Proto {scheme} + } + } +} +``` +2. Restart Caddy. + +### 5.2. Nginx +1. The following needs to be added to your Nginx configuration: +``` +server { + listen 443 ssl; + listen [::]:443 ssl; + http2 on; + server_name matrix-rtc.yourdomain.com; + + # Logging + access_log /var/log/nginx/matrix-rtc.yourdomain.com.log; + error_log /var/log/nginx/matrix-rtc.yourdomain.com.error; + + # TLS example for certificate obtained from Let's Encrypt. + ssl_certificate /etc/letsencrypt/live/matrix-rtc.yourdomain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/matrix-rtc.yourdomain.com/privkey.pem; + + # lk-jwt-service + location ~ ^(/sfu/get|/healthz) { + proxy_pass http://localhost:8081; + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + # livekit + location /livekit/sfu/ { + proxy_pass http://localhost:7880; + proxy_http_version 1.1; + + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Server $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Optional timeouts per LiveKit + proxy_read_timeout 300s; + proxy_send_timeout 300s; + } + + # Redirect root / at /livekit/sfu/ + location = / { + return 301 /livekit/sfu/; + } +} +``` +2. Restart Nginx. + +## 6. Start Docker Containers +1. Ensure you are in your matrix-rtc directory: `cd /opt/matrix-rtc`. +2. Start containers: `docker compose up -d`. + +Element Call should now be working.