Add support for specifying the SFU WebSocket URL together with configured LiveKit transports (#20146)

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
This commit is contained in:
Johannes Marbach
2026-08-27 11:21:47 +00:00
committed by GitHub
co-authored by Andrew Morgan
parent 781d08df26
commit c246d81dec
6 changed files with 131 additions and 11 deletions
+1
View File
@@ -0,0 +1 @@
Deprecate `livekit_service_url` and add support for specifying the SFU WebSocket URL for configured LiveKit transports. Please check [the relevant section in the upgrade notes](https://github.com/element-hq/synapse/blob/develop/docs/upgrade.md#upgrading-to-v11600).
+14
View File
@@ -118,6 +118,20 @@ stacking them up. You can monitor the currently running background updates with
[the Admin API](usage/administration/admin_api/background_updates.html#status).
# Upgrading to v1.161.0
## Deprecation of `matrix_rtc.livekit_service_url`
When configuring the MatrixRTC LiveKit transport, the `livekit_service_url` is now
deprecated but should continue to be listed to ensure backwards compatibility with
older clients. A new sibling `url` config property is added that should be set to
your SFU's WebSocket URL. Clients that support `url` will use the Client-Server API
to (indirectly) interact with the LiveKit authorization service. The service needs
to be set up as an application service in order to support these endpoints. See
https://github.com/element-hq/lk-jwt-service and
https://element-hq.github.io/synapse/v1.161/usage/configuration/config_documentation.html#matrix_rtc
for further details.
# Upgrading to v1.159.0
## Change of signing key expiry date for the Debian/Ubuntu package repository (2026)
@@ -2662,13 +2662,20 @@ This setting has the following sub-options:
* `type` (string): The type of transport to use to connect to the selective forwarding unit (SFU).
* `livekit_service_url` (string): The base URL of the LiveKit service. Should only be used with LiveKit-based transports.
* `url` (string): The WebSocket URL of the LiveKit SFU. If type is "livekit", either this or `livekit_service_url` is required.
Clients that support `url` will use the Client-Server API to (indirectly) interact with the LiveKit authorization service. The service needs to be set up as an application service in order to support these endpoints. See https://github.com/element-hq/lk-jwt-service for further details.
* `livekit_service_url` (string): Deprecated. The HTTP URL of the LiveKit authorization service. If type is "livekit", either this or `url` is required.
Clients that don't support `url` will use `livekit_service_url` to directly interact with the LiveKit authorization service. This mode of operation is deprecated and should only be used for backwards compatibility.
Example configuration:
```yaml
matrix_rtc:
transports:
- type: livekit
url: wss://livekit.example.com
livekit_service_url: https://matrix-rtc.example.com/livekit/jwt
```
---
+20 -1
View File
@@ -3022,10 +3022,28 @@ properties:
type: string
description: The type of transport to use to connect to the selective forwarding unit (SFU).
example: livekit
url:
type: string
description: >-
The WebSocket URL of the LiveKit SFU. If type is "livekit", either this or `livekit_service_url` is
required.
Clients that support `url` will use the Client-Server API to (indirectly) interact with the LiveKit
authorization service. The service needs to be set up as an application service in order to support
these endpoints. See https://github.com/element-hq/lk-jwt-service for further details.
example:
wss://livekit.example.com
livekit_service_url:
type: string
description: >-
The base URL of the LiveKit service. Should only be used with LiveKit-based transports.
Deprecated. The HTTP URL of the LiveKit authorization service. If type is "livekit", either this or `url` is
required.
Clients that don't support `url` will use `livekit_service_url` to directly interact with the LiveKit
authorization service. This mode of operation is deprecated and should only be used for backwards
compatibility.
example: https://matrix-rtc.example.com/livekit/jwt
description: A list of transport types and arguments to use for MatrixRTC connections.
default: []
@@ -3033,6 +3051,7 @@ properties:
examples:
- transports:
- type: livekit
url: wss://livekit.example.com
livekit_service_url: https://matrix-rtc.example.com/livekit/jwt
enable_registration:
type: boolean
+20 -6
View File
@@ -17,7 +17,7 @@
from typing import Any
from pydantic import Field, StrictStr, ValidationError, model_validator
from pydantic import Field, StrictStr, ValidationError, field_validator, model_validator
from typing_extensions import Self
from synapse.types import JsonDict
@@ -29,20 +29,34 @@ from ._base import Config, ConfigError
class TransportConfigModel(ParseModel):
type: StrictStr
url: StrictStr | None = Field(default=None)
"""An optional WebSocket URL pointing to the LiveKit SFU. If type is "livekit", either this or livekit_service_url is required."""
livekit_service_url: StrictStr | None = Field(default=None)
"""An optional livekit service URL. Only required if type is "livekit"."""
"""Deprecated. An optional HTTP URL pointing to the LiveKit authorization service. If type is "livekit", either this or url is required."""
@model_validator(mode="after")
def validate_livekit_service_url(self) -> Self:
if self.type == "livekit" and not self.livekit_service_url:
def validate_livekit_transport(self) -> Self:
if self.type == "livekit" and not self.url and not self.livekit_service_url:
raise ValueError(
"You must set a `livekit_service_url` when using the 'livekit' transport."
"You must set either `url` or `livekit_service_url` when using the 'livekit' transport."
)
return self
class MatrixRtcConfigModel(ParseModel):
transports: list = []
transports: list[dict[str, Any]] = []
@field_validator("transports")
@classmethod
def validate_transports(
cls, transports: list[dict[str, Any]]
) -> list[dict[str, Any]]:
"""Validate each transport by attempting to construct a `TransportConfigModel`
from it, raising a `ValidationError` if construction fails."""
for transport in transports:
TransportConfigModel(**transport)
return transports
class MatrixRtcConfig(Config):
+68 -3
View File
@@ -17,8 +17,13 @@
"""Tests REST events for /rtc/endpoints path."""
import unittest as stdlib_unittest
from pydantic import ValidationError
from twisted.internet.testing import MemoryReactor
from synapse.config.matrixrtc import TransportConfigModel
from synapse.rest import admin
from synapse.rest.client import login, matrixrtc, register, room, versions
from synapse.server import HomeServer
@@ -30,7 +35,16 @@ from tests.unittest import HomeserverTestCase, override_config
PATH_PREFIX = "/_matrix/client/unstable/org.matrix.msc4143"
RTC_ENDPOINT = {"type": "focusA", "required_field": "theField"}
LIVEKIT_ENDPOINT = {
LIVEKIT_TRANSPORT = {
"type": "livekit",
"url": "wss://livekit.example.com",
}
BACKWARDS_COMPATIBLE_LIVEKIT_TRANSPORT = {
"type": "livekit",
"url": "wss://livekit.example.com",
"livekit_service_url": "https://livekit.example.com",
}
LEGACY_LIVEKIT_TRANSPORT = {
"type": "livekit",
"livekit_service_url": "https://livekit.example.com",
}
@@ -96,7 +110,7 @@ class MatrixRtcTestCase(HomeserverTestCase):
@override_config(
{
"experimental_features": {"msc4143_enabled": True},
"matrix_rtc": {"transports": [LIVEKIT_ENDPOINT]},
"matrix_rtc": {"transports": [LIVEKIT_TRANSPORT]},
}
)
def test_matrixrtc_endpoint_livekit_transport(self) -> None:
@@ -104,7 +118,38 @@ class MatrixRtcTestCase(HomeserverTestCase):
"GET", f"{PATH_PREFIX}/rtc/transports", access_token=self._alice_tok
)
self.assertEqual(200, channel.code, channel.json_body)
self.assert_dict({"rtc_transports": [LIVEKIT_ENDPOINT]}, channel.json_body)
self.assert_dict({"rtc_transports": [LIVEKIT_TRANSPORT]}, channel.json_body)
@override_config(
{
"experimental_features": {"msc4143_enabled": True},
"matrix_rtc": {"transports": [BACKWARDS_COMPATIBLE_LIVEKIT_TRANSPORT]},
}
)
def test_matrixrtc_endpoint_backwards_compatible_livekit_transport(self) -> None:
channel = self.make_request(
"GET", f"{PATH_PREFIX}/rtc/transports", access_token=self._alice_tok
)
self.assertEqual(200, channel.code, channel.json_body)
self.assert_dict(
{"rtc_transports": [BACKWARDS_COMPATIBLE_LIVEKIT_TRANSPORT]},
channel.json_body,
)
@override_config(
{
"experimental_features": {"msc4143_enabled": True},
"matrix_rtc": {"transports": [LEGACY_LIVEKIT_TRANSPORT]},
}
)
def test_matrixrtc_endpoint_legacy_livekit_transport(self) -> None:
channel = self.make_request(
"GET", f"{PATH_PREFIX}/rtc/transports", access_token=self._alice_tok
)
self.assertEqual(200, channel.code, channel.json_body)
self.assert_dict(
{"rtc_transports": [LEGACY_LIVEKIT_TRANSPORT]}, channel.json_body
)
class MatrixRtcVersionsTestCase(HomeserverTestCase):
@@ -150,3 +195,23 @@ class MatrixRtcVersionsTestCase(HomeserverTestCase):
channel = self.make_request("GET", "/_matrix/client/versions")
self.assertEqual(channel.code, 200, channel.result)
self.assertTrue(channel.json_body["unstable_features"]["org.matrix.msc4143"])
class TransportConfigModelTestCase(stdlib_unittest.TestCase):
"""Tests validation of the `TransportConfigModel` pydantic model."""
def test_livekit_transport_requires_url_or_livekit_service_url(self) -> None:
with self.assertRaises(ValidationError):
TransportConfigModel(type="livekit")
def test_livekit_transport_with_only_url(self) -> None:
TransportConfigModel(type="livekit", url="wss://livekit.example.com")
def test_livekit_transport_with_only_livekit_service_url(self) -> None:
TransportConfigModel(
type="livekit", livekit_service_url="https://livekit.example.com"
)
def test_invalid_field_type(self) -> None:
with self.assertRaises(ValidationError):
TransportConfigModel(type="livekit", url=1234) # type: ignore[arg-type]