This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:element-call [2026/10/10 01:09] – oemb1905 | computing:element-call [2026/10/10 06:03] (current) – oemb1905 | ||
|---|---|---|---|
| Line 14: | Line 14: | ||
| ==== Introduction ==== | ==== Introduction ==== | ||
| - | Rootless Podman as user '' | + | |
| + | This tutorial is for Debian users who already self-host Matrix-Synapse and need to build an Element Call instance to support | ||
| ^ Name ^ Container ^ Bind ^ Public ^ | ^ Name ^ Container ^ Bind ^ Public ^ | ||
| Line 25: | Line 26: | ||
| | TURN relay | same | '' | | TURN relay | same | '' | ||
| - | Do not use 8080, 8082, 8088, 3478, or 443. | + | Since this was the 4th container on the same instance, I need to avoid using ports 8080, 8082, 8088, 3478, and 443. I just used 3479 instead, since HPB was already using 3478. The main proxy port was also easy to adjust. |
| Images: | Images: | ||
| Line 32: | Line 33: | ||
| * '' | * '' | ||
| * '' | * '' | ||
| - | |||
| - | Do not use '' | ||
| ==== 1. DNS ==== | ==== 1. DNS ==== | ||
| - | '' | + | |
| + | Set your A/AAAA records to point at the virtual machine / OCI container host. The reverse proxy we set up later will handle the rest. | ||
| ==== 2. Firewall (root) ==== | ==== 2. Firewall (root) ==== | ||
| + | |||
| + | Here's the ufw rules I came up with: | ||
| + | |||
| < | < | ||
| - | ufw allow 3479/ | + | ufw allow 3479/udp |
| - | ufw allow 35000: | + | ufw allow 35000: |
| - | ufw allow 7881/ | + | ufw allow 7881/tcp |
| - | ufw allow 50100: | + | ufw allow 50100: |
| </ | </ | ||
| ==== 3. Secret (worker) ==== | ==== 3. Secret (worker) ==== | ||
| + | |||
| + | Let's get the secrets cut: | ||
| + | |||
| < | < | ||
| mkdir -p ~/ | mkdir -p ~/ | ||
| Line 54: | Line 60: | ||
| </ | </ | ||
| - | Key name: '' | + | ==== 4. Certificates (root) ==== |
| - | < | + | After the key and project directory are ready, we can cut the cert: |
| - | LIVEKIT_SECRET=replace-with-your-livekit-secret | + | |
| - | </ | + | |
| - | ==== 4. Certificates (root) ==== | ||
| < | < | ||
| certbot certonly --apache -d call.gnulinux.club -d webrtc.gnulinux.club | certbot certonly --apache -d call.gnulinux.club -d webrtc.gnulinux.club | ||
| a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl | a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl | ||
| </ | </ | ||
| - | |||
| - | Apache is the only process that reads these. | ||
| ==== 5. LiveKit config (worker) ==== | ==== 5. LiveKit config (worker) ==== | ||
| + | |||
| + | Let's pull the images and create our configuration files: | ||
| + | |||
| < | < | ||
| + | podman pull ghcr.io/ | ||
| + | podman pull ghcr.io/ | ||
| + | podman pull docker.io/ | ||
| + | |||
| cat > ~/ | cat > ~/ | ||
| port: 7880 | port: 7880 | ||
| Line 100: | Line 108: | ||
| </ | </ | ||
| - | '' | + | Make sure '' |
| ==== 6. Element Call config (worker) ==== | ==== 6. Element Call config (worker) ==== | ||
| - | The image serves files from ''/ | + | |
| + | The image serves files from ''/ | ||
| < | < | ||
| Line 125: | Line 134: | ||
| ==== 7. Quadlets ==== | ==== 7. Quadlets ==== | ||
| - | '' | + | |
| + | Also on the VM, make sure the quadlet is setup. You should note that '' | ||
| < | < | ||
| Line 194: | Line 204: | ||
| systemctl --user start container-element-call.service | systemctl --user start container-element-call.service | ||
| </ | </ | ||
| - | |||
| - | '' | ||
| ==== 8. Verify ==== | ==== 8. Verify ==== | ||
| + | |||
| + | Let's make sure those quadlets all function: | ||
| + | |||
| < | < | ||
| systemctl --user is-active container-livekit.service container-lk-jwt.service container-element-call.service | systemctl --user is-active container-livekit.service container-lk-jwt.service container-element-call.service | ||
| Line 206: | Line 217: | ||
| </ | </ | ||
| - | Expect | + | Here, we are looking for '' |
| ==== 9. Upgrade script ==== | ==== 9. Upgrade script ==== | ||
| - | ''/ | + | |
| + | Here's a simple upgrade script for the OCI container. Create | ||
| < | < | ||
| #!/bin/bash | #!/bin/bash | ||
| set -euo pipefail | set -euo pipefail | ||
| + | export XDG_RUNTIME_DIR=/ | ||
| + | export DBUS_SESSION_BUS_ADDRESS=unix: | ||
| podman pull docker.io/ | podman pull docker.io/ | ||
| Line 235: | Line 249: | ||
| </ | </ | ||
| - | Run it as '' | + | ==== 10. Apache (root) ==== |
| - | < | + | Now that the service is created and running, make sure dns for a/aaaa is ready and then let's cut the cert. |
| - | su - worker -c '/bin/bash / | + | |
| - | </ | + | |
| - | Do not '' | + | |
| + | sudo certbot certonly --apache -d webrtc.gnulinux.club | ||
| - | ==== 10. Apache | + | We also need to create the reverse proxy so we can forward external requests upstream to the local listening services we just created. For the cert(s) '' |
| - | ''/ | + | |
| < | < | ||
| Line 252: | Line 264: | ||
| RewriteRule ^ https:// | RewriteRule ^ https:// | ||
| </ | </ | ||
| + | </ | ||
| + | Inside '' | ||
| + | |||
| + | < | ||
| < | < | ||
| ServerName call.gnulinux.club | ServerName call.gnulinux.club | ||
| Line 266: | Line 282: | ||
| </ | </ | ||
| - | ''/ | + | Inside |
| < | < | ||
| Line 274: | Line 290: | ||
| RewriteRule ^ https:// | RewriteRule ^ https:// | ||
| </ | </ | ||
| + | </ | ||
| + | Inside '' | ||
| + | |||
| + | < | ||
| < | < | ||
| ServerName webrtc.gnulinux.club | ServerName webrtc.gnulinux.club | ||
| Line 294: | Line 314: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| + | Once that's done, let's enable them and check the endpoints: | ||
| < | < | ||
| Line 306: | Line 328: | ||
| ==== 11. Synapse (Matrix VM) ==== | ==== 11. Synapse (Matrix VM) ==== | ||
| - | No new ports. Existing HTTPS is enough. Append this at the bottom of ''/ | + | |
| + | On the Matrix VM, we need to edit '' | ||
| < | < | ||
| Line 329: | Line 352: | ||
| livekit_service_url: | livekit_service_url: | ||
| </ | </ | ||
| + | |||
| + | Then, restart the service: | ||
| < | < | ||
| Line 334: | Line 359: | ||
| </ | </ | ||
| - | Wait until it is active. A curl during those few seconds returns nginx 502. The LiveKit secret is not added here. Synapse only advertises the JWT URL. '' | + | You can test with: |
| - | + | ||
| - | This Synapse serves the unstable route only. ''/ | + | |
| - | + | ||
| - | With a real Element access token: | + | |
| < | < | ||
| Line 345: | Line 366: | ||
| </ | </ | ||
| - | The body must contain '' | + | The body of the output should |
| ==== 12. Well-known (Matrix VM) ==== | ==== 12. Well-known (Matrix VM) ==== | ||
| - | ''/ | + | |
| + | In an initial build, I left old comments/ | ||
| < | < | ||
| Line 377: | Line 399: | ||
| } | } | ||
| </ | </ | ||
| + | |||
| + | Reload service and check API endpoint: | ||
| < | < | ||
| Line 384: | Line 408: | ||
| ==== 13. Element Web ==== | ==== 13. Element Web ==== | ||
| - | In '' | + | |
| + | In '' | ||
| < | < | ||
| Line 395: | Line 420: | ||
| </ | </ | ||
| - | '' | + | That should be it. Debug and review line by line if stuff is failing. Reach out on Matrix if needed. |
| - | + | ||
| - | ==== Facts ==== | + | |
| - | * UD | + | |
| - | --- // | + | --- // |