Hosting Livekit The server part Install livekit-server and livekit-cli on a server which isn’t behind NAT .
Firstly, generate your API keys using livekit’s cli tool:
1 2 3 livekit-server generate-keys API Key: APIp2ow9ec5MJQd API Secret: CjwZBVnAeaCVebgtYyWfEjLehqjR6I5PHEkTVdUci2Q
Store these secrets in somewhere safe, like in an password manager.
Create a livekit config file using this template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 port: 7880 rtc: port_range_start: 7881 port_range_end: 17881 tcp_port: 17882 use_external_ip: false use_ice_lite: true stun_servers: - some.random.stun.server:3478 congestion_control: enabled: true allow_tcp_fallback: true keys: elecall: CjwZBVnAeaCVebgtYyWfEjLehqjR6I5PHEkTVdUci2Q logging: level: info room: enabled_codecs: - mime: audio/opus - mime: video/h264 turn: enabled: true udp_port: 3478 tls_port: 5349 external_tls: false domain: some.livekit.instance cert_file: /path/to/cert key_file: /path/to/certkey
Replace stun_servers
(remove this entry if you don’t have one), domain
, cert_file
and key_file
. If you have coturn or other software using the ports, change the livekit config as required.
Open the ports on your firewall.
Add a systemd service using systemctl edit --force --full livekit
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 [Unit] Description="LiveKit: Real-time video, audio and data for developers" After=network.target Conflicts=livekit.service Documentation=https://docs.livekit.io/home/ [Service] ExecStart=livekit-server --config /path/to/config.yaml --node-ip your.ip.address Restart=always RestartSec=5 TimeoutStopSec=4m TimeoutStartSec=4m StartLimitInterval=1m StartLimitBurst=5 AmbientCapabilities= CapabilityBoundingSet= DevicePolicy=closed LockPersonality=yes MemoryDenyWriteExecute=yes NoNewPrivileges=yes ProcSubset=pid ProtectClock=yes ProtectControlGroups=yes #ProtectHome=yes ProtectHostname=yes ProtectKernelLogs=yes ProtectKernelModules=yes ProtectKernelTunables=yes ProtectProc=invisible ProtectSystem=strict PrivateDevices=yes PrivateMounts=yes PrivateTmp=yes PrivateIPC=yes RemoveIPC=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes SystemCallFilter=~@clock @debug @module @mount @reboot @swap @cpu-emulation @obsolete @timer @chown @setuid @privileged @keyring SystemCallErrorNumber=EPERM [Install] WantedBy=multi-user.target
At the very least, replace /path/to/config.yaml and your.ip.address , then start livekit.service
.
Reverse proxy We’ll take NGINX for an example. Add a new server block as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server { ssl_certificate /path/to/cert; ssl_certificate_key /path/to/certkey; ssl_prefer_server_ciphers off ; ssl_protocols TLSv1.2 TLSv1.3 ; add_header Strict-Transport-Security "max-age=63072000" always; ssl_stapling on ; ssl_stapling_verify on ; resolver 127.0.0.1 ; error_page 497 https://$host ; listen 443 ssl; server_name some.livekit.instance.domain; client_max_body_size 10M ; location / { proxy_pass http://localhost:7880/; proxy_set_header Host your.ip.address; proxy_pass_header Authorization; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_http_version 1 .1 ; proxy_set_header Upgrade $http_upgrade ; proxy_set_header Connection "upgrade" ; } }
Change your.ip.address
, some.livekit.instance.domain
accordingly, and reload your reverse proxy.
Hosting Livekit JWT Create a systemd service:
1 systemctl edit --force --full lk-jwt-service.service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 [Unit] Description="LiveKit Management Service" After=network.target [Service] DynamicUser=yes Environment=LIVEKIT_URL="wss://some.livekit.instance.domain" Environment=LK_JWT_PORT="27881" Environment=LIVEKIT_KEY='elecall' Environment=LIVEKIT_SECRET="CjwZBVnAeaCVebgtYyWfEjLehqjR6I5PHEkTVdUci2Q" Environment=HOMESERVER_URL="https://matrix.example.org" ExecStart=lk-jwt-service Restart=on-failure RestartSec=5 TimeoutStopSec=4m TimeoutStartSec=4m StartLimitInterval=1m StartLimitBurst=5 AmbientCapabilities= CapabilityBoundingSet= DevicePolicy=closed LockPersonality=yes MemoryDenyWriteExecute=yes NoNewPrivileges=yes ProcSubset=pid ProtectClock=yes ProtectControlGroups=yes ProtectHome=yes ProtectHostname=yes ProtectKernelLogs=yes ProtectKernelModules=yes ProtectKernelTunables=yes ProtectProc=invisible ProtectSystem=strict PrivateDevices=yes PrivateMounts=yes PrivateTmp=yes PrivateUsers=yes PrivateIPC=yes RemoveIPC=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes SystemCallFilter=~@clock @debug @module @mount @reboot @swap @cpu-emulation @obsolete @timer @chown @setuid @privileged @keyring SystemCallErrorNumber=EPERM [Install] WantedBy=multi-user.target
Change LIVEKIT_URL
, LIVEKIT_SECRET
and HOMESERVER_URL
accordingly, then enable & start lk-jwt-service.service
.
Add a new server block in Nginx config:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server { access_log off ; ssl_certificate /var/tmp/fullchain; ssl_certificate_key /var/tmp/privkey; ssl_prefer_server_ciphers off ; ssl_protocols TLSv1.3 ; add_header Strict-Transport-Security "max-age=63072000" always; ssl_stapling on ; ssl_stapling_verify on ; resolver 127.0.0.1 ; error_page 497 https://$host ; listen 443 ssl; server_name lk-jwt.example.com; client_max_body_size 10M ; location / { proxy_pass http://localhost:27881/; proxy_set_header Host $http_host ; proxy_pass_header Authorization; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; } }
Replace server_name
, ssl_certificate
, ssl_certificate_key
.
Install aur/element-call or whatever your distro provides.
Add a server block into Nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 server { listen 443 ssl; server_name widget.element.call; ssl_certificate /var/tmp/fullchain; ssl_certificate_key /var/tmp/privkey; ssl_prefer_server_ciphers off ; ssl_protocols TLSv1.3 ; add_header Strict-Transport-Security "max-age=63072000" always; ssl_stapling on ; ssl_stapling_verify on ; resolver 127.0.0.1 ; error_page 497 https://$host ; root /usr/share/webapps/element-call; location / { add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0' ; if_modified_since off ; expires off ; add_header Last-Modified "" ; try_files $uri /$uri /index.html; } location /assets { expires 1w ; add_header Cache-Control "public, no-transform" ; } location /apple-app-site-association { default_type application/json; } }
Replace server_name
, widget.element.call
, ssl_certificate
, ssl_certificate_key
. And add a new well-known file to your matrix domain: /.well-known/element/element.json
1 { "call" : { "widget_url" : "https://widget.element.call" } }
Modifying well-known Modify your Matrix client well-known like the following text:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "m.homeserver" : { "base_url" : "https://matrix.example.org/" } , "org.matrix.msc3575.proxy" : { "url" : "https://matrix.example.org/" } , "org.matrix.msc4143.rtc_foci" : [ { "type" : "livekit" , "livekit_service_url" : "https://lk-jwt.example.com" } ] }
Replace those URLs!
After those modifications, we should be all set.