diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a34ac713..268933cfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 2026-02-21 + +## LiveKit TURN TLS can now be fronted by playbook-managed Traefik + +For deployments that use the playbook-managed Traefik reverse-proxy, LiveKit TURN over TCP is now SSL-terminated at Traefik and passed as plain TCP to LiveKit (`turn.external_tls = true`) by default. + +If you are using `other-traefik-container` or [another reverse-proxy](./configuring-playbook-own-webserver.md), this change does **not** switch behavior automatically. That mode remains using certificate files in the container (Traefik certificates dumper flow) unless you explicitly set the TURN-Traefik mode variables to opt in. + # 2026-02-17 ## (BC Break) prometheus-nginxlog-exporter role has been relocated and variable names need adjustments diff --git a/docs/configuring-playbook-livekit-server.md b/docs/configuring-playbook-livekit-server.md index 3579feb56..395f391d4 100644 --- a/docs/configuring-playbook-livekit-server.md +++ b/docs/configuring-playbook-livekit-server.md @@ -31,6 +31,26 @@ To ensure LiveKit Server functions correctly, the following firewall rules and p 💡 The suggestions above are inspired by the upstream [Ports and Firewall](https://docs.livekit.io/home/self-hosting/ports-firewall/) documentation based on how LiveKit is configured in the playbook. If you've using custom configuration for the LiveKit Server role, you may need to adjust the firewall rules accordingly. +## TURN TLS handling + +When `matrix_playbook_reverse_proxy_type` is `playbook-managed-traefik` (which is the default for this playbook), TURN over TCP is terminated by Traefik and forwarded to LiveKit with `turn.external_tls = true`. In this playbook default, this mode is enabled automatically when SSL is enabled and TURN is enabled. + +- The playbook installs a dedicated Traefik TCP entrypoint for TURN (`matrix-livekit-turn`) by default and binds it to `tcp/5350`. +- `livekit_server_config_turn_external_tls` is automatically enabled for this setup. +- Because Traefik handles TLS, LiveKit no longer needs certificate-file paths for TURN in this mode. + +If your setup uses `other-traefik-container` or [another reverse-proxy](./configuring-playbook-own-webserver.md), behavior is unchanged by default and still relies on certificates being available inside the container as before. + +Deployments using `other-traefik-container` can opt into the same Traefik-terminated mode there, by setting: + +```yml +livekit_server_config_turn_external_tls: true +livekit_server_container_labels_turn_traefik_enabled: true +livekit_server_container_labels_turn_traefik_entrypoints: "" +``` + +and configuring their own Traefik TCP entrypoint dedicated to LiveKit TURN traffic. + ## Limitations For some reason, LiveKit Server's TURN ports (`3479/udp` and `5350/tcp`) are not reachable over IPv6 regardless of whether you've [enabled IPv6](./configuring-ipv6.md) for your server. diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index a9ecfaaad..e980cd99a 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -5944,6 +5944,8 @@ traefik_additional_entrypoints_auto: | ([matrix_playbook_public_matrix_federation_api_traefik_entrypoint_definition] if matrix_playbook_public_matrix_federation_api_traefik_entrypoint_enabled else []) + ([matrix_playbook_internal_matrix_client_api_traefik_entrypoint_definition] if matrix_playbook_internal_matrix_client_api_traefik_entrypoint_enabled else []) + + + ([matrix_playbook_livekit_turn_traefik_entrypoint_definition] if matrix_playbook_livekit_turn_traefik_entrypoint_enabled else []) }} traefik_config_providers_docker_endpoint: "{{ container_socket_proxy_endpoint if container_socket_proxy_enabled else 'unix:///var/run/docker.sock' }}" @@ -6103,6 +6105,11 @@ livekit_server_container_image_registry_prefix_upstream: "{{ matrix_container_gl livekit_server_container_network: "{{ matrix_addons_container_network }}" livekit_server_container_additional_networks_auto: "{{ [matrix_playbook_reverse_proxyable_services_additional_network] if (livekit_server_container_labels_traefik_enabled and matrix_playbook_reverse_proxyable_services_additional_network) else [] }}" +# We expose LiveKit TURN/TLS via Traefik on a dedicated TCP entrypoint. +matrix_playbook_livekit_turn_traefik_entrypoint_enabled: "{{ matrix_playbook_reverse_proxy_type == 'playbook-managed-traefik' and livekit_server_config_turn_enabled and livekit_server_config_turn_external_tls and livekit_server_container_labels_traefik_enabled }}" +matrix_playbook_livekit_turn_traefik_entrypoint_port: "{{ livekit_server_config_turn_tls_port }}" +matrix_playbook_livekit_turn_traefik_entrypoint_host_bind_port: "{{ (matrix_playbook_service_host_bind_interface_prefix ~ (matrix_playbook_livekit_turn_traefik_entrypoint_port | string)) if matrix_playbook_service_host_bind_interface_prefix else (matrix_playbook_livekit_turn_traefik_entrypoint_port | string) }}" + livekit_server_container_additional_volumes_auto: | {{ ( @@ -6117,7 +6124,7 @@ livekit_server_container_additional_volumes_auto: | 'dst': livekit_server_config_turn_key_file, 'options': 'ro', }, - ] if (matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and traefik_certs_dumper_enabled and livekit_server_config_turn_enabled and (livekit_server_config_turn_cert_file and livekit_server_config_turn_key_file)) else [] + ] if (matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and traefik_certs_dumper_enabled and livekit_server_config_turn_enabled and not (livekit_server_config_turn_external_tls | bool) and (livekit_server_config_turn_cert_file and livekit_server_config_turn_key_file)) else [] ) }} @@ -6125,6 +6132,9 @@ livekit_server_container_labels_traefik_enabled: "{{ matrix_playbook_reverse_pro livekit_server_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}" livekit_server_container_labels_traefik_entrypoints: "{{ traefik_entrypoint_primary }}" livekit_server_container_labels_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}" +livekit_server_container_labels_turn_traefik_enabled: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_enabled }}" +livekit_server_container_labels_turn_traefik_entrypoints: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_name }}" +livekit_server_container_labels_turn_traefik_tls_certResolver: "{{ traefik_certResolver_primary }}" livekit_server_container_labels_public_metrics_middleware_basic_auth_enabled: "{{ matrix_metrics_exposure_http_basic_auth_enabled }}" livekit_server_container_labels_public_metrics_middleware_basic_auth_users: "{{ matrix_metrics_exposure_http_basic_auth_users }}" @@ -6163,15 +6173,19 @@ livekit_server_config_turn_tls_port: 5350 # Note that TURN is not enabled by default. See `livekit_server_config_turn_enabled`. livekit_server_config_turn_udp_port: 3479 -# LiveKit's TURN implementation requires SSL certificates. -# We only enable it if we can provide them automatically via Traefik + Traefik Certs Dumper. -livekit_server_config_turn_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and traefik_certs_dumper_enabled }}" +# In this mode, Traefik terminates TURN/TLS and forwards plaintext TCP to LiveKit's `turn.tls_port`. +# We only enable it automatically when Traefik is managed by this playbook. +livekit_server_config_turn_external_tls: "{{ matrix_playbook_reverse_proxy_type == 'playbook-managed-traefik' and matrix_playbook_ssl_enabled }}" +# TURN stays enabled for either mode: +# - external TLS termination by playbook-managed Traefik +# - in-container TLS using certificates from Traefik Certs Dumper +livekit_server_config_turn_enabled: "{{ matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and (livekit_server_config_turn_external_tls or traefik_certs_dumper_enabled) }}" livekit_server_config_turn_cert_file: |- {{ { - 'playbook-managed-traefik': ('/certificate.crt' if traefik_certs_dumper_enabled else ''), - 'other-traefik-container': ('/certificate.crt' if traefik_certs_dumper_enabled else ''), + 'playbook-managed-traefik': ('/certificate.crt' if traefik_certs_dumper_enabled and not (livekit_server_config_turn_external_tls | bool) else ''), + 'other-traefik-container': ('/certificate.crt' if traefik_certs_dumper_enabled and not (livekit_server_config_turn_external_tls | bool) else ''), 'none': '', }[matrix_playbook_reverse_proxy_type] }} @@ -6179,15 +6193,15 @@ livekit_server_config_turn_cert_file: |- livekit_server_config_turn_key_file: |- {{ { - 'playbook-managed-traefik': ('/privatekey.key' if traefik_certs_dumper_enabled else ''), - 'other-traefik-container': ('/privatekey.key' if traefik_certs_dumper_enabled else ''), + 'playbook-managed-traefik': ('/privatekey.key' if traefik_certs_dumper_enabled and not (livekit_server_config_turn_external_tls | bool) else ''), + 'other-traefik-container': ('/privatekey.key' if traefik_certs_dumper_enabled and not (livekit_server_config_turn_external_tls | bool) else ''), 'none': '', }[matrix_playbook_reverse_proxy_type] }} livekit_server_systemd_required_services_list_auto: | {{ - ([traefik_certs_dumper_identifier + '-wait-for-domain@' + livekit_server_config_turn_domain + '.service'] if matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and traefik_certs_dumper_enabled and livekit_server_config_turn_enabled else []) + ([traefik_certs_dumper_identifier + '-wait-for-domain@' + livekit_server_config_turn_domain + '.service'] if matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] and traefik_certs_dumper_enabled and livekit_server_config_turn_enabled and not (livekit_server_config_turn_external_tls | bool) else []) }} ######################################################################## diff --git a/requirements.yml b/requirements.yml index cdd6ae7f7..926e2e3b7 100644 --- a/requirements.yml +++ b/requirements.yml @@ -42,7 +42,7 @@ version: v10741-0 name: jitsi - src: git+https://github.com/mother-of-all-self-hosting/ansible-role-livekit-server.git - version: v1.9.11-1 + version: v1.9.11-2 name: livekit_server - src: git+https://github.com/mother-of-all-self-hosting/ansible-role-ntfy.git version: v2.17.0-1 diff --git a/roles/custom/matrix-base/defaults/main.yml b/roles/custom/matrix-base/defaults/main.yml index 202b1aea3..15ea0ebe6 100644 --- a/roles/custom/matrix-base/defaults/main.yml +++ b/roles/custom/matrix-base/defaults/main.yml @@ -397,6 +397,22 @@ matrix_playbook_internal_matrix_client_api_traefik_entrypoint_definition: host_bind_port: "{{ matrix_playbook_internal_matrix_client_api_traefik_entrypoint_host_bind_port }}" config: "{{ matrix_playbook_internal_matrix_client_api_traefik_entrypoint_config }}" +# Controls whether to enable an additional Traefik entrypoint for LiveKit TURN/TLS (TCP) traffic. +matrix_playbook_livekit_turn_traefik_entrypoint_enabled: false +matrix_playbook_livekit_turn_traefik_entrypoint_name: matrix-livekit-turn +matrix_playbook_livekit_turn_traefik_entrypoint_port: 5350 +matrix_playbook_livekit_turn_traefik_entrypoint_host_bind_port: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_port }}" +matrix_playbook_livekit_turn_traefik_entrypoint_config: "{{ (matrix_playbook_livekit_turn_traefik_entrypoint_config_default | combine(matrix_playbook_livekit_turn_traefik_entrypoint_config_auto)) | combine(matrix_playbook_livekit_turn_traefik_entrypoint_config_custom, recursive=True) }}" +matrix_playbook_livekit_turn_traefik_entrypoint_config_default: {} +matrix_playbook_livekit_turn_traefik_entrypoint_config_auto: {} +matrix_playbook_livekit_turn_traefik_entrypoint_config_custom: {} + +matrix_playbook_livekit_turn_traefik_entrypoint_definition: + name: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_name }}" + port: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_port }}" + host_bind_port: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_host_bind_port }}" + config: "{{ matrix_playbook_livekit_turn_traefik_entrypoint_config }}" + # Variables to Control which parts of our roles run. run_postgres_import: true run_postgres_upgrade: true