I am a very responsible and organised maintainer and this was a deliberate plan to see how many users are keeping an active watch on the project's releases /j
* Make all links indirect for better maintenance
* Add Domain section with `coturn.example.com` and use it in subsequent
examples
* Add standard ports for TURN and TURNS
* Remove TURNS-over-UDP (unknown whether it is supported)
* Add section on opening ports with ufw commands
* IMPORTANT: Move password auth/guest access instructions into the
Appendix as they are very insecure
* Small improvements in Testing section
* Rewrite Troubleshooting section to be more concise and cut down on
errors
* Add note to Eturnal in Appendix section
Temporarily using revision until a full release can be made.
This update includes more trace logging to help with debugging
possible resolution errors.
On room creation, A list of initial state events may be provided that
should be submitted to the room after creation. These events
should be treated as any other state event and submitted to
the same checks.
With this change, state events submitted on room creation will be
submitted through the same helper as those through the usual endpoint.
The submission helper is moved to the timeline service to make it
available everywhere. This will be useful for implementing MSC4140
(issue #903).
roomuserid_lastnotificationread was mapped to userroomid_highlightcount
instead of its own table, so last_notification_read() read the highlight
count and reset_notification_counts clobbered the highlight table when
setting a read marker. Add the missing table definition and fix the alias.
The current `request_ip_source` setting only allows a single option.
While it does fall back to the peer IP if the header is missing as of !2003,
which likely covers a lot of regular use, only allowing a single option limits
the deployment options available to more advanced deployments.
Setups where internal and external traffic use different reverse proxies will
end up with the wrong IP and the implicitness of the fallback allows for
situations where the used IP is not the IP expected.
By introducing a setting that allows multiple options to be set,
this limitation is resolved and it becomes possible to have client IP resolution
behind different reverse proxies and also making it possible to decide if and/or
what the fallback should be.
If set, options are evaluated in order. If all fail, the request fails.
The appservice branch of update_device_route (MSC4190 device creation)
generated a random device ID instead of using the one from the request
path, and dropped the requested display name. The PUT returned 200, but
the device the appservice asked for never existed, so every subsequent
request masquerading as that device failed with M_FORBIDDEN and one
orphaned random-ID device was left behind per attempt.
This made encrypted mautrix (bridgev2) bridges unable to start on
OIDC-enabled servers, where MSC4190 is the only available device
creation mechanism: /keys/upload failed on first start and /keys/query
on every restart. Combined with the pre-1f5e178c3f behaviour (400
"Token conflicts with an existing appservice token"), MSC4190 device
creation has never worked end-to-end in any release.
Create the device under the requested ID and forward the requested
display name.
Prevents a potential bug where we might inadvertently reject valid invites because we have a stale state cache that blocks the sender or even ourselves
Also fixes the banned remote server room check by using the create event instead of room ID
* Ignores any events pushed without a room ID
* Removes needless clones for PDU size checking
* Removes incorrect ACL check in incoming handler
* Fast-path handling already handled outlier events
* Remove redundant same-room checks, replace with useful ones
* Combine event rejection and persistence in a single function
* Additional safety assertions in upgrade task
* Split upgrade task into multiple subroutines for reduced cognitive complexity
* Only mutate current state and forward extremities in tandem
* Improve code documentation to better explain the logic flow
This removes the old (broken) DNS caching method for reqwest, and replaces
it with resolvematrix' `MatrixDnsResolver`, as it correctly implements
caching and overrides for correct SNI behavior.
diff --git c/src/service/resolver/actual.rs i/src/service/resolver/actual.rs
index 9cd1aec15..495d83172 100644
--- c/src/service/resolver/actual.rs
+++ i/src/service/resolver/actual.rs
@@ -1,9 +1,5 @@
use std::fmt::Debug;
-use super::{
- cache::{CachedDest, CachedOverride, MAX_IPS},
- fed::{FedDest, PortString, add_port_to_hostname, ensure_host_has_port, get_ip_with_port},
-};
use conduwuit::{Err, Result, debug, debug_info, err, error, trace};
use futures::{FutureExt, TryFutureExt};
use hickory_resolver::{
@@ -15,9 +11,11 @@
use super::{
cache::{CachedDest, CachedOverride, MAX_IPS},
- fed::{FedDest, PortString, add_port_to_hostname, get_ip_with_port},
+ fed::{FedDest, PortString, add_port_to_hostname, ensure_host_has_port, get_ip_with_port},
};
+const DEFAULT_PORT: u16 = 8448;
+
#[derive(Clone, Debug)]
pub(crate) struct ActualDest {
pub(crate) dest: FedDest,
@@ -26,9 +24,7 @@ pub(crate) struct ActualDest {
impl ActualDest {
#[inline]
- pub(crate) fn string(&self) -> String {
- self.dest.https_string()
- }
+ pub(crate) fn string(&self) -> String { self.dest.https_string() }
}
impl super::Service {
@@ -75,7 +71,8 @@ pub async fn resolve_actual_dest(
// Ensure dest is a valid connection endpoint
self.validate_dest(dest)?;
- // Clippy believes this can be a clone, however we are actually converting ServerName to String
+ // Clippy believes this can be a clone, however we are actually converting
+ // ServerName to String
#[allow(clippy::implicit_clone)]
let mut host = dest.to_string().to_owned();
let actual_dest = self.resolve_server_name(dest, cache, &mut host).await?;
@@ -103,8 +100,8 @@ async fn resolve_server_name(
cache: bool,
host: &mut String,
) -> Result<FedDest> {
- // 1. If `dest` is an IP, use it directly. If a port is provided as well (IP:port socket pair)
- // use that, otherwise default to port 8448
+ // 1. If `dest` is an IP, use it directly. If a port is provided as well
+ // (IP:port socket pair) use that, otherwise default to port 8448
if let Some(fed_dest) = get_ip_with_port(dest.as_str()) {
debug!("1: IP literal with provided or default port");
return Ok(fed_dest);
@@ -117,8 +114,8 @@ async fn resolve_server_name(
.await?;
}
- // Pre-resolve IP? Unsure what overrides exactly do, system is due to be removed either way
- // https://matrix.to/#/!da26JtAjE6APGLnX8ncWsvc-skF2KQZ9Nw_MbNpYD2k/%24_hq6JP0JXANbMTMPdV64iZbgbsZdhy92M5ndDYGy6No
+ // Pre-resolve IP? Unsure what overrides exactly do, system is due to be removed
+ // either way https://matrix.to/#/!da26JtAjE6APGLnX8ncWsvc-skF2KQZ9Nw_MbNpYD2k/%24_hq6JP0JXANbMTMPdV64iZbgbsZdhy92M5ndDYGy6No
self.conditional_query_and_cache(dest.as_str(), DEFAULT_PORT, true)
.await?;
@@ -126,7 +123,8 @@ async fn resolve_server_name(
self.services.server.check_running()?;
// 3. If `dest` is a hostname with no port, send GET to `https://<dest>/.well-known/matrix/server`.
- // If invalid JSON (throws error), skip to step 4. Otherwise, parse `delegated` as `<hostname>[:<port>]` and...
+ // If invalid JSON (throws error), skip to step 4. Otherwise, parse `delegated`
+ // as `<hostname>[:<port>]` and...
if let Some(delegated) = self.request_well_known(dest.as_str()).await? {
// delegated=matrix-federation.matrix.org:443 // host=matrix.org
self.resolve_3_well_known(host, cache, delegated).await?;
@@ -137,11 +135,13 @@ async fn resolve_server_name(
self.resolve_4_srv_lookup(host, cache, overrider).await?;
}
- // 5. if .well-known errored and no SRV exists, resolve IP and connect on default port (8448)
+ // 5. if .well-known errored and no SRV exists, resolve IP and connect on
+ // default port (8448)
self.resolve_5_direct(dest, cache).await
}
- /// Parse a host:port socket pair into separate parts, and resolve the hostname into an IP address
+ /// Parse a host:port socket pair into separate parts, and resolve the
+ /// hostname into an IP address
async fn resolve_2_host_port(
&self,
dest: &ServerName,
@@ -180,14 +180,16 @@ async fn resolve_3_well_known(
return Ok(host_and_port);
}
- // 3.2 - If <delegated> is not an IP and a port is present, lookup IP for hostname and connect
+ // 3.2 - If <delegated> is not an IP and a port is present, lookup IP for
+ // hostname and connect
if let Some(pos) = &delegated.find(':') {
self.resolve_3_2_hostname_port(cache, &delegated, *pos)
.await?;
}
- // 3.3 - If <delegated> is not an IP and there is no port, lookup SRV `_matrix._tcp.<delegated>`
- // (which may provide a new hostname + port to use, see steps 3.1 and 3.2)
+ // 3.3 - If <delegated> is not an IP and there is no port, lookup SRV
+ // `_matrix._tcp.<delegated>` (which may provide a new hostname + port to use,
+ // see steps 3.1 and 3.2)
trace!("Delegated hostname has no port, querying SRV");
if let Some(overrider) = self.query_srv_record(&delegated).await? {
self.resolve_3_3_use_srv(cache, &delegated, overrider)
@@ -342,17 +344,14 @@ async fn query_and_cache_override(
match self.resolver.resolver.lookup_ip(hostname.to_owned()).await {
| Err(e) => Self::handle_resolve_error(&e, hostname),
| Ok(override_ip) => {
- self.cache.set_override(
- untername,
- &CachedOverride {
- ips: override_ip.iter().take(MAX_IPS).collect(),
- port,
- expire: CachedOverride::default_expire(),
- overriding: (hostname != untername)
- .then_some(hostname.into())
- .inspect(|_| debug_info!("{untername:?} overridden by {hostname:?}")),
- },
- );
+ self.cache.set_override(untername, &CachedOverride {
+ ips: override_ip.into_iter().take(MAX_IPS).collect(),
+ port,
+ expire: CachedOverride::default_expire(),
+ overriding: (hostname != untername)
+ .then_some(hostname.into())
+ .inspect(|_| debug_info!("{untername:?} overridden by {hostname:?}")),
+ });
Ok(())
},
@@ -415,7 +414,8 @@ fn handle_resolve_error(err: &NetError, host: &'_ str) -> Result<()> {
}
}
- /// Ensure `dest` is a valid destination (valid ip if it is an IP), and not ourselves (unless in config)
+ /// Ensure `dest` is a valid destination (valid ip if it is an IP), and not
+ /// ourselves (unless in config)
fn validate_dest(&self, dest: &ServerName) -> Result<()> {
if dest == self.services.server.name && !self.services.server.config.federation_loopback {
return Err!("Won't send federation request to ourselves");
diff --git c/src/service/resolver/fed.rs i/src/service/resolver/fed.rs
index b43f62eed..83601a98a 100644
--- c/src/service/resolver/fed.rs
+++ i/src/service/resolver/fed.rs
@@ -9,8 +9,8 @@
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum FedDest {
- Literal(SocketAddr),
- Named(String, PortString),
+ Literal(SocketAddr), // "ip:port"
+ Named(String, PortString), // ("hostname", ":port")
}
/// numeric or service-name
@@ -18,6 +18,9 @@ pub enum FedDest {
const DEFAULT_PORT: &str = ":8448";
+/// Attempt to parse `dest_str` as either an IP:port socket pair or as a plain
+/// IP (adding the default port), returning `None` if dest_str is neither a
+/// socket pair nor a plain IP.
pub(crate) fn get_ip_with_port(dest_str: &str) -> Option<FedDest> {
if let Ok(dest) = dest_str.parse::<SocketAddr>() {
Some(FedDest::Literal(dest))
@@ -28,6 +31,8 @@ pub(crate) fn get_ip_with_port(dest_str: &str) -> Option<FedDest> {
}
}
+/// Convert a `dest` string with or without port into a FedDest with either
+/// the provided port (if host:port format) or the default port (8448)
pub(crate) fn add_port_to_hostname(dest: &str) -> FedDest {
let (host, port) = match dest.find(':') {
| None => (dest, DEFAULT_PORT),
@@ -42,8 +47,8 @@ pub(crate) fn add_port_to_hostname(dest: &str) -> FedDest {
/// Ensure `host` always has a port
///
-/// `get_ip_with_port` returns `None` if `host` isn't an IP:port string or plain IP,
-/// in which case `add_port_to_hostname` adds it instead
+/// `get_ip_with_port` returns `None` if `host` isn't an IP:port string or plain
+/// IP, in which case `add_port_to_hostname` adds it instead
#[inline]
pub(crate) fn ensure_host_has_port(host: &str) -> FedDest {
get_ip_with_port(host).unwrap_or_else(|| add_port_to_hostname(host))
Previously the function assumed the caller had performed proper validation on the inputs (and all current callers do), but this is a poor reason to panic when sane error handling is available.
Events with no prev events now return an error, and prev events which are illegal are simply skipped.
Some servers reference events in prev_events that they might not yet have finished processing, so this allows us to at least attempt to get the state from another trustworthy server in the room that might be faster. I don't think this is too effective, however it's more effective than giving up immediately.
This may look scary, but this is safe because event auth performs the same check, and will reject the event if it doesn't reference the create event correctly.
tomfos.tr act-runner image removed the possibility to install the latest LLVM using an installer script, so let us also remove the detection and just live with the distro's clang image.
- Sliding sync no longer continues streaming data to a user after they are removed from a room. Contributed by @eleboucher. (SEC10)
- Valid redaction events no longer arbitrarily soft-fail and are applied correctly as expected.
- Fixed a regression that caused the server to process events for rooms it no longer has any local users in, which caused users to be reset back *into* rooms.
# Continuwuity 26.7.0 (2026-07-27)
## Features
- Build and publish arm64 .deb packages alongside amd64 for all supported Debian and Ubuntu releases. (#1235)
- Dehydrated devices are now visible in the account panel. Contributed by @ginger. (#1970)
- Introduce `accepted_ip_sources` as a multiple options variant of `request_ip_source`, allowing for more advanced deployments and making fallbacks an explicit choice. Contributed by @Omar007 (#1985)
- Added an admin command to issue an access token for a bot account, to allow legacy bots to function while legacy authentication is disabled. Contributed by @ginger (#2044)
- Added support for the OAuth2 device authorization flow. Contributed by @ginger
- Added support for the stable mutual rooms query endpoint. Contributed by @ginger
- Fetch the joined member count once per event instead of once per notified user.
## Bugfixes
- Fix joining restricted rooms over federation failing with signature verification error. (fix-federation-signature)
- Fixed the client space hierarchy endpoint returning a 500 "Space hierarchy is unreasonably large" error for cyclic space graphs (e.g. a space containing itself). Rooms are now deduplicated during
traversal as required by the spec, and the traversal depth is bounded even when the client does not specify `max_depth`. (space-hierarchy-cycle)
- Fixed simplified sliding sync holding account data for up to 30 seconds, which made encryption setup and cross-signing resets appear to hang. (sss-account-data-longpoll)
- Fixed local invites and invite acceptances not being reflected in sync promptly. Contributed by @eleboucher (wake-local-member-sync)
- Fixed the deeplink redirect for deleting devices. Contributed by @koen (#1965)
- Fix status code for oauth registration. Contributed by @n00byking (#1984)
- Exempt m.room.create from auth_events check. Contributed by @eleboucher (#1987)
- Fixed `create` being returned as a supported prompt value regardless of if registration is enabled or not. Contributed by @ginger (#1994)
- Fixed high CPU usage when multiple clients from the same account were connected at once. Each sync woke the account's other sync loops, causing them to wake each other in a loop. (#2006)
- Fixed MSC4190 appservice device creation registering a random device ID instead of the requested one (and dropping the requested display name), which prevented encrypted mautrix bridges from
starting on OIDC-enabled servers and leaked an orphan device on the bridge bot per startup attempt. (#2015)
- Deactivated users and appservice puppets are no longer counted by `/_continuwuity/local_user_count`. Contributed by @ginger. (#2040)
- Re-introduced admin room registration alerts that were accidentally removed in the OAuth2 update. (#2057)
- Appservices are now properly able to create devices for E2EE.
- Appservices may now specify both the unstable and stable `device_id` query parameters in a request. The stable parameter will take priority. Contributed by @ginger.
- Fixed `roomuserid_lastnotificationread` being aliased to the highlight count table, which clobbered highlight counts when setting a read marker. Contributed by @eleboucher
- Fixed freshly left room failing to sync.
- Fixed newly created rooms failing to sync properly in clients using legacy sync.
- Fixed newly joined rooms failing to sync their full state (including the room name) to clients using legacy sync.
- Fixed requests returning `500 Internal Server Error` when the header selected by `request_ip_source` is absent, duplicated, or malformed (for example Envoy omitting `X-Envoy-External-Address` on
internal requests). The client IP now falls back to the connection peer address instead of failing the request. Contributed by @eleboucher
- Resolve alias service by correct name for auto-join. Contributed by @eleboucher
## Improved Documentation
- Updated an out-of-date statement about Oracle Linux release cadences. (#1999)
# Continuwuity 26.6.2 (2026-07-12)
## Bugfixes
- Fixed the server returning 500 errors if `admin_console_automatic` is enabled and no TTY is available. Contributed by @s1lv3r. (#1975)
- Fixed `global.oauth.compatibility_mode` being required, despite being ignored, when the `[global.oauth.oidc]` config section is provided.
- Fixed an issue with a migration that could cause user accounts imported from an identity provider to be marked as deactivated when the server started. If you have accounts affected by this issue,
use `!admin users reset-password --convert-to-local-account` to reactivate them.
# Continuwuity 26.6.1 (2026-07-12)
## Features
- Added enforcement for new federated invite checks and corrected a bunch of related spec compliance issues along the way. Contributed by @nex. (#1952)
## Bugfixes
- Fixed existing accounts failing to link when logging in with OIDC if `prompt_for_localpart` was `false`. (#1942)
- Authentication is no longer required on the `/_matrix/client/v3/account/3pid/email/requestToken` endpoint. (#1953)
- Fixed newly created rooms failing to sync properly in clients using legacy sync.
- Stopped appservice users from being erroneously marked as deactivated during a 26.6 database migration.
- Whitespace will now automatically be trimmed from the start and end of the `global.oauth.oidc.client_secret_file`.
# Continuwuity 26.6.0 (2026-07-10)
## Features
- Added support for linking an external identity provider with OIDC. Contributed by @ginger. (#765)
- Updated [MSC4284: Policy Servers](https://github.com/matrix-org/matrix-spec-proposals/pull/4284) implementation to support the newly stabilised proposal. Contributed by @nex. (#1487)
- Added config option for default room ACLs. Contributed by @eve. (#1691)
- Added support for fallback encryption keys. (#1710)
- Add `!admin users reject-all-invites` to clean invite spam (#1741)
- Implemented event rejection, which should resolve and prevent future netsplits of the kinds observed within some Continuwuity rooms. Also resolved several bugs related to both soft-failing events,
and event backfilling, which should improve state resolution stability. The `!admin debug get-pdu` command was updated to disambiguate event acceptance status, and
`!admin debug show-auth-chain` was added to visually display event auth chains, which may assist developers in debugging strangely complex events.
Contributed by @nex. (#1747)
- Added full support for [MSC4168: Update `m.space.*` state on room upgrade](https://github.com/matrix-org/matrix-spec-proposals/pull/4168). Contributed by @nex. (#1807)
- Improved the performance and reliability of fetching missing events, improving network partition recovery. Contributed by @nex. (#1818)
- Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you
are on NixOS. Contributed by @Henry-Hiles (QuadRadical). (#1853)
- Added support for MSC4380 invite blocking, which has become part of the Matrix specification in v1.18. Contributed by @nex. (#1875)
- Added a configuration option to allow choosing a client IP source that is not the TCP connecting IP. Contributed by @nex. (#1931)
- Added support for MSC4466, which allows clients to customize how changes to a user's global profile are propagated. Contributed by @ginger.
- Added support for Matrix 1.16's `state_after` feature, allowing clients which understand it to sync room state changes more reliably. Contributed by @ginger.
- Added support for authenticating clients using the new OAuth 2.0 login API. Contributed by @ginger.
- Appservice device management as outlined in MSC4190 (part of Matrix 1.17) is now fully supported. Contributed by @ginger.
- Users may now be forbidden from deactivating their own accounts with the new `allow_deactivation` config option. Contributed by @ginger.
## Bugfixes
- Adjusted legacy sync logic to allow the `roomsynctoken_shortstatehash` database column to be dropped, massively reducing database sizes, especially for old deployments. Contributed by @ginger.
(#917)
- Fixed a bug that caused the server to drop events during processing if several events for the same room were sent in a singular transaction. Contributed by @nex. (#1711)
- fix `!admin query account-data account-data-get` not returning the content (#1742)
- Fixed an issue where Continuwuity would only advertise support for the unstable endpoint for Mutual Rooms (MSC2666), despite only supporting the stable endpoint. Contributed by @Henry-Hiles
(QuadRadical) (#1752)
- Fixed admin commands being ignored when they had leading whitespace before admin commands. Contributed by @kitvonsnookerz. (#1804)
- Fixed several bugs in the `POST /_matrix/client/v3/rooms/{roomId}/upgrade` endpoint. Contributed by @nex. (#1807)
- Devices which set their presence as "offline" will no longer be considered for presence updates. Contributed by @timedout.
- Improved invite and join reliability in clients using legacy sync. Contributed by @ginger
- The invite recipient's membership event is now included in invite stripped state, which should fix flaky invite display in some clients. Contributed by @ginger
## Improved Documentation
- Add performance tuning documentation. Contributed by @stratself. (#1498)
- Explain accessing Continuwuity's server console when deployed via Docker. (#1671)
- Clarified in the config that `max_request_size` affects federated media as well. (#1706)
- Added example configuration using caddy-docker-proxy in the livekit setup section of the docs. Contributed by @Cease (#1762)
- Updated deployment docs to account for new RPM package availability across more distros. Contributed by @julian45. (#1912)
## Deprecations and Removals
- Removed support for LDAP. (#1701)
- Removed support for guest user registration, a little-used and deprecated approach to room previews.
- Removed the `/_conduwuit/` versions of the `local_user_count` and `version` routes. These routes are still accessible under the `/_continuwuity` prefix.
- Support for server-side blurhashing (part of MSC2448) has been removed.
- The deprecated `well_known.rtc_focus_server_urls` config option has been removed. MatrixRTC foci should be configured using the `matrix_rtc.foci` config option.
## Misc
- #1505, #1829, #1927, #1933, #1934
- Switched from Continuwuity's fork of Ruma back to upstream Ruma. Contributed by @ginger.
- The version of Debian that the Docker-based build process uses has been upgraded from Bookworm to Trixie, meaning that standalone binaries now have a minimum glibc of 2.41, and can no longer be used
on distro versions from before 2025-01-30
# Continuwuity 0.5.8 (2026-04-24)
## Features
@@ -14,7 +151,6 @@ ## Improved Documentation
- Updated config docs to state we support room version 12, and set it as default. Contributed by @ezera. (#1622)
- Improve instructions for generic deployments, removing unnecessary parts and documenting the new initial registration token flow. Contributed by @stratself (#1677)
# Continuwuity v0.5.7 (2026-04-17)
## Features
@@ -56,7 +192,6 @@ ## Misc
- Fixed compiler warning in cf_opts.rs when building in release. Contributed by @ezera. (#1620)
# Continuwuity 0.5.6 (2026-03-03)
## Security
@@ -66,22 +201,33 @@ ## Security
## Features
- Outgoing presence is now disabled by default, and the config option documentation has been adjusted to more accurately represent the weight of presence, typing indicators, and read receipts. Contributed by @nex. ([#1399](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1399))
- Improved the concurrency handling of federation transactions, vastly improving performance and reliability by more accurately handling inbound transactions and reducing the amount of repeated wasted work. Contributed by @nex and @Jade. ([#1428](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1428))
- Added [MSC3202](https://github.com/matrix-org/matrix-spec-proposals/pull/3202) Device masquerading (not all of MSC3202). This should fix issues with enabling [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190) for some Mautrix bridges. Contributed by @Jade ([#1435](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1435))
- Added [MSC3814](https://github.com/matrix-org/matrix-spec-proposals/pull/3814) Dehydrated Devices - you can now decrypt messages sent while all devices were logged out. ([#1436](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1436))
- Implement [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) MatrixRTC transport discovery endpoint. Move RTC foci configuration from `[global.well_known]` to a new `[global.matrix_rtc]` section with a `foci` field. Contributed by @0xnim ([#1442](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1442))
- Outgoing presence is now disabled by default, and the config option documentation has been adjusted to more accurately represent the weight of presence, typing indicators, and read receipts.
Contributed by @nex. ([#1399](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1399))
- Improved the concurrency handling of federation transactions, vastly improving performance and reliability by more accurately handling inbound transactions and reducing the amount of repeated wasted
work. Contributed by @nex and @Jade. ([#1428](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1428))
- Added [MSC3202](https://github.com/matrix-org/matrix-spec-proposals/pull/3202) Device masquerading (not all of MSC3202). This should fix issues with
enabling [MSC4190](https://github.com/matrix-org/matrix-spec-proposals/pull/4190) for some Mautrix bridges. Contributed by @Jade
- Added [MSC3814](https://github.com/matrix-org/matrix-spec-proposals/pull/3814) Dehydrated Devices - you can now decrypt messages sent while all devices were logged out.
- Implement [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) MatrixRTC transport discovery endpoint. Move RTC foci configuration from `[global.well_known]` to a new
`[global.matrix_rtc]` section with a `foci` field. Contributed by @0xnim ([#1442](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1442))
- Updated `list-backups` admin command to output one backup per line. ([#1394](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1394))
- Improved URL preview fetching with a more compatible user agent for sites like YouTube Music. Added `!admin media delete-url-preview <url>` command to clear cached URL previews that were stuck and broken. ([#1434](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1434))
- Improved URL preview fetching with a more compatible user agent for sites like YouTube Music. Added `!admin media delete-url-preview <url>` command to clear cached URL previews that were stuck and
- Removed non-compliant nor functional room alias lookups over federation. Contributed by @nex ([#1393](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1393))
- Removed ability to set rocksdb as read only. Doing so would cause unintentional and buggy behaviour. Contributed by @Terryiscool160. ([#1418](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1418))
- Fixed a startup crash in the sender service if we can't detect the number of CPU cores, even if the `sender_workers` config option is set correctly. Contributed by @katie. ([#1421](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1421))
- Removed ability to set rocksdb as read only. Doing so would cause unintentional and buggy behaviour. Contributed by @Terryiscool160.
- Fixed a startup crash in the sender service if we can't detect the number of CPU cores, even if the `sender_workers` config option is set correctly. Contributed by @katie.
- Removed the `allow_public_room_directory_without_auth` config option. Contributed by @0xnim. ([#1441](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1441))
- Fixed sliding sync v5 list ranges always starting from 0, causing extra rooms to be unnecessarily processed and returned. Contributed by @0xnim ([#1445](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1445))
- Fixed a bug that (repairably) caused a room split between continuwuity and non-continuwuity servers when the room had both `m.room.policy` and `org.matrix.msc4284.policy` in its room state. Contributed by @nex ([#1481](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1481))
- Fixed sliding sync v5 list ranges always starting from 0, causing extra rooms to be unnecessarily processed and returned. Contributed by @0xnim
- Fixed a bug that (repairably) caused a room split between continuwuity and non-continuwuity servers when the room had both `m.room.policy` and `org.matrix.msc4284.policy` in its room state.
Contributed by @nex ([#1481](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1481))
- Fixed `!admin media delete --mxc <url>` responding with an error message when the media was deleted successfully. Contributed by @lynxize
- Fixed spurious 404 media errors in the logs. Contributed by @benbot.
- Fixed spurious warn about needed backfill via federation for non-federated rooms. Contributed by @kraem.
- You can now set a custom User Agent for URL previews; the default one has been modified to be less likely to be
rejected. Contributed by @trashpanda ([#1372](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1372))
`M_SENDER_IGNORED`](https://github.com/matrix-org/matrix-spec-proposals/pull/4406). Contributed by @nex ([#1308](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1308))
- Introduce a resolver command to allow flushing a server from the cache or to flush the complete cache. Contributed by @Omar007
- Improved the handling of restricted join rules and improved the performance of local-first joins. Contributed by @nex. ([#1368](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1368))
- You can now set a custom User Agent for URL previews; the default one has been modified to be less likely to be rejected. Contributed by@trashpanda
- Improved the first-time setup experience for new homeserver administrators:
- Account registration is disabled on the first run, except for with a new special registration token that is logged
to the console.
- Other helpful information is logged to the console as well, including a giant warning if open registration is
enabled.
- Account registration is disabled on the first run, except for with a new special registration token that is logged to the console.
- Other helpful information is logged to the console as well, including a giant warning if open registration is enabled.
- The default index page now says to check the console for setup instructions if no accounts have been created.
- Once the first admin account is created, an improved welcome message is sent to the admin room.
@@ -111,10 +253,10 @@ ## Features
## Bugfixes
- Fixed invites sent to other users in the same homeserver not being properly sent down sync. Users with missing or
broken invites should clear their client caches after updating to make them appear. ([#1249](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1249))
- LDAP-enabled servers will no longer have all admins demoted when LDAP-controlled admins are not configured.
Contributed by @Jade ([#1307](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1307))
- Fixed invites sent to other users in the same homeserver not being properly sent down sync. Users with missing or broken invites should clear their client caches after updating to make them appear.
- Fixed sliding sync not resolving wildcard state key requests, enabling Video/Audio calls in Element X. ([#1370](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1370))
- The announcement checker will now announce errors it encounters in the first run to the admin room, plus a few other misc improvements. Contributed by @Jade
- Drastically improved the performance and reliability of account deactivations. Contributed by@nex ([#1314](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1314))
- Refuse to process requests for and events in rooms that we no longer have any local users in (reduces state resets and improves performance). Contributed by @nex
- Added server-specific admin API routes to ban and unban rooms, for use with moderation bots. Contributed by @nex ([#1301](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1301))
## Bugfixes
- Fix the generated configuration containing uncommented optional sections. Contributed by
- Fixed specification non-compliance when handling remote media errors. Contributed by @nex ([#1298](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1298))
- UIAA requests which check for out-of-band success (sent by matrix-js-sdk) will no longer create unhelpful errors in the logs. Contributed by@ginger
- Fixed backtraces being swallowed during panics. Contributed by @jade ([#1337](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1337))
- Fixed a potential vulnerability that could allow an evil remote server to return malicious events during the room join and knock process. Contributed by @nex, reported by
violet & [mat](https://matdoes.dev).
- Fixed a race condition that could result in outlier PDUs being incorrectly marked as visible to a remote server. Contributed by @nex, reported by violet & [mat](https://matdoes.dev).
- ACLs are no longer case-sensitive. Contributed by @nex, reported by [vel](matrix:u/vel:nhjkl.com?action=chat).
## Docs
- Fixed Fedora install instructions. Contributed by
- Improve the display of nested configuration with the `!admin server show-config` command. Contributed by@Jade ([#1279](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1279))
## Bugfixes
- Fixed `M_BAD_JSON` error when sending invites to other servers or when providing joins. Contributed by
- Fixed `M_BAD_JSON` error when sending invites to other servers or when providing joins. Contributed by@nex ([#1286](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1286))
## Docs
- Improve admin command documentation generation. Contributed by
- Added support for issuing additional registration tokens, stored in the database, which supplement the existing registration token hardcoded in the config file. These tokens may optionally expire
after a certain number of uses or after a certain amount of time has passed. Additionally, the `registration_token_file` configuration option is superseded by this feature and **has been removed**.
Use the new `!admin token` command family to manage registrationtokens. Contributed by @ginger (#783).
- Implemented a configuration defined admin list independent of the admin room. Contributed by @Terryiscool160. ([#1253](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1253))
- Added support for invite and join anti-spam via Draupnir and Meowlnir, similar to that of synapse-http-antispam. Contributed by @nex.
- Implemented account locking functionality, to complement user suspension. Contributed by @nex. ([#1266](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1266))
- Added admin command to forcefully log out all of a user's existing sessions. Contributed by @nex. ([#1271](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1271))
- Implemented toggling the ability for an account to log in without mutating any of its data. Contributed by @nex. (
- Client requested timeout parameter is now applied to e2ee key lookups and claims. Related federation requests are now also concurrent. Contributed by @nex.
- Fixed the whoami endpoint returning HTTP 404 instead of HTTP 403, which confused some appservices. Contributed by @nex. ([#1276](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1276))
## Misc
- The `console` feature is now enabled by default, allowing the server console to be used for running admin commands
directly. To automatically open the console on startup, set the `admin_console_automatic` config option to `true`.
Contributed by @ginger.
- The `console` feature is now enabled by default, allowing the server console to be used for running admin commands directly. To automatically open the console on startup, set the
`admin_console_automatic` config option to `true`. Contributed by @ginger.
- We now (finally) document our container image mirrors. Contributed by @Jade
- Enabled the OTLP exporter in default builds, and allow configuring the exporter protocol. (@Jade). ([#1251](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1251))
## Bug Fixes
- Don't allow admin room upgrades, as this can break the admin room (
- Don't allow admin room upgrades, as this can break the admin room (@timedout) ([#1245](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1245))
- Fix invalid creators in power levels during upgrade to v12 (@timedout) ([#1245](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1245))
This document outlines the security policy for Continuwuity. Our goal is to maintain a secure platform for all users, and we take security matters seriously.
This document outlines the security policy for Continuwuity. Our goal is to maintain a secure platform for all users,
and we take security matters seriously.
## Supported Versions
We provide security updates for the following versions of Continuwuity:
| Version | Supported |
|-------------- |:----------------:|
| Latest release | ✅ |
| Main branch | ✅ |
| Older releases | ❌ |
| Version | Supported |
|----------------|:---------:|
| Latest release | ✅ |
| Main branch | ✅ |
| Older releases | ❌ |
We may backport fixes to the previous release at our discretion, but we don't guarantee this.
We may backport fixes to the previous release at our discretion, but we don't guarantee this; our versioning is designed
to encourage users to stay up-to-date with the latest release, and we have no concept of "long term support".
## Reporting a Vulnerability
### Responsible Disclosure
We appreciate the efforts of security researchers and the community in identifying and reporting vulnerabilities. To ensure that potential vulnerabilities are addressed properly, please follow these guidelines:
We appreciate the efforts of security researchers and the community in identifying and reporting vulnerabilities. To
ensure that potential vulnerabilities are addressed properly, please follow these guidelines:
1. **Contact members of the team directly** over E2EE private message.
2. **Email the security team** at [security@continuwuity.org](mailto:security@continuwuity.org). This is not E2EE, so
don't include sensitive details.
3. **Do not disclose the vulnerability publicly** until a fix has been pushed to the main branch.
4. **Provide detailed information** about the vulnerability, including:
- A clear description of the issue
- Steps to reproduce
- Potential impact
- Any possible mitigations
- Version(s) affected, including specific commits if possible
- A clear description of the issue
- Steps to reproduce
- Potential impact
- Any possible mitigations
- Version(s) affected, including specific commits if possible
- How you want to be attributed if your report is accepted (website, social media handle, Matrix user ID, etc).
**Please state explicitly if you wish to remain anonymous.**
If you have any doubts about a potential security vulnerability, contact us via private channels first! We'd prefer that you bother us, instead of having a vulnerability disclosed without a fix.
If you have any doubts about a potential security vulnerability, contact us via private channels first! We'd prefer that
you bother us, instead of having a vulnerability disclosed without a fix.
### What to Expect
### Terms for credit
Before reporting a vulnerability, please remember that we are a small team maintaining a large codebase depended upon by
a vast unknown number of users in our free time. While we always investigate *all* security reports, we may not
acknowledge or credit your report under certain circumstances.
#### Following the security policy
If you do not report the vulnerability following this security policy, your report may be ignored and/or may not be
credited if fixed. This includes filing for GitHub security advisories without contacting us directly first (we do not
get notified about these!).
#### Automation-assisted reports
Reports assisted by automatic tooling such as LLMs MUST disclose such in the report.
Assisted reports must also produce a working proof-of-concept (PoC) demonstrating the vulnerability against the latest
release and/or main commit with no modifications to the codebase. This is to demonstrate that not only does
the author understand the vulnerability that they are reporting, but also that the vulnerability is reproducible
and not a false positive.
#### Reports for known issues
Reports for issues we are already aware of will only be credited if subsequent reporters provide new information.
#### Audits and CVE farming
Sweeping audits (vulnerability hunting) **must** be coordinated with the team first - receiving a rapsheet of new
vulnerabilities is explicitly not helpful to us and only harms the project. If you are interested in performing a
security audit, please contact us first to discuss the scope and methodology.
Likewise, CVE farming (reporting vulnerabilities with the primary intent to get a CVE number) is actively harmful to the
project, and will not be credited. Severe violations of this policy will result in a permanent ban from collaborating
with the project in any capacity. We are attempting to build high quality free software, not flesh out your CV/resume.
### What to expect
When you report a security vulnerability:
1. **Acknowledgment**: We will acknowledge receipt of your report.
2. **Assessment**: We will assess the vulnerability and determine its impact on our users
3. **Updates**: We will provide updates on our progress in addressing the vulnerability, and may request you help test mitigations
1. **Acknowledgment**: We will acknowledge receipt of your report. We may ask for further information.
2. **Triage**: The report will be triaged into our internal tracker, and you will be provided with a reference number (
in case you end up with multiple reports). An ETA for a fix will be provided if feasible.
3. **Updates**: We will provide updates on our progress in addressing the vulnerability, including a heads-up for when
we plan to release a fix.
4. **Resolution**: Once resolved, we will notify you and discuss coordinated disclosure
5. **Credit**: We will recognize your contribution (unless you prefer to remain anonymous)
@@ -50,7 +94,8 @@ ## Security Update Process
1. We will develop and test fixes in a private fork
2. Security updates will be released as soon as possible
3. Release notes will include information about the vulnerabilities, avoiding details that could facilitate exploitation where possible
3. Release notes will include information about the vulnerabilities, avoiding details that could facilitate exploitation
where possible
4. Critical security updates may be backported to the previous stable release
The invite recipient's membership event is now included in invite stripped state, which should fix flaky invite display in some clients. Contributed by @ginger
The deprecated `well_known.rtc_focus_server_urls` config option has been removed. MatrixRTC foci should be configured using the `matrix_rtc.foci` config option.
The version of Debian that the Docker-based build process uses has been upgraded from Bookworm to Trixie, meaning that standalone binaries now have a minimum glibc of 2.41, and can no longer be used on distro versions from before 2025-01-30
Fixed a bug that caused the server to drop events during processing if several events for the same room were sent in a singular transaction. Contributed by @nex.
Refactor TURN docs and remove unsafe setups. Polish LiveKit docs. Add guidance for TURNS-over-443 multiplexing for both LiveKit and legacy calls. Contributed by @stratself
Fixed an issue where Continuwuity would only advertise support for the unstable endpoint for Mutual Rooms (MSC2666), despite only supporting the stable endpoint. Contributed by @Henry-Hiles (QuadRadical)
Added full support for [MSC4168: Update `m.space.*` state on room upgrade](https://github.com/matrix-org/matrix-spec-proposals/pull/4168). Contributed by @nex.
- Element Call powered by [MatrixRTC](https://half-shot.github.io/msc-crafter/#msc/4143) and [LiveKit](https://github.com/livekit/livekit)
- Legacy calls, sometimes using Jitsi
- Legacy calls, supported by a STUN/TURN server.
Both types of calls are supported by different sets of clients, but most clients are moving towards MatrixRTC / Element Call.
For either one to work correctly, you have to do some additional setup.
For either one to work correctly, you have to do some additional setup:
- For legacy calls to work, you need to set up a TURN/STUN server. [Read the TURN guide for tips on how to set up coturn](./calls/turn.mdx)
- For MatrixRTC / Element Call to work, you have to set up the LiveKit backend (foci). LiveKit also uses TURN/STUN to increase reliability - you can set up its built-in TURN server, or integrate with an existing one. [Read the LiveKit guide](./calls/livekit.mdx)
- For MatrixRTC / Element Call to work, you have to set up the LiveKit backend. LiveKit also uses TURN/STUN to increase reliability - you can set up its built-in TURN server, or integrate with an existing one. [Read the LiveKit guide](./calls/livekit.mdx)
LiveKit should live on its own domain or subdomain. In this guide we use `livekit.example.com` - this should be replaced with a domain you control.
Make sure the DNS record for the (sub)domain you plan to use is pointed to your server.
### 2. Services
### 2. Set up the LiveKit services
Using LiveKit with Matrix requires two services - LiveKit itself, and a service (`lk-jwt-service`) that grants Matrix users permission to connect to it.
Using LiveKit with Matrix requires two services - LiveKit itself, and a brokering service (`lk-jwt-service`) that grants Matrix users permission to connect to it.
You must generate a key and secret to allow the Matrix service to authenticate with LiveKit. `LK_MATRIX_KEY` should be around 20 random characters, and `LK_MATRIX_SECRET` should be around 64. Remember to replace these with the actual values!
You will need to allow ports `7881/tcp` and `50100:50200/udp` through your firewall. If you use UFW, the commands are: `ufw allow 7881/tcp` and `ufw allow 50100:50200/udp`.
### 3. Telling clients where to find LiveKit
To tell clients where to find LiveKit, you need to add the address of your `lk-jwt-service` to the `[global.matrix_rtc]` config section using the `foci` option.
To tell clients where to find LiveKit, you need to add your `lk-jwt-service`'s address to the `[global.matrix_rtc] > foci` field of your Continuwuity config file.
The variable should be a list of servers serving as MatrixRTC endpoints. Replace the URL with the address you are deploying your instance of lk-jwt-service to:
@@ -100,6 +106,12 @@ ### 3. Telling clients where to find LiveKit
]
```
If you configure Continuwuity via environment variables, use the following:
```bash
CONTINUWUITY_MATRIX_RTC__FOCI=[{ type = "livekit", livekit_service_url = "https://livekit.example.com" }]
```
This will expose LiveKit information on the following endpoints for clients to discover:
@@ -132,6 +144,11 @@ ### 4. Configure your Reverse Proxy
}
```
**Note**: if you run Caddy inside a container (e.g. by following the example [here](../deploying/docker.mdx#caddy-using-caddyfile)) instead of on the host, then:
- Put these containers on the same bridge network as caddy (by defining `networks: [ caddy ]` in each of the services), and
- Use appropriate container hostnames (`lk-jwt-service` and `livekit`) instead of `127.0.0.1` in the Caddyfile
</details>
<details>
@@ -187,6 +204,7 @@ ### 4. Configure your Reverse Proxy
```
</details>
<details>
<summary>Example docker compose file with caddy-docker-proxy labels</summary>
```yaml
@@ -262,73 +280,6 @@ ### 6. Start Everything
Start up the services using your usual method - for example `docker compose up -d`.
## Additional TURN configuration
### Using LiveKit's built-in TURN server
LiveKit includes a built-in TURN server which can be used in place of an external option. This TURN server will only work with LiveKit, so you can't use it for legacy Matrix calling or anything else.
If you don't want to set up a separate TURN server, you can enable this with the following changes:
```yaml
### add this to livekit.yaml ###
turn:
enabled: true
udp_port: 3478
relay_range_start: 50300
relay_range_end: 50400
domain: livekit.example.com
```
```yaml
### add these to livekit's docker-compose ###
ports:
- "3478:3478/udp"
- "50300-50400:50300-50400/udp"
### if you're using `network_mode: host`, you can skip this part
```
Recreate the LiveKit container (with `docker-compose up -d livekit`) to apply these changes. Remember to allow the new `3478/udp` and `50300:50400/udp` ports through your firewall.
### Integration with an external TURN server
If you've already [set up coturn](./turn), you can configure Livekit to use it.
:::tip Avoid port clashes between the two services
Before continuing, make sure coturn's `min-port` and `max-port` do not overlap with LiveKit's port range:
```ini
# in your coturn.conf
min-port=50201
max-port=65535
```
:::
Generate a long random secret for LiveKit, and add it to your coturn config under the `static-auth-secret` option. You can add as many secrets as you want, so set a different one for LiveKit to use.
Then configure LiveKit, making sure to replace `COTURN_SECRET` with the one you generated:
```yaml
# livekit.yaml
rtc:
turn_servers:
- host: coturn.example.com
port: 3478
protocol: udp
secret: "COTURN_SECRET"
- host: coturn.example.com
port: 3478
protocol: tcp
secret: "COTURN_SECRET"
- host: coturn.example.com
port: 5349
protocol: tls # Only if you have already set up TLS in your coturn
secret: "COTURN_SECRET"
```
Restart LiveKit and coturn to apply these changes.
## Testing
To test that LiveKit is successfully integrated with Continuwuity, you will need to replicate its [Token Exchange Flow](https://github.com/element-hq/lk-jwt-service#%EF%B8%8F-how-it-works--token-exchange-flow). Follow the steps below while checking Docker logs (`docker-compose logs --follow`), in order to help [troubleshooting](#troubleshooting) any issues.
Use this token to test at the [LiveKit Connection Tester](https://livekit.io/connection-test). If everything works there, then you have set up LiveKit successfully!
Use this token to test at the [LiveKit Connection Tester][livekit-connection-test]. If everything works there, then you have set up LiveKit successfully!
- `MISSING_MATRIX_RTC_FOCUS`: LiveKit is missing from Continuwuity's config file
- `MISSING_MATRIX_RTC_FOCUS`/`MISSING_MATRIX_RTC_TRANSPORT`: LiveKit is missing from Continuwuity's config file
- "Waiting for media" popup always showing: a LiveKit URL has been configured in Continuwuity, but your client cannot connect to it for some reason
- `OPEN_ID_ERROR`: Your client can reach out to `lk-jwt-service`, but has problems authenticating with it. In this case, check `lk-jwt-service` logs for more details
For browser-based clients, you can also inspect connections using DevTools' Networking tab, to see which requests are erroring out.
@@ -440,6 +394,19 @@ # --- some errors ---
After implementing the changes and restarting your compose, `lk-jwt-service` should now connect to your other services. The sidecar container test above should now return an `OK` from LiveKit.
### Incorrect IP address for LiveKit
By default, LiveKit auto-discovers its public IP address(es), which is reflected in the "Establishing WebRTC connection" section of the connection test page. If these IPs are incorrect, you may want to hardcode your own IP by doing the following:
```diff
### in your livekit.yaml ###
rtc:
# ... other configs here ...
- use_external_ip: true
+ use_external_ip: false
+ node_ip: "1.2.3.4"
```
### Workaround for non-federating servers
When deploying on servers with federation disabled (`allow_federation = false`), LiveKit will fail as it can't fetch the required [OpenID endpoint](https://spec.matrix.org/v1.17/server-server-api/#get_matrixfederationv1openiduserinfo) via federation paths.
Most of the time, LiveKit [**does not need TURN**][sspaeth-matrix-voip-turn] to function. However, there are situations where clients are in very restrictive networks that disallows non-standard ports and UDP. In these cases, a TURN-over-TLS server on port :443 could be employed to relay traffic for them.
First, set up LiveKit's built-in TURN server with its own domain - we'll use `livekit-turn.example.com` in our example.
```yaml
## add this to `livekit.yaml` ##
turn:
enabled: true
# note: the TLS port will always be advertised as :443
tls_port: 5349
# optional: configure an extra UDP port on :3478
# udp_port: 3478
relay_range_start: 50300
relay_range_end: 50400
domain: livekit-turn.example.com
# replace these with your actual cert/key files
cert_file: /path/to/livekit-turn.example.com.crt
key_file: /path/to/livekit-turn.example.com.key
```
```yaml
### add these ports to livekit's docker-compose ###
### if you're using `network_mode: host`, you can skip this part
ports:
- "127.0.0.1:5349:5349/tcp"
- "50300-50400:50300-50400/udp"
# "3478:3478/udp" # (optional UDP port)
```
Recreate the LiveKit container (with `docker-compose up -d livekit`) to apply these changes. Remember to allow the new `50300:50400/udp` ports through your firewall.
Then, we will configure a route from port 443 of the host back to our `livekit-turn.example.com` service on port 5349. To both **multiplex** this and LiveKit's websocket on the same port, we will use a layer-4 reverse proxy with **SNI routing** capabilities, such as [caddy-l4][caddy-l4] on the host system.
```
## in your Caddyfile ##
{
servers {
listener_wrappers {
# intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners
layer4 {
@turn tls sni livekit-turn.example.com
route @turn {
proxy 127.0.0.1:5349 # forward to normal TURNS port
}
}
}
tls
}
}
}
# livekit stuff
https://livekit.example.com {
@lk-jwt-service path /healthz /get_token /sfu/get
route @lk-jwt-service {
reverse_proxy 127.0.0.1:8081
}
reverse_proxy http://127.0.0.1:7880
}
```
[caddy-l4]: https://github.com/mholt/caddy-l4
</details>
<details>
<summary>Using an external TURN server (coturn)</summary>
Before continuing, make sure coturn's `min-port` and `max-port` do not overlap with LiveKit's port range:
```ini
# in your coturn.conf
min-port=50201
max-port=65535
```
Then, generate a long random secret for LiveKit, and add it to your coturn config under the `static-auth-secret` option. You can add as many secrets as you want, so set a different one for LiveKit to use.
After that, refer to the following [**TURN instructions**](./turn#turns-over-443) to set up coturn with TLS, as well as multiplexing with LiveKit's websocket on port 443.
Then configure LiveKit, making sure to replace `COTURN_SECRET` with the one you generated:
```yaml
### in your livekit.yaml ###
rtc:
# ... other configs here ...
turn_servers:
- host: coturn.example.com
port: 443
protocol: tls
secret: "COTURN_SECRET"
```
Restart LiveKit, coturn, and Caddy-l4 to apply these changes.
</details>
After finishing configuration, you can run the Testing steps again to check that TURN-over-TLS is working. In the LiveKit connection test page, there should be a green tick saying "Can connect to TURN".
[TURN](https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT) and [STUN](https://en.wikipedia.org/wiki/STUN) are used as a component in many calling systems. Matrix uses them directly for legacy calls and indirectly for MatrixRTC via Livekit.
[TURN][turn] and [STUN][stun] are used as a component in many calling systems. Matrix uses them directly for legacy calls and indirectly for MatrixRTC via Livekit.
Continuwuity recommends using [Coturn](https://github.com/coturn/coturn) as your TURN/STUN server, which is available as a Docker image or a distro package.
Continuwuity recommends using [Coturn][coturn] as your TURN/STUN server, which is available as a Docker image or a distro package. This guide assumes that you are using docker compose for deployment.
:::tip
You can find help setting up TURN/STUN in our MatrixRTC room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org)
Next, we will start the Coturn container with the [official image][coturn-image]. **Host networking mode** will be used, as it is better for performance and reduces configuration complexity (see [Coturn Docker docs][coturn-docker-docs] for rationale).
Create a `docker-compose.yml` file and run `docker compose up -d`:
```yaml
version: '3'
services:
turn:
container_name: coturn-server
image: docker.io/coturn/coturn
restart: unless-stopped
network_mode: "host"
volumes:
- ./coturn.conf:/etc/coturn/turnserver.conf
```
:::info Why host networking?
Coturn uses host networking mode because it needs to bind to multiple ports and work with various network protocols. Using host networking is better for performance, and reduces configuration complexity. To understand alternative configuration options, visit [Coturn's Docker documentation](https://github.com/coturn/coturn/blob/master/docker/coturn/README.md).
:::
### Security Recommendations
### 5. Security Recommendations
For security best practices, see Synapse's [Coturn documentation](https://element-hq.github.io/synapse/latest/turn-howto.html), which includes important firewall and access control recommendations.
For Coturn hardening and security best practices, see Synapse's [Coturn documentation][synapse-coturn-guide],
which includes important firewall and access control recommendations.
# TTL for generated credentials in seconds (default: 86400 = 24 hours)
turn_ttl = 86400
turn_ttl = 10800
```
:::tip Using TLS
The `turns:` URI prefix instructs clients to connect to TURN over TLS, which is highly recommended for security. Make sure you've configured TLS in your coturn server first.
:::
### Static Credentials (Alternative)
If you prefer static username/password credentials instead of shared secrets:
```toml
turn_uris = [
"turn:coturn.example.com?transport=udp",
"turn:coturn.example.com?transport=tcp"
]
turn_username = "your_username"
turn_password = "your_password"
```
:::warning
Static credentials are less secure than shared secrets because they don't expire and must be configured in coturn separately. It is strongly advised you use shared secret authentication.
:::
### Guest Access
By default, TURN credentials require client authentication. To allow unauthenticated access:
```toml
turn_allow_guests = true
```
:::caution
This is not recommended as it allows unauthenticated users to access your TURN server, potentially enabling abuse by bots. All major Matrix clients that support legacy calls *also* support authenticated TURN access.
:::
### Important Notes
- Replace `coturn.example.com` with your actual TURN server domain (the `realm` from coturn.conf)
- The `turn_secret` must match the `static-auth-secret` in your coturn configuration
- Restart or reload Continuwuity after making configuration changes
Restart Continuwuity, and the new changes should now be applied.
## Testing Your TURN Server
### Testing Credentials
Verify that Continuwuity is correctly serving TURN credentials to clients:
Get an access token for your current login session. These can be found in your client's settings or obtained via [this website](https://timedout.uk/mxtoken.html).
Then, using that token, verify that Continuwuity is correctly serving TURN credentials to clients:
To gather debug logs while troubleshooting Coturn, add `verbose` to your `coturn.conf`. You can then view these logs with `docker-compose logs --follow coturn`.
- Verify firewall rules allow the necessary ports (3478, 5349, and your media port range)
- Check that DNS resolves correctly for your TURN domain
- Ensure your `turn_secret` matches coturn's `static-auth-secret`
- Test with Trickle ICE to isolate the issue
### Errors with Trickle ICE
### Port conflicts with LiveKit
- `code=701` - the TURN server is not reachable
- Verify firewall rules allow the necessary ports (3478, 5349, and your media port range)
- Verify via logs that coturn is exposed on the correct addresses and interfaces
- Check that DNS resolves correctly for your TURN domain
- `code=401` - unauthorized credentials
- Ensure your `turn_secret` matches coturn's `static-auth-secret`
- Ensure the credentials you obtained from the Testing steps has not expired yet. You can adjust `turn_ttl` in your Continuwuity configuration to increase this, or simply re-request a new one
- Wrong IP address advertised
- This may be caused by coturn not recognizing its public-facing IP correctly, due to particular network setups. You can configure `external-ip=<desired-public-ip>` to fix this issue.
- Or adjust LiveKit's port range to avoid coturn's default range
### 404 when calling the turnServer endpoint
### 404 when calling turnServer endpoint
This is the correct response when no TURN servers are configured, as per [MSC4166][msc4166]. Verify that your `turn_uris` is not empty in your Continuwuity config and try again.
- Verify that `turn_uris` is not empty in your Continuwuity config
- This behavior is correct per MSC4166 if no TURN URIs are configured
Normally, TURN would work on their default setups. However, there are situations where clients are in very restrictive networks that disallows non-standard ports and UDP. In these cases, a TURN-over-TLS server on port :443 could be employed to relay traffic for them.
However, port 443 is usually utilized by other HTTPS services. Therefore, one would need to **multiplex** both TURN HTTPS on these ports, and filter packets to them via **SNI routing**.
Below are examples to multiplex Coturn and [LiveKit](./livekit.mdx) on port 443, using [caddy-l4][caddy-l4] on the host system.
<details>
<summary>Caddyfile with TLS passthrough</summary>
This Caddyfile:
- Route `turn.example.com` to the TURNS port for Coturn without TLS termination, and
- Route `livekit.example.com` to the [LiveKit services](./livekit.mdx) with TLS termination by Caddy
Please note that all traffic from Coturn's perspective will be coming from caddy-l4's IP now.
```
{
servers {
listener_wrappers {
# intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners
layer4 {
@turn tls sni turn.example.com
route @turn {
proxy 127.0.0.1:5349 # forward to normal TURNS port
}
}
tls
}
}
}
# livekit stuff
https://livekit.example.com {
@lk-jwt-service path /healthz /get_token /sfu/get
route @lk-jwt-service {
reverse_proxy 127.0.0.1:8081
}
reverse_proxy http://127.0.0.1:7880
}
```
</details>
<details>
<summary>Caddyfile with TLS termination and PROXY protocol forwarding</summary>
This setup:
- Terminates TLS for `turn.example.com`,
- Tag the decrypted packets with PROXY protocol, and route it to coturn's `tcp-proxy-port`
- Route `livekit.example.com` to the [LiveKit services](./livekit.mdx) with TLS termination by Caddy
It allows coturn to see real client IPs, but the TLS handling is done on Caddy's side.
First, enable coturn's PROXY-protocol accepting port by adding this:
```ini
# in coturn.conf
tcp-proxy-port=5555
```
Then, in the Caddyfile:
```
{
servers {
listener_wrappers {
# intercept packets meant for the TURN domain first
# before forwarding other packets to "normal" HTTP listeners
layer4 {
@turn tlssni turn.example.com
route @turn {
tls # terminate TLS for the turn.example.com packets
proxy {
# then, proxy them to tcp-proxy-port and enable PROXY protocol version 2
upstream 127.0.0.1:5555
proxy_protocol v2
}
}
}
tls
}
}
}
# livekit stuff
https://livekit.example.com {
@lk-jwt-service path /healthz /get_token /sfu/get
route @lk-jwt-service {
reverse_proxy 127.0.0.1:8081
}
reverse_proxy http://127.0.0.1:7880
}
# placeholder block to obtain certs for turn.example.com
https://turn.example.com {
respond "OK" 200
}
```
**Note**: the setup will disable TURN-over-TLS functionality on port 5349/tcp.
</details>
After configuration and spin-up, the destination `turns:turn.example.com:443?transport=tcp` should work with Trickle ICE tests. You can now advertise it as an address in your `turn_uris` as well as [LiveKit](./livekit#additional-turns-over-443-configuration).
[caddy-l4]: https://github.com/mholt/caddy-l4
### Unsafe TURN setups (not recommended)
<details>
<summary>Using static credentials</summary>
:::caution
Static credentials are less secure than shared secrets because they don't expire and must be configured in coturn separately. It is strongly advised you use [shared secret authentication](#2-configuration).
:::
If you prefer static username/password credentials instead of shared secrets:
- Alternatively, if you want both client and federation traffic on `:443`, you can configure `CONTINUWUITY_WELL_KNOWN` following some of the [examples](#choose-your-reverse-proxy) below.
:::tip Split-domain setups
For more setups with `.well-known` delegation and split-domain deployments, consult the [Delegation/Split-domain](../advanced/delegation) page.
For more setups with `.well-known` delegation and split-domain deployments, consult the [Delegation/Split-domain](../guides/delegation) page.
:::
## Docker Compose
@@ -79,7 +79,7 @@ ### Choose Your Reverse Proxy
nameserver 1.1.1.1
```
Consult the [**DNS tuning guide (recommended)**](../advanced/dns.mdx) for full solutions to this issue.
Consult the [**DNS tuning guide (recommended)**](../guides/dns.mdx) for full solutions to this issue.
:::
#### Caddy (using Caddyfile)
@@ -269,7 +269,7 @@ ### Accessing the Server's Console
## Next steps
- For smooth federation, set up a caching resolver according to the [**DNS tuning guide**](../advanced/dns.mdx) (recommended)
- For smooth federation, set up a caching resolver according to the [**DNS tuning guide**](../guides/dns.mdx) (recommended)
- To set up Audio/Video communication, see the [**Calls**](../calls.mdx) page.
- Consult the [Maintenance](../maintenance.mdx) page for guidance on maintaining your homeserver.
- If you want to set up an appservice, take a look at the [**Appservice Guide**](../appservices.mdx).
For x86_64 systems with CPUs from the last ~15 years, use the
`-haswell-` optimised binaries for best performance. These
binaries enable hardware-accelerated CRC32 checksumming in
RocksDB, which significantly improves database performance.
The haswell instruction set provides an excellent balance of
compatibility and speed.
Continuwuity provides `*-maxperf` tagged binaries, which uses the `release-max-perf` build profile with [link-time optimisation (LTO)][lto-rust-docs]. For the x86_64 architecture, these binaries specifically target the Haswell architecture (hence the `-haswell-` name extension), and enables hardware-accelerated CRC32 checksumming in
RocksDB which significantly improves database performance. If you're using an x86_64 system with CPUs from the last ~15 years, consider using these images for best performance.
If you're using Docker instead, equivalent performance-optimised
images are available with the `-maxperf` suffix (e.g.
Theres a Nix package defined in our flake, available for Linux and MacOS. Add continuwuity as an input to your flake, and use `inputs.continuwuity.packages.${system}.default` to get a working Continuwuity package.
If you wish to generate a static binary, you can do so using Nix: `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity#packageName`, where `packageName` is one of:
If you simply wish to generate a binary using Nix, you can run `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity` to generate a binary in `result/bin/conduwuit`.
- `default-static-x86_64`
- `default-static-aarch64`
- `max-perf-static-x86_64`
- `max-perf-haswell-static-x86_64`
- `max-perf-static-aarch64`
`max-perf` takes longer to build, but has more runtime optimizations. Haswell builds are optimized for modern CPUs.
### Compiling
Alternatively, you may compile the binary yourself.
#### Using Docker
See the [Building Docker Images](../development/index.mdx#building-docker-images)
section in the development documentation.
#### Manual
##### Dependencies
- Run `nix develop` to get a devshell with everything you need
- Or, install the following:
- (On linux) `liburing-dev` on the compiling machine, and `liburing` on the target host
- (On linux) `pkg-config` on the compiling machine to allow finding `liburing`
- A C++ compiler and (on linux) `libclang` for RocksDB
##### Build
You can now build Continuwuity using `cargo build --release`.
Continuwuity supports various optional features that can be enabled during compilation. Please see the Cargo.toml file for a comprehensive list, or ask in our rooms.
Alternatively, you may compile the binary yourself. See the [Appendix subsection](#compiling-continuwuity) for more details.
## Adding a Continuwuity user
@@ -164,7 +142,7 @@ ## Exposing ports in the firewall or the router
are: `ufw allow 8448/tcp` and `ufw allow 443/tcp`.
:::tip Alternative port/domain setups
If you would like to use only port 443, a different port, or a subdomain for the homeserver, you will need to set up `.well-known` delegation. Consult the `[global.well_known]` section of the config file, and the [**Delegation/Split-domain**](../advanced/delegation) page to learn more about these kinds of deployments.
If you would like to use only port 443, a different port, or a subdomain for the homeserver, you will need to set up `.well-known` delegation. Consult the `[global.well_known]` section of the config file, and the [**Delegation/Split-domain**](../guides/delegation) page to learn more about these kinds of deployments.
:::
## Setting up the Reverse Proxy
@@ -201,7 +179,7 @@ ### Other Reverse Proxies
- `/_matrix/client` - core Client-Server APIs. These should be available on port :443
- `/_conduwuit/` and `/_continuwuity/` - ad-hoc Continuwuity routes for password resets, email verification, and server details such as `/local_user_count` and `/server_version`.
- `/_continuwuity/` - Continuwuity's integrated account management interface and authentication path for OAuth-compatible clients
You can optionally reverse proxy the following individual routes:
@@ -209,7 +187,7 @@ ### Other Reverse Proxies
Continuwuity to perform delegation (see the `[global.well_known]` config section)
- `/.well-known/matrix/support` if using Continuwuity to send the homeserver admin
[contact and support page][well-known-support]
- `/` and `/_continuwuity/logo.svg` if you would like to see the Continuwuity landing page
- `/` and `/_continuwuity/resources` if you would like to see the Continuwuity landing page
Refer to the respective software's documentation and online guides on how to do so.
@@ -280,10 +258,10 @@ ## How do I know it works?
As a quick health check, you can also use these cURL commands:
@@ -294,7 +272,33 @@ # For client-server endpoints
## What's next?
- For smooth federation, set up a caching resolver according to the [**DNS tuning guide**](../advanced/dns.mdx) (recommended)
- For smooth federation, set up a caching resolver according to the [**DNS tuning guide**](../guides/dns.mdx) (recommended)
- To configure OIDC login with an identity provider, see the [**delegated authentication guide**](../guides/oidc.mdx).
- For Audio/Video call functionality see the [**Calls**](../calls.md) page.
- Consult the [Maintenance](../maintenance.mdx) page for guidance on maintaining your homeserver.
- If you want to set up an appservice, take a look at the [**Appservice Guide**](../appservices.md).
## Appendix
### Compiling Continuwuity
#### Using Docker
See the [Building Docker Images](../development/index.mdx#building-docker-images)
section in the development documentation.
#### Manual
##### DEPENDENCIES
- Run `nix develop` to get a devshell with everything you need
- Or, install the following:
- (On linux) `liburing-dev` on the compiling machine, and `liburing` on the target host
- (On linux) `pkg-config` on the compiling machine to allow finding `liburing`
- A C++ compiler and (on linux) `libclang` for RocksDB
##### BUILD
You can now build Continuwuity using `cargo build --release`.
Continuwuity supports various optional features that can be enabled during compilation. Please see the Cargo.toml file for a comprehensive list, or ask in our rooms.
Continuwuity versions v0.5.10+ are available as RPM packages for the following distributions:
<Tabs groupId="distro">
<Tab label="Fedora">
Available for upstream-supported Fedora versions (including compatible distributions, such as Ultramarine Linux) and Rawhide through Terra.
</Tab>
<Tab label="EL">
Available for Enterprise Linux (RHEL, AlmaLinux, Rocky Linux, etc.) **10+** through Terra.
:::warning Oracle Linux support
Due to upstream limitations, Terra is only usable on Oracle Linux if you use [upstream EPEL](https://docs.fedoraproject.org/en-US/epel/getting-started/)
rather than Oracle's rebuilds of EPEL. Oracle tends to lag behind on new EL versions, both major and minor—for example, Oracle's release of 10.2 lagged
approximately 1.5 months behind other ELs—so you may encounter further compatibility issues with EPEL.
**For this reason, it is recommended that you use another EL distribution if at all possible.**
:::
</Tab>
<Tab label="SUSE">
Available for openSUSE Tumbleweed and [supported Leap versions](https://en.opensuse.org/Lifetime) through the openSUSE Build Service.
</Tab>
</Tabs>
## Installation methods
### Stable releases (recommended)
<Tabs groupId="distro">
<Tab label="Fedora">
1. Follow [Terra's directions for adding the Terra repo on your distribution](https://docs.terrapkg.com/usage/installing/#fedora-and-derivatives).
2. Install the `continuwuity` package.
</Tab>
<Tab label="EL">
1. Follow [Terra's directions for adding the Terra repo on your distribution](https://docs.terrapkg.com/usage/installing/#enterprise-linux). Be sure to acquire/enable relevant dependencies!
2. Install the `continuwuity` package.
</Tab>
<Tab label="SUSE">
openSUSE packages are available through an openSUSE Build Service project namespace provided by a community member.
1. Navigate to [this page](https://software.opensuse.org/download.html?project=home%3Ajulian45&package=continuwuity).
2. Click on the "Add repository and install manually" text to expand install instructions.
3. Follow the provided instructions for your version of openSUSE.
</Tab>
</Tabs>
### Nightly releases
Nightly versions are built from the latest commit on the `main` branch every 24 hours.
<Tabs groupId="distro">
<Tab label="Fedora">
1. Follow [Terra's directions for adding the Terra repo on your distribution](https://docs.terrapkg.com/usage/installing/#fedora-and-derivatives).
2. Install the `continuwuity-nightly` package.
</Tab>
<Tab label="EL">
1. Follow [Terra's directions for adding the Terra repo on your distribution](https://docs.terrapkg.com/usage/installing/#enterprise-linux). Be sure to acquire/enable relevant dependencies!
2. Install the `continuwuity-nightly` package.
</Tab>
<Tab label="SUSE">
Nightly packages for openSUSE are **not currently available**.
If there is an ongoing need for these, please ask in `#continuwuity:continuwuity.org` or [open an issue on Forgejo](https://forgejo.ellis.link/continuwuation/continuwuity/issues/new).
In the meantime, you may follow the [generic deployment instructions](generic).
</Tab>
</Tabs>
## Service management and removal
**Systemd service commands**
```bash
# Start the service
sudo systemctl start conduwuit
# Enable on boot
sudo systemctl enable conduwuit
# Check status
sudo systemctl status conduwuit
# View logs
sudo journalctl -u conduwuit -f
```
**Uninstallation**
```bash
# Stop and disable the service
sudo systemctl stop conduwuit
sudo systemctl disable conduwuit
# Remove the package
sudo dnf remove continuwuity # replace `dnf` with `zypper` on openSUSE
1. Follow [Terra's prep directions](https://docs.terrapkg.com/contributing/getting-started/#preparation) to bootstrap your development environment.
2. `git clone` the [Terra sources repo](https://github.com/terrapkg/packages).
3. Follow [Terra's build instructions](https://docs.terrapkg.com/contributing/getting-started/#building), using the path `anda/misc/continuwuity/nightly/pkg`. If desiring a build of the latest stable version, replace `nightly` with `stable` instead.
</Tab>
<Tab label="EL">
1. Follow [Terra's prep directions](https://docs.terrapkg.com/contributing/getting-started/#preparation) to bootstrap your development environment.
2. `git clone` the [Terra sources repo](https://github.com/terrapkg/packages).
3. Follow [Terra's build instructions](https://docs.terrapkg.com/contributing/getting-started/#building), using the path `anda/misc/continuwuity/nightly/pkg`. If desiring a build of the latest stable version, replace `nightly` with `stable` instead.
</Tab>
<Tab label="SUSE">
1. Navigate to [this package's location in the openSUSE Build Service web UI](https://build.opensuse.org/package/show/home:julian45/continuwuity).
2. Click on the "Checkout package" text and follow the instructions to acquire a local copy of the packaging source.
3. In the `_service` file, adjust the revision within the `<param name="revision">` tag (approx. line 6) to your desired git repo revision.
4. Run `osc service ra` to update your copy of the Continuwuity sources and vendored packages.
5. Run `osc build` to locally build an openSUSE-ready RPM.
Instead of configuring `[global.well_known]` options and reverse proxying well-known URIs, you can serve these files directly as static JSON that match the ones above. This is useful if your base domain points to a different physical server, and reverse proxying isn't feasible.
Instead of reverse proxying well-known URIs, you can serve these files directly as static JSON that match the ones above. This is useful if your base domain points to a different physical server, and reverse proxying isn't feasible.
:::warning
Even if you choose to serve the well-known files manually, if you are using delegation at all, you **must** still set the `global.well_known.client` configuration option to the domain you're delegating to. Continuwuity needs to know the domain it runs on for OAuth-compatible clients to work correctly.
Continuwuity supports delegating user authentication to an external identity provider that implements the OpenID Connect specification, such as Authentik, kanidm, or Keycloak.
:::warning{title="OIDC versus OAuth, and supported clients"}
**OIDC** is not to be confused with **OAuth**. In the context of Matrix, OAuth is the protocol that Matrix clients use to authenticate with the _homeserver_. OIDC is the protocol that the _homeserver_ uses to communicate with the _identity provider_. Continuwuity supports OAuth by default, alongside the legacy **UIAA** authentication framework.
When OIDC is configured, Continuwuity will disable its support for legacy authentication. **Only clients that support OAuth**, such as the Element family of clients, will be able to log in when OIDC is configured. If your client of choice shows an error when you try to log in after configuring OIDC, it likely does not support OAuth. This is an issue with your client, not Continuwuity, and should be reported to your client's developers.
:::
A simple OIDC configuration is as easy as creating a new OIDC application in your identity provider's settings and supplying Continuwuity with the client ID and client secret. This guide will use kanidm as an example, but the described steps are broadly applicable to other identity providers.
First, create a new application for Continuwuity in your identity provider.
```sh
# Here, `c10y` is the client ID that kanidm will use, and `Continuwuity` is the display name.
# Other identity providers may generate a client ID for you.
# Use the domain that clients can reach Continuwuity at, which may not be the same as your server name
# if you have configured well-known delegation.
kanidm system oauth2 create c10y Continuwuity https://matrix.yourdomain.com
```
Configure the redirect URL that Continuwuity uses.
```sh
kanidm system oauth2 add-redirect-url c10y https://matrix.yourdomain.com/_continuwuity/oidc/complete
```
Allow Continuwuity to request the `openid` scope. Other identity providers may not require this step.
```sh
kanidm system oauth2 update-scope-map c10y idm_all_persons openid
```
Find the client secret that was generated. Other identity providers may show this information in their web UI.
```sh
kanidm system oauth2 show-basic-secret c10y
d1qgx352kkuvs1j70b6w293d65x68jve1f7b27fyk90gjhpr
```
Configure Continuwuity with the client ID, client secret, and discovery URL. kanidm has a different discovery URL for each client, but other identity providers may have a single discovery URL at the root of their domain.
```toml
[global.oauth.oidc]
# `/.well-known/openid-configuration` will be appended automatically
Finally, restart Continuwuity, and log out and back in again. Your client should prompt you to continue in your web browser and open a webpage with the Continuwuity logo that allows you to continue in your identity provider. Once you log in successfully, you will be prompted to choose a user ID -- to link your existing account, enter its user ID, and then your old password when prompted.
Continuwuity offers several additional configuration options to tweak its integration with your identity provider. Review the `[global.oauth.oidc]` section towards the bottom of the [reference configuration](../reference/config) for a complete list of options and documentation.
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
},
{
"id": 13,
"id": 17,
"mention_room": true,
"date": "2026-05-08",
"message": "[v0.5.9](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.9) has been released, fixing a few low-severity federation-related vulnerabilities. It is recommended you read the changelog and update as soon as possible. There are no new features or other changes in this release, only related bugfixes. Deployments tracking the main branch should also update to the latest commit."
"date": "2026-07-30",
"message": "[Continuwuity 26.7.2](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v26.7.2) (and [v26.7.1](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v26.7.1)) have been released! v26.7.1 includes several new bug fixes and features, such as the OAuth2 device authorization flow, and a fix for the \"empty room\" bug (check the release notes!). v26.7.2 is a hotfix that fixes a lowseverity vulnerability in simplified sliding sync (particularly relevant to multi-user homeservers) and two regressions. It is recommended every deployment upgrades as soon as possible. Join the [announcements room](https://matrix.to/#/#announcements:continuwuity.org) for more prompt announcements regarding updates!"
Ensure no appservice puppets are marked as deactivated. This is a debug command to fix issues caused by a faulty database migration in Continuwuity 26.6.0
Issue an access token for a user. This command will not work on shadow users, such as appservice puppets or accounts imported from an identity provider
## `!admin users reset-password`
Reset user password
## `!admin users issue-password-reset-link`
Issue a self-service password reset link for a user
## `!admin users get-email`
Get a user's associated email address
@@ -96,6 +96,14 @@ ## `!admin users list-users`
List local users in the database
## `!admin users list-invited-rooms`
Lists all the rooms (local and remote) that the specified user is invited to
## `!admin users reject-all-invites`
Manually make a user reject all current invites
## `!admin users list-joined-rooms`
Lists all the rooms (local and remote) that the specified user is joined in
Some slowness is to be expected if you're the first person on your homserver to join a room (which will
Some slowness is to be expected if you're the first person on your homeserver to join a room (which will
always be the case for single-user homeservers). In this situation, your homeserver has to verify the signatures of
all of the state events sent by other servers before your join. To make this process as fast as possible, make sure you have
multiple fast, trusted servers listed in `trusted_servers` in your configuration, and ensure
@@ -60,7 +60,7 @@ ### DNS server overload
Matrix federation is extremely heavy and sends wild amounts of DNS requests. This makes normal resolvers like the ones above unsuitable for its activity. Ultimately, the best solution/fix for this is to selfhost a high quality caching DNS resolver such as Unbound, and configure Continuwuity to use it.
Follow the [**DNS tuning guide**](./advanced/dns) for details on setting it up.
Follow the [**DNS tuning guide**](./guides/dns) for details on setting it up.
### Intermittent federation failures to a specific server
/// Ensure no appservice puppets are marked as deactivated.
/// This is a debug command to fix issues caused by a faulty database
/// migration in Continuwuity 26.6.0.
#[clap(hide = true)]
EnsurePuppetsActive,
}
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.