This guide is focused on modern approach entirely skipping outdated TURN services for media, so only modern clients like Element X are supported.
The official guide is here https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md
- rust
- go
- clang
- nginx
- mage (yet another kind of go build system)
When on Gentoo simply emerge:
emerge -av dev-lang/rust dev-lang/go sys-devel/clang www-servers/nginxAnd install mage
cd /usr/src
git clone --depth 1 https://github.com/magefile/mage
cd mage
go run bootstrap.go
mv ~/go/bin/mage /usr/local/bin/You need three services:
- Matrix API engine (chats and other except live media)
- SFU
- RTC auth service
cd /usr/src
git clone --depth 1 https://github.com/matrix-construct/tuwunel.git
cd tuwunel
LIBCLANG_PATH=/usr/lib/llvm/21/lib64/ cargo build --release --jobs 2
install -Dm755 target/release/tuwunel /usr/local/bin/tuwunelInherit default config
cp tuwunel-example.toml /etc/tuwunel.toml Change these values
< #server_name =
> server_name = "matrix.your.domain"
< #unix_socket_path =
> unix_socket_path = "/run/tuwunel/tuwunel.sock"
< #[global.well_known]
> [global.well_known]
< #client =
> client = "https://matrix.your.domain"
< #server =
> server = "matrix.your.domain:443"
< #rtc_transports = []
> rtc_transports = [{ type = "livekit", livekit_service_url = "https://matrix.your.domain/livekit/jwt" }]Additionally, allow registration for the first (admin) user, disable later
< #allow_registration = false
> allow_registration = true
< #registration_token =
> registration_token = "some_secret_token_to_register_users"cat << 'EOF' > /etc/init.d/tuwunel
#!/sbin/openrc-run
name="Tuwunel Matrix homeserver"
command="/usr/local/bin/tuwunel"
command_args="-c /etc/tuwunel.toml"
command_background=true
pidfile="/run/${RC_SVCNAME}.pid"
command_user="tuwunel:nginx"
directory="/var/lib/tuwunel"
export TOKIO_WORKER_THREADS=4
logfile="/var/log/${RC_SVCNAME}.log"
output_log="${logfile}"
error_log="${logfile}"
start_pre() {
checkpath --file --owner $command_user --mode 0644 "${logfile}"
checkpath --directory --owner $command_user -m 0750 /run/${RC_SVCNAME}
}
EOF
chmod +x /etc/init.d/tuwuneluseradd -r -u 501 -s/sbin/nologin -d/var/lib/tuwunel tuwunel
mkdir -p /var/lib/tuwunel
chown tuwunel:tuwunel /var/lib/tuwunel
chmod 0750 /var/lib/tuwunelrc-update add tuwunel default
rc-service tuwunel startCheck logs
cat /var/log/tuwunel.logcd /usr/src
git clone --depth 1 https://github.com/livekit/livekit-server.git
cd livekit-server
go mod download
./install-livekit.shcat << 'EOF' > /etc/livekit.yaml
port: 7880
bind_addresses:
- "127.0.0.1"
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 50100
# use_external_ip: true # when behind NAT
node_ip: 1.2.3.4 # direct
keys:
element: <super_secret_key>
room:
auto_create: false
EOF
chown chown livekit:livekit /etc/livekit.yaml
chmod 0600 /etc/livekit.yamlMore options here: https://github.com/livekit/livekit/blob/master/config-sample.yaml
cat << 'EOF' > /etc/init.d/livekit
#!/sbin/openrc-run
name="LiveKit RTC server"
command="/usr/local/bin/livekit-server"
command_args="--config /etc/livekit.yaml --dev"
command_background=true
pidfile="/run/${RC_SVCNAME}.pid"
command_user="livekit:livekit"
directory="/var/lib/livekit"
logfile="/var/log/${RC_SVCNAME}.log"
output_log="${logfile}"
error_log="${logfile}"
start_pre() {
checkpath --file --owner $command_user --mode 0644 "${logfile}"
}
EOF
chmod +x /etc/init.d/livekituseradd -r -u 502 -s/sbin/nologin -d/var/lib/livekit livekit
mkdir -p /var/lib/livekit
chown livekit:livekit /var/lib/livekit
chmod 0750 /var/lib/livekitrc-update add livekit default
rc-service livekit startCheck logs
cat /var/log/livekit.loggit clone https://github.com/element-hq/lk-jwt-service.git
cd lk-jwt-service
go build -o lk-jwt-service
install -Dm755 lk-jwt-service /usr/local/bin/lk-jwt-serviceDon't be lazy and separate configuration variables to
/etc/conf.d/lk-jwt
cat << 'EOF' > /etc/init.d/lk-jwt
#!/sbin/openrc-run
name="LiveKit JWT Auth service"
command="/usr/local/bin/lk-jwt-service"
command_background=true
pidfile="/run/${RC_SVCNAME}.pid"
command_user="livekit:livekit"
directory="/var/lib/livekit"
export LIVEKIT_URL="wss://matrix.your.domain/livekit/sfu"
export LIVEKIT_KEY="element"
export LIVEKIT_SECRET="<super_secret_key>"
export LIVEKIT_FULL_ACCESS_HOMESERVERS="matrix.your.domain"
export LIVEKIT_JWT_BIND="127.0.0.1:7882"
logfile="/var/log/${RC_SVCNAME}.log"
output_log="${logfile}"
error_log="${logfile}"
start_pre() {
checkpath --file --owner $command_user --mode 0644 "${logfile}"
}
EOF
chmod 0750 /etc/init.d/lk-jwt # prevent access to the LIVEKIT_SECRETrc-update add lk-jwt default
rc-service lk-jwt startCheck logs
cat /var/log/lk-jwt.logAdd this server config to nginx
# Matrix homeserver reverse proxy
server {
listen 0.0.0.0:443 ssl;
listen [::]:443 ssl;
http2 on;
server_name matrix.your.domain;
ssl_certificate /etc/letsencrypt/live/your.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.domain/privkey.pem;
access_log /var/log/nginx/matrix.your.domain.ssl_access_log main;
error_log /var/log/nginx/matrix.your.domain.ssl_error_log info;
# LiveKit JWT auth endpoint -- proxy to lk-jwt http port
location ^~ /livekit/jwt/ {
proxy_pass http://127.0.0.1:7882/;
proxy_set_header Host $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 SFU websocket connection running at port 7880
location ^~ /livekit/sfu/ {
proxy_pass http://127.0.0.1:7880/;
proxy_set_header Host $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;
proxy_send_timeout 120;
proxy_read_timeout 120;
proxy_buffering off;
proxy_set_header Accept-Encoding gzip;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Matrix API -- proxy to tuwunel unix socket
location / {
proxy_pass http://unix:/run/tuwunel/tuwunel.sock;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Reload nginx config after adding new endpoints.