From 93fb299770f76e1f87fb7166c98aa3c52590d4b6 Mon Sep 17 00:00:00 2001 From: fkwp Date: Wed, 5 Mar 2025 21:13:55 +0100 Subject: [PATCH] add self-hosting section --- README.md | 9 +- docs/MSC4195_setup.drawio.png | Bin 0 -> 50157 bytes docs/self-hosting.md | 167 ++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 docs/MSC4195_setup.drawio.png create mode 100644 docs/self-hosting.md diff --git a/README.md b/README.md index 5ea2d18d..cc22d83e 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,12 @@ and voice calls within Matrix rooms. > Embedded packaging is recommended for Element Call in widget mode! -MSC4222 allow clients to opt-in to a change of the sync v2 API that allows them -to correctly track the state of the room. This is required by Element Call to -track room state reliably. +## 🛠️ Self-Hosting + +For operating and deploying Element Call on your own server, refer to the +[**Self-Hosting Guide**](./docs/self-hosting.md). + + Element Call requires a Livekit SFU alongside a [Livekit JWT service](https://github.com/element-hq/lk-jwt-service) to work. The url to the diff --git a/docs/MSC4195_setup.drawio.png b/docs/MSC4195_setup.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..51cf7074dddab1d8f87e2dbcce383f7ab7319b57 GIT binary patch literal 50157 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

sz^;z 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 SUin+#PgO}%u~`0<-~Ry%PBORv literal 0 HcmV?d00001 diff --git a/docs/self-hosting.md b/docs/self-hosting.md new file mode 100644 index 00000000..751ea530 --- /dev/null +++ b/docs/self-hosting.md @@ -0,0 +1,167 @@ +# Self-Hosting Element Call + +## Prerequisites + +> [!IMPORTANT] +> This section covers the requirements for deploying a **Matrix site** +> compatible with MatrixRTC, the foundation of Element Call. These requirements +> apply to both Standalone as well as Widget mode operation of Element Call. + +### A Matrix Homeserver + +The following [MSCs](https://github.com/matrix-org/matrix-spec-proposals) are +required for Element Call to work properly: + +- + **[MSC3266](https://github.com/deepbluev7/matrix-doc/blob/room-summaries/proposals/3266-room-summary.md): + Room Summary API**: In Standalone mode Element Call is able to join rooms + over federation using knocking. In this context MSC3266 is required as it + allows to request a room summary of rooms you are not joined. The summary + contains the room join rules. We need that information to decide if the user + gets prompted with the option to knock ("Request to join call"), a "cannot + join error" or "the join view". + +- + **[MSC4140](https://github.com/matrix-org/matrix-spec-proposals/blob/toger5/expiring-events-keep-alive/proposals/4140-delayed-events-futures.md) + Delayed Events**: Delayed events are required for proper call participation + signalling. If disabled it is very likely that you end up with stuck calls in + Matrix rooms. + +- + **[MSC4222](https://github.com/matrix-org/matrix-spec-proposals/blob/erikj/sync_v2_state_after/proposals/4222-sync-v2-state-after.md) + Adding `state_after` to sync v2**: Allow clients to opt-in to a change of the + sync v2 API that allows them to correctly track the state of the room. This is + required by Element Call to track room state reliably. + + +If you're using [Synapse](https://github.com/element-hq/synapse/) as your homeserver, you'll need +to additionally add the following config items to `homeserver.yaml` to comply with Element Call: + +```yaml +experimental_features: + # MSC3266: Room summary API. Used for knocking over federation + msc3266_enabled: true + # MSC4222 needed for syncv2 state_after. This allow clients to + # correctly track the state of the room. + msc4222_enabled: true + +# The maximum allowed duration by which sent events can be delayed, as +# per MSC4140. +max_event_delay_duration: 24h + +rc_message: + # This needs to match at least the heart-beat frequency plus a bit of headroom + # Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s + per_second: 0.5 + burst_count: 30 +``` + +### MatrixRTC Backend + +In order to **guarantee smooth operation** of Element Call MatrixRTC backend is +required for each site deployment. + +![MSC4195 compatible setup](MSC4195_setup.drawio.png) + +As depicted above, Element Call requires a +[Livekit SFU](https://github.com/livekit/livekit) alongside a +[Matrix Livekit JWT auth service](https://github.com/element-hq/lk-jwt-service) +to implement +[MSC4195: MatrixRTC using LiveKit backend](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md). + +> [!IMPORTANT] +> As defined in +> [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) +> MatrixRTC backend must be announced to the client via your **homeserver's +> `.well-known/matrix/client`**. The configuration is a list of Foci configs: +```json +"org.matrix.msc4143.rtc_foci": [ + { + "type": "livekit", + "livekit_service_url": "https://someurl.com" + }, + { + "type": "livekit", + "livekit_service_url": "https://livekit2.com" + }, + { + "type": "another_foci", + "props_for_another_foci": "val" + }, +] +``` + + +## Building Element Call + +> [!NOTE] +> This step is only required if you want to deploy Element Call in Standalone +> mode. + +Until prebuilt tarballs are available, you'll need to build Element Call from +source. First, clone and install the package: + +```sh +git clone https://github.com/element-hq/element-call.git +cd element-call +yarn +yarn build +``` + +If all went well, you can now find the build output under `dist` as a series of +static files. These can be hosted using any web server that can be configured +with custom routes (see below). + +You also need to add a configuration file which goes in `public/config.json` - +you can use the sample as a starting point: + +```sh +cp config/config.sample.json public/config.json +# edit public/config.json +``` + +The sample needs editing to contain the homeserver that you are using. + +Because Element Call uses client-side routing, your server must be able to route +any requests to non-existing paths back to `/index.html`. For example, in Nginx +you can achieve this with the `try_files` directive: + +```jsonc +server { + ... + location / { + ... + try_files $uri /$uri /index.html; + } +} +``` + + +## Configuration + +There are currently two different config files. `.env` holds variables that are +used at build time, while `public/config.json` holds variables that are used at +runtime. Documentation and default values for `public/config.json` can be found +in [ConfigOptions.ts](src/config/ConfigOptions.ts). + +> [!CAUTION] +> Please note configuring MatrixRTC backend via `config.json` of +> Element Call is only available for developing and debug purposes. Relying on +> it might break Element Call going forward! + + +## A Note on Standalone Mode of Element Call + +Element Call in Standalone mode requires a homeserver with registration enabled +without any 3pid or token requirements, if you want it to be used by +unregistered users. Furthermore, it is not recommended to use it with an +existing homeserver where user accounts have joined normal rooms, as it may not +be able to handle those yet and it may behave unreliably. + +Therefore, to use a self-hosted homeserver, this is recommended to be a new +server where any user account created has not joined any normal rooms anywhere +in the Matrix federated network. The homeserver used can be setup to disable +federation, so as to prevent spam registrations (if you keep registrations open) +and to ensure Element Call continues to work in case any user decides to log in +to their Element Call account using the standard Element app and joins normal +rooms that Element Call cannot handle. \ No newline at end of file