mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-08-11 07:09:42 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74c453d606 | ||
|
|
523e7548d6 | ||
|
|
6535246094 | ||
|
|
6115bb3101 | ||
|
|
61f6930b5d | ||
|
|
2fb63f4cbc | ||
|
|
fcc8b3d697 | ||
|
|
5ead900e4a | ||
|
|
5b0aacb57f | ||
|
|
3f2d0ae2ff | ||
|
|
5d461d2023 | ||
|
|
836748b569 | ||
|
|
643ca38710 | ||
|
|
ef1506204d | ||
|
|
9589501db5 | ||
|
|
3a8040ccf1 |
@@ -44,7 +44,7 @@ runs:
|
||||
|
||||
- name: Login to builtin registry
|
||||
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
|
||||
with:
|
||||
registry: ${{ env.BUILTIN_REGISTRY }}
|
||||
username: ${{ inputs.registry_user }}
|
||||
|
||||
@@ -79,7 +79,7 @@ runs:
|
||||
|
||||
- name: Login to builtin registry
|
||||
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
|
||||
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
|
||||
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
|
||||
with:
|
||||
registry: ${{ env.BUILTIN_REGISTRY }}
|
||||
username: ${{ inputs.registry_user }}
|
||||
|
||||
@@ -71,7 +71,7 @@ runs:
|
||||
|
||||
- name: Install timelord-cli and git-warp-time
|
||||
if: steps.check-binaries.outputs.need-install == 'true'
|
||||
uses: https://github.com/taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2
|
||||
uses: https://github.com/taiki-e/install-action@a6b2e2dcd845ddd7f509ce4f3ed3d922b80cc5d9 # v2
|
||||
with:
|
||||
tool: git-warp-time,timelord-cli@3.0.1
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
container: [ "ubuntu-latest", "ubuntu-previous", "debian-latest", "debian-oldstable" ]
|
||||
arch: [ "amd64", "arm64" ]
|
||||
container:
|
||||
image: "ghcr.io/tcpipuk/act-runner:${{ matrix.container }}"
|
||||
|
||||
@@ -55,9 +54,9 @@ jobs:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}-
|
||||
cargo-debian-${{ steps.debian-version.outputs.distribution }}-
|
||||
|
||||
- name: Setup sccache
|
||||
uses: https://git.tomfos.tr/tom/sccache-action@v1
|
||||
@@ -71,55 +70,11 @@ jobs:
|
||||
# Aggressive GC since cache restores don't increment counter
|
||||
echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV
|
||||
|
||||
- name: Install cross-compilation tools for arm64
|
||||
if: matrix.arch == 'arm64'
|
||||
run: |
|
||||
dpkg --add-architecture arm64
|
||||
if ! apt-get update; then
|
||||
# Older Ubuntu releases (e.g. noble) advertise arm64 in their
|
||||
# Release files but only serve amd64/i386 from archive.ubuntu.com,
|
||||
# so apt update 404s. Restrict the main sources to amd64 and
|
||||
# fetch arm64 from ports.ubuntu.com instead.
|
||||
CODENAME=$(lsb_release -sc)
|
||||
# deb822 sources (noble and newer)
|
||||
if [ -f /etc/apt/sources.list.d/ubuntu.sources ]; then
|
||||
sed -i '/^Components:/a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources
|
||||
fi
|
||||
# one-line sources (jammy and older)
|
||||
if [ -f /etc/apt/sources.list ]; then
|
||||
sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
|
||||
fi
|
||||
printf 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports %s main restricted universe multiverse\n' \
|
||||
"$CODENAME" "$CODENAME-updates" "$CODENAME-security" \
|
||||
> /etc/apt/sources.list.d/arm64-ports.list
|
||||
apt-get update
|
||||
fi
|
||||
apt-get install -y \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
libc6-dev-arm64-cross
|
||||
|
||||
- name: Setup Rust
|
||||
uses: ./.forgejo/actions/setup-rust
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PUBLIC_RO }}
|
||||
|
||||
- name: Add Rust target
|
||||
run: |
|
||||
TARGET=${{ matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}
|
||||
rustup target add $TARGET
|
||||
|
||||
- name: Configure cross-compilation for arm64
|
||||
if: matrix.arch == 'arm64'
|
||||
run: |
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV
|
||||
# rust-rocksdb's build script probes liburing via pkg-config, which
|
||||
# refuses to run when host != target unless explicitly allowed
|
||||
echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV
|
||||
echo "PKG_CONFIG_PATH_aarch64_unknown_linux_gnu=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV
|
||||
|
||||
- name: Get package version and component
|
||||
id: package-meta
|
||||
run: |
|
||||
@@ -165,26 +120,21 @@ jobs:
|
||||
apt-get update -y
|
||||
# Build dependencies for rocksdb
|
||||
apt-get install -y liburing-dev clang
|
||||
# For arm64 builds, install cross-compiled dependencies.
|
||||
# libstdc++6:arm64 is needed by dpkg-shlibdeps to resolve the
|
||||
# dynamically-linked libstdc++ when cargo-deb computes $auto depends.
|
||||
if [ "${{ matrix.arch }}" = "arm64" ]; then
|
||||
apt-get install -y liburing-dev:arm64 libstdc++6:arm64
|
||||
fi
|
||||
|
||||
- name: Run cargo-deb
|
||||
id: cargo-deb
|
||||
run: |
|
||||
TARGET=${{ matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu' }}
|
||||
DEB_PATH=$(cargo deb --target $TARGET --deb-version ${{ steps.package-meta.outputs.version }})
|
||||
DEB_PATH=$(cargo deb --deb-version ${{ steps.package-meta.outputs.version }})
|
||||
echo "path=$DEB_PATH" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Test deb installation
|
||||
if: matrix.arch == 'amd64'
|
||||
run: |
|
||||
echo "Installing: ${{ steps.cargo-deb.outputs.path }}"
|
||||
|
||||
apt-get install -y ${{ steps.cargo-deb.outputs.path }}
|
||||
|
||||
dpkg -s continuwuity
|
||||
|
||||
[ -f /usr/bin/conduwuit ] && echo "✅ Binary installed successfully"
|
||||
[ -f /usr/lib/systemd/system/conduwuit.service ] && echo "✅ Systemd service installed"
|
||||
[ -f /etc/conduwuit/conduwuit.toml ] && echo "✅ Config file installed"
|
||||
@@ -192,7 +142,7 @@ jobs:
|
||||
- name: Upload deb artifact
|
||||
uses: forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: continuwuity-${{ steps.debian-version.outputs.distribution }}-${{ matrix.arch }}
|
||||
name: continuwuity-${{ steps.debian-version.outputs.distribution }}
|
||||
path: ${{ steps.cargo-deb.outputs.path }}
|
||||
|
||||
- name: Publish to Forgejo package registry
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
# repositories: continuwuity
|
||||
|
||||
- name: Install regsync
|
||||
uses: https://github.com/regclient/actions/regsync-installer@78eb729dbdb4ef6480e85ff697b4410e22112583 # main
|
||||
uses: https://github.com/regclient/actions/regsync-installer@c48159175b58fb90cccd0f98410927a81e04a166 # main
|
||||
|
||||
- name: Check what images need mirroring
|
||||
run: |
|
||||
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check for file changes
|
||||
uses: https://github.com/dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4
|
||||
uses: https://github.com/dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
name: Renovate
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/renovatebot/renovate:43.288.0@sha256:bcde7a061ab42d1ae6d4500769d80727e5694bb889dbcbf1005e9f4e741ab76d
|
||||
image: ghcr.io/renovatebot/renovate:43.272.6@sha256:e9dee374e7a32827af434362c6e503aa179168a96a8212cc4a5c64bb5c550142
|
||||
options: --tmpfs /tmp:exec
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -24,7 +24,7 @@ repos:
|
||||
- id: check-added-large-files
|
||||
|
||||
- repo: https://github.com/crate-ci/typos
|
||||
rev: v1.49.0
|
||||
rev: v1.48.0
|
||||
hooks:
|
||||
- id: typos
|
||||
- id: typos
|
||||
|
||||
+111
-138
@@ -1,61 +1,11 @@
|
||||
# Continuwuity v26.7.2 (2026-07-30)
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- 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.
|
||||
- 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)
|
||||
|
||||
@@ -71,6 +21,7 @@ ## Bugfixes
|
||||
- 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
|
||||
@@ -80,15 +31,19 @@ ## Features
|
||||
- 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.
|
||||
- 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)
|
||||
- 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 `!admin debug get-state-at` command (#1877)
|
||||
- Added a configuration option to allow choosing a client IP source that is not the TCP connecting IP. Contributed by @nex. (#1931)
|
||||
@@ -100,12 +55,10 @@ ## Features
|
||||
|
||||
## 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)
|
||||
- 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 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.
|
||||
@@ -132,8 +85,8 @@ ## 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
|
||||
- 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)
|
||||
|
||||
@@ -151,6 +104,7 @@ ## 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
|
||||
@@ -192,6 +146,7 @@ ## Misc
|
||||
|
||||
- Fixed compiler warning in cf_opts.rs when building in release. Contributed by @ezera. (#1620)
|
||||
|
||||
|
||||
# Continuwuity 0.5.6 (2026-03-03)
|
||||
|
||||
## Security
|
||||
@@ -201,33 +156,22 @@ ## 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 ([#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))
|
||||
- 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 broken. ([#1434](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1434))
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- 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. ([#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 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 ([#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 `!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.
|
||||
@@ -237,15 +181,19 @@ # Continuwuity v0.5.5 (2026-02-15)
|
||||
## Features
|
||||
|
||||
- Added unstable support for [MSC4406:
|
||||
`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
|
||||
([#1349](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1349))
|
||||
- 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
|
||||
([#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 ([#1349](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1349))
|
||||
- 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 ([#1372](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1372))
|
||||
- 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.
|
||||
|
||||
@@ -253,10 +201,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. ([#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 sliding sync not resolving wildcard state key requests, enabling Video/Audio calls in Element X. ([#1370](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1370))
|
||||
|
||||
## Misc
|
||||
@@ -267,78 +215,100 @@ # Continuwuity v0.5.4 (2026-02-08)
|
||||
|
||||
## Features
|
||||
|
||||
- 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
|
||||
([#1288](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1288))
|
||||
- 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
|
||||
([#1316](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1316))
|
||||
- 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))
|
||||
- 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 ([#1288](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1288))
|
||||
- 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 ([#1316](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1316))
|
||||
- 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 @Jade ([#1290](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1290))
|
||||
- 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
|
||||
([#1305](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1305))
|
||||
- Use exists instead of contains to save writing to a buffer in `src/service/users/mod.rs`: `is_login_disabled`. Contributed by @aprilgrimoire.
|
||||
([#1340](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1340))
|
||||
- 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).
|
||||
- Fix the generated configuration containing uncommented optional sections. Contributed by
|
||||
@Jade ([#1290](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1290))
|
||||
- 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 ([#1305](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1305))
|
||||
- Use exists instead of contains to save writing to a buffer in `src/service/users/mod.rs`: `is_login_disabled`.
|
||||
Contributed
|
||||
by @aprilgrimoire. ([#1340](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1340))
|
||||
- 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 @julian45 ([#1342](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1342))
|
||||
- Fixed Fedora install instructions. Contributed by
|
||||
@julian45 ([#1342](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1342))
|
||||
|
||||
# Continuwuity 0.5.3 (2026-01-12)
|
||||
|
||||
## Features
|
||||
|
||||
- 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))
|
||||
- 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 @nex ([#1286](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1286))
|
||||
- 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 @ginger ([#1280](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1280))
|
||||
- Improve admin command documentation generation. Contributed by
|
||||
@ginger ([#1280](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1280))
|
||||
|
||||
## Misc
|
||||
|
||||
- Improve timeout-related code for federation and URL previews. Contributed by @Jade ([#1278](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1278))
|
||||
- Improve timeout-related code for federation and URL previews. Contributed by
|
||||
@Jade ([#1278](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1278))
|
||||
|
||||
# Continuwuity 0.5.2 (2026-01-09)
|
||||
|
||||
## Features
|
||||
|
||||
- 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 registration tokens. 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.
|
||||
([#1263](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1263))
|
||||
- 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))
|
||||
- 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 registration
|
||||
tokens. 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. ([#1263](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1263))
|
||||
- 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. (
|
||||
[#1272](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1272))
|
||||
- Add support for custom room create event timestamps, to allow generating custom prefixes in hashed room IDs. Contributed by @nex.
|
||||
([#1277](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1277))
|
||||
- Certain potentially dangerous admin commands are now restricted to only be usable in the admin room and server console. Contributed by @ginger.
|
||||
- Add support for custom room create event timestamps, to allow generating custom prefixes in hashed room IDs.
|
||||
Contributed by @nex. ([#1277](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1277))
|
||||
- Certain potentially dangerous admin commands are now restricted to only be usable in the admin room and server
|
||||
console. Contributed by @ginger.
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fixed unreliable room summary fetching and improved error messages. Contributed by @nex. ([#1257](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1257))
|
||||
- Client requested timeout parameter is now applied to e2ee key lookups and claims. Related federation requests are now also concurrent. Contributed by @nex.
|
||||
([#1261](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1261))
|
||||
- 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))
|
||||
- Fixed unreliable room summary fetching and improved error messages. Contributed by
|
||||
@nex. ([#1257](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1257))
|
||||
- Client requested timeout parameter is now applied to e2ee key lookups and claims. Related federation requests are now
|
||||
also concurrent. Contributed by @nex. ([#1261](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1261))
|
||||
- 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
|
||||
|
||||
# Continuwuity 0.5.0 (2025-12-30)
|
||||
@@ -347,9 +317,12 @@ # Continuwuity 0.5.0 (2025-12-30)
|
||||
|
||||
## Features
|
||||
|
||||
- Enabled the OTLP exporter in default builds, and allow configuring the exporter protocol. (@Jade). ([#1251](https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1251))
|
||||
- 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 (@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))
|
||||
- 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))
|
||||
|
||||
Generated
+191
-200
File diff suppressed because it is too large
Load Diff
+8
-7
@@ -12,7 +12,7 @@ license = "Apache-2.0"
|
||||
# See also `rust-toolchain.toml`
|
||||
readme = "README.md"
|
||||
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
||||
version = "26.7.2"
|
||||
version = "26.6.2"
|
||||
|
||||
[workspace.metadata.crane]
|
||||
name = "conduwuit"
|
||||
@@ -342,8 +342,9 @@ version = "1.1.1"
|
||||
|
||||
# Used for matrix spec type definitions and helpers
|
||||
[workspace.dependencies.ruma]
|
||||
git = "https://github.com/ruma/ruma.git"
|
||||
rev = "c1100793d2fd464be34052773360f3f3773d0fc4"
|
||||
# version = "0.14.1"
|
||||
git = "https://github.com/gingershaped/ruwuma.git"
|
||||
rev = "66811f042b1bdc147dab3c45f697383e902f28c0"
|
||||
features = [
|
||||
"appservice-api-c",
|
||||
"client-api",
|
||||
@@ -356,6 +357,7 @@ features = [
|
||||
"compat-upload-signatures",
|
||||
"compat-optional-txn-pdus",
|
||||
"compat-get-3pids",
|
||||
"unstable-msc2666",
|
||||
"unstable-msc2867",
|
||||
"unstable-msc2870",
|
||||
"unstable-msc3061",
|
||||
@@ -377,9 +379,8 @@ features = [
|
||||
"unstable-msc4293",
|
||||
"unstable-msc4406",
|
||||
"unstable-msc4439",
|
||||
"unstable-msc4354",
|
||||
"unstable-msc4480",
|
||||
"unstable-msc4466",
|
||||
"unstable-msc4484",
|
||||
"unstable-extensible-events",
|
||||
]
|
||||
|
||||
@@ -503,7 +504,7 @@ default-features = false
|
||||
version = "0.1"
|
||||
|
||||
[workspace.dependencies.syn]
|
||||
version = "3.0"
|
||||
version = "2.0"
|
||||
default-features = false
|
||||
features = ["full", "extra-traits"]
|
||||
|
||||
@@ -564,7 +565,7 @@ features = ["std"]
|
||||
version = "0.3.0"
|
||||
|
||||
[workspace.dependencies.resolvematrix]
|
||||
version = "1.3.0"
|
||||
version = "1.2.0"
|
||||
|
||||
[workspace.dependencies.serde_urlencoded]
|
||||
version = "0.7.1"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Added support for the OAuth2 device authorization flow. Contributed by @ginger
|
||||
@@ -1 +0,0 @@
|
||||
Update backup instructions: the right paths for `.sst` files are now in `$DATABASE_BACKUP_PATH/private/<number>` path instead of `$DATABASE_BACKUP_PATH/<number>`. Contributed by @stratself
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
Appservices are now properly able to create devices for E2EE.
|
||||
@@ -1 +0,0 @@
|
||||
Added MSC4480 sticky events to simplified sliding sync. Contributed by @eleboucher.
|
||||
@@ -1 +0,0 @@
|
||||
Added scoped typing updates to simplified Sliding Sync (MSC4508). Contributed by @eleboucher.
|
||||
@@ -1 +0,0 @@
|
||||
Replace deprecated `docker-compose` commands with `docker compose` to reflect latest Docker changes.
|
||||
@@ -0,0 +1 @@
|
||||
Resolve alias service by correct name for auto-join. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Fixed typing notifications not interrupting a sync long poll. Contributed by @eleboucher.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed newly created rooms failing to sync properly in clients using legacy sync.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed newly joined rooms failing to sync their full state (including the room name) to clients using legacy sync.
|
||||
@@ -1 +0,0 @@
|
||||
Updated Ruma dependencies. Contributed by @eleboucher.
|
||||
@@ -1 +0,0 @@
|
||||
Fixed missed wake-ups and stale responses in legacy and sliding sync long polls. Contributed by @eleboucher.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed `roomuserid_lastnotificationread` being aliased to the highlight count table, which clobbered highlight counts when setting a read marker. Contributed by @eleboucher
|
||||
@@ -1 +0,0 @@
|
||||
Livekit docs: `room.auto_create: false` is now included in default `livekit.yaml`, following `lk-jwt-service` recommendation.
|
||||
@@ -1 +0,0 @@
|
||||
Add caveat and workaround for container resolution (e.g. for dockerized appservices) when using mounted `/etc/resolv.conf`. Contributed by @stratself
|
||||
@@ -0,0 +1 @@
|
||||
Fixed freshly left room failing to sync.
|
||||
@@ -1 +0,0 @@
|
||||
Added MSC4354 sticky events, behind the `allow_sticky_events` config option. Contributed by @eleboucher.
|
||||
@@ -0,0 +1 @@
|
||||
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.
|
||||
@@ -1 +0,0 @@
|
||||
Added MSC4186 direct, encrypted, and room-type list filters, resolving invited rooms from their stripped invite state. Contributed by @eleboucher.
|
||||
@@ -0,0 +1 @@
|
||||
Fetch the joined member count once per event instead of once per notified user.
|
||||
@@ -1 +0,0 @@
|
||||
Preserve all users' read receipts when batching room receipt updates.
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
Fixed the deeplink redirect for deleting devices. Contributed by @koen
|
||||
@@ -0,0 +1 @@
|
||||
Fix status code for oauth registration. Contributed by @n00byking
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
Exempt m.room.create from auth_events check. Contributed by @eleboucher
|
||||
@@ -0,0 +1 @@
|
||||
Fixed `create` being returned as a supported prompt value regardless of if registration is enabled or not. Contributed by @ginger
|
||||
@@ -0,0 +1 @@
|
||||
Updated an out-of-date statement about Oracle Linux release cadences.
|
||||
@@ -0,0 +1 @@
|
||||
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.
|
||||
@@ -0,0 +1 @@
|
||||
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.
|
||||
@@ -1 +0,0 @@
|
||||
Updated admin command names (list-users -> list, list-rooms -> list, and reload-mods -> reload), old names are now aliases. Contributed by @PerformativeJade
|
||||
@@ -0,0 +1 @@
|
||||
Deactivated users and appservice puppets are no longer counted by `/_continuwuity/local_user_count`. Contributed by @ginger.
|
||||
@@ -1 +0,0 @@
|
||||
Updated the docs to reflect the current default User-Agent for URL previews
|
||||
@@ -1 +0,0 @@
|
||||
Resolve membership service by correct name for auto-join. Contributed by @Aranjedeath
|
||||
@@ -1 +0,0 @@
|
||||
Plugged a logic gap that may have been allowing Continuwuity to process events with incorrect room versions under certain conditions. Contributed by @nex.
|
||||
@@ -1 +0,0 @@
|
||||
Added missing documentation to config parameters. Contributed by @renegadespork
|
||||
@@ -1 +0,0 @@
|
||||
The OAuth 2.0 device authorization endpoint now rejects clients which did not register the device code grant type, instead of issuing them a device code. The token endpoint now returns the `unauthorized_client` error code when a client requests a grant type it did not register, instead of `invalid_grant`. Contributed by @mmaudet.
|
||||
@@ -1 +0,0 @@
|
||||
Generic deployment documentation: Use `/etc/caddy/Caddyfile` instead of `/etc/caddy/conf.d/*` paths, which do not exist on a majority of Caddy installations.
|
||||
@@ -0,0 +1 @@
|
||||
Fix joining restricted rooms over federation failing with signature verification error.
|
||||
@@ -0,0 +1 @@
|
||||
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`.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed simplified sliding sync holding account data for up to 30 seconds, which made encryption setup and cross-signing resets appear to hang.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed local invites and invite acceptances not being reflected in sync promptly. Contributed by @eleboucher
|
||||
+18
-151
@@ -170,136 +170,43 @@
|
||||
#
|
||||
#db_write_buffer_capacity_mb = varies by system
|
||||
|
||||
# The maximum number of Persisted Data Units (PDUs) to cache.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# PDUs are events broadcast from one homeserver to any others that have
|
||||
# joined the same room (identified by Room ID). They are persisted in
|
||||
# long-term storage and record the history of messages and state
|
||||
# for a room.
|
||||
#
|
||||
# An example of a PDU would be a message or joining a room.
|
||||
#
|
||||
# Setting this higher might be useful if the server has a large memory
|
||||
# capacity and is noticeably I/O limited.
|
||||
#
|
||||
# This defaults to 100,000 + (10,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#pdu_cache_capacity = varies by system
|
||||
|
||||
# The maximum number of auth chains to cache.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# When determining is a user is authorized to send an event,
|
||||
# the server will first check the cache for an auth chain.
|
||||
# If the auth chain is not present in the cache,
|
||||
# The server will read the auth chain from the database
|
||||
# and add it to the cache.
|
||||
#
|
||||
# This defaults to 100,000 + (10,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#auth_chain_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for eventid data references.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# Each matrix event can be referenced in the database via either
|
||||
# an eventid (string) or a shorteventid (64-bit integer).
|
||||
# This caps the capacity of cached eventids referenced
|
||||
# by their shorteventid.
|
||||
#
|
||||
# This defaults to 100,000 + (50,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#shorteventid_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for eventid data references.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# Each matrix event can be referenced in the database via either
|
||||
# an eventid (string) or a shorteventid (64-bit integer).
|
||||
# This caps the capacity of cached shorteventids referenced
|
||||
# by their eventid.
|
||||
#
|
||||
# This defaults to 100,000 + (25,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#eventidshort_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for pdu data references.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# This caps the capacity of cached pdus referenced
|
||||
# by their eventid.
|
||||
#
|
||||
# This defaults to 100,000 + (25,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#eventid_pdu_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for state key data references.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# State keys are used by the server to verify that a token
|
||||
# from a third-party invite event was actually generated
|
||||
# by the server where the room resides.
|
||||
#
|
||||
# These state keys can be referenced in the database via either
|
||||
# a statekey (string) or a shortstatekey (64-bit integer).
|
||||
# This caps the capacity of cached statekeys referenced
|
||||
# by shortstatekeys.
|
||||
#
|
||||
# This defaults to 100,000 + (10,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#shortstatekey_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for state key data references.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# State keys are used by the server to verify that a token
|
||||
# from a third-party invite event was actually generated
|
||||
# by the server where the room resides.
|
||||
#
|
||||
# These state keys can be referenced in the database via either
|
||||
# a statekey (string) or a shortstatekey (64-bit integer).
|
||||
# This caps the capacity of cached shortstatekeys referenced
|
||||
# by statekeys.
|
||||
#
|
||||
# This defaults to 100,000 + (10,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#statekeyshort_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for event_data references scoped
|
||||
# by server_name.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# Event data can be referenced in the database by server name.
|
||||
# This is useful if the server needs to clear all events associated
|
||||
# with a particular federated server, for example.
|
||||
# This caps the capacity of cached event_data referenced
|
||||
# by server_name.
|
||||
#
|
||||
# This defaults to 500,000 + (100,000 * CPU core count)
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#servernameevent_data_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for room states.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# To ensure data integrity of room events across asynchronous
|
||||
# requests from federated servers, Matrix tracks the state
|
||||
# of a room using a statehash and the changes since the
|
||||
# previous (parent) statehash.
|
||||
# This caps the capacity of cached room state data.
|
||||
#
|
||||
# This defaults to 100 * CPU core count.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#stateinfo_cache_capacity = varies by system
|
||||
|
||||
# Determines the cache size for spacehierarchy data.
|
||||
# Accepts any 32-bit integer.
|
||||
#
|
||||
# Each roomid contains info on its place in the space hierarchy.
|
||||
# This caps the capacity of cached spacehierarchy data.
|
||||
#
|
||||
# This defaults to 1,000 * CPU core count.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#roomid_spacehierarchy_cache_capacity = varies by system
|
||||
|
||||
@@ -440,13 +347,7 @@
|
||||
#
|
||||
#max_request_size = 20971520
|
||||
|
||||
# Maximum number of prev_events the server will request from
|
||||
# other servers.
|
||||
#
|
||||
# When requesting room events from another server, this server will
|
||||
# specify a maximum prev_events for the other server to return in its
|
||||
# response. This can be used for things like backfilling room data and
|
||||
# getting missing events.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#max_fetch_prev_events = 1024
|
||||
|
||||
@@ -831,15 +732,11 @@
|
||||
#
|
||||
#tracing_flame = false
|
||||
|
||||
# Which log level tracing_flame will trace.
|
||||
#
|
||||
# See "tracing_flame" for more details.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#tracing_flame_filter = "info"
|
||||
|
||||
# The output path for tracing_flame data.
|
||||
#
|
||||
# See "tracing_flame" for more details.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#tracing_flame_output_path = "./tracing.folded"
|
||||
|
||||
@@ -1067,7 +964,7 @@
|
||||
#
|
||||
#rocksdb_log_level = "error"
|
||||
|
||||
# Whether to output RocksDB errors to stderr.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#rocksdb_log_stderr = false
|
||||
|
||||
@@ -1317,17 +1214,7 @@
|
||||
#
|
||||
#emergency_password =
|
||||
|
||||
# Specifies the path where push notifications will be sent to a
|
||||
# push gateway.
|
||||
#
|
||||
# When a Matrix client registers for push notifications, it will specify
|
||||
# a push gateway url where notification events will be sent.
|
||||
# According to the current spec for Matrix Push Gateways, the path should
|
||||
# always be "/_matrix/push/v1/notify".
|
||||
# You should only change this if you have configured your own push gateway
|
||||
# that requires a different path.
|
||||
#
|
||||
# For more information on Push Gateways: https://spec.matrix.org/latest/push-gateway-api/
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#notification_push_path = "/_matrix/push/v1/notify"
|
||||
|
||||
@@ -1419,12 +1306,6 @@
|
||||
#
|
||||
#allow_incoming_typing = true
|
||||
|
||||
# Allow the use of unstable persistent "sticky events" ([MSC4354])
|
||||
#
|
||||
# MSC4354: https://c10y.cc/MSC4354
|
||||
#
|
||||
#allow_sticky_events = false
|
||||
|
||||
# Maximum time federation user can indicate typing.
|
||||
#
|
||||
#typing_federation_timeout_s = 30
|
||||
@@ -1484,10 +1365,7 @@
|
||||
#
|
||||
#allow_legacy_media = true
|
||||
|
||||
# If set to true, prevents fetching new legacy remote media.
|
||||
#
|
||||
# Legacy media may still be accessible if it was already fetched
|
||||
# previously and allow_legacy_media is true.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#freeze_legacy_media = true
|
||||
|
||||
@@ -1717,7 +1595,7 @@
|
||||
|
||||
# User agent that is used specifically when fetching url previews.
|
||||
#
|
||||
#url_preview_user_agent = "continuwuity/<version> (embedbot; facebookexternalhit/1.1; +https://continuwuity.org)"
|
||||
#url_preview_user_agent = "continuwuity/<version> (bot; +https://continuwuity.org)"
|
||||
|
||||
# Determines whether audio and video files will be downloaded for URL
|
||||
# previews.
|
||||
@@ -1895,18 +1773,7 @@
|
||||
#
|
||||
#tokio_console = false
|
||||
|
||||
# A list of flags that modify startup behavior.
|
||||
# Accepts an array of strings.
|
||||
#
|
||||
# During startup, the program will check for the presence of certain
|
||||
# strings in this array. Matching values will modify how the program runs
|
||||
# those startup tasks.
|
||||
#
|
||||
# If this variable is empty or contains no matches, the server will start
|
||||
# normally.
|
||||
#
|
||||
# Currently this only checks for "smoke" which enables "Smoketest mode."
|
||||
# This mode exits the program after running startup tasks.
|
||||
# This item is undocumented. Please contribute documentation for it.
|
||||
#
|
||||
#test = false
|
||||
|
||||
|
||||
+11
-19
@@ -20,19 +20,17 @@ ## Set up the appservice - general instructions
|
||||
registered on the homeserver automatically joins it. Then send a message into
|
||||
the room like this:
|
||||
|
||||
~~~txt
|
||||
!admin appservices register
|
||||
```
|
||||
paste
|
||||
the
|
||||
contents
|
||||
of
|
||||
the
|
||||
yaml
|
||||
registration
|
||||
here
|
||||
```
|
||||
~~~
|
||||
!admin appservices register
|
||||
```
|
||||
paste
|
||||
the
|
||||
contents
|
||||
of
|
||||
the
|
||||
yaml
|
||||
registration
|
||||
here
|
||||
```
|
||||
|
||||
You can confirm it worked by sending a message like this:
|
||||
`!admin appservices list`
|
||||
@@ -53,9 +51,3 @@ ### Remove an appservice
|
||||
`!admin appservices unregister <name>`
|
||||
|
||||
where `<name>` one of the output of `appservices list`.
|
||||
|
||||
## Caveats
|
||||
|
||||
### Docker DNS
|
||||
|
||||
If you follow the [DNS tuning guide](./guides/dns.mdx#for-docker-users) and mount a custom `/etc/resolv.conf`, you may not be able to connect to appservices' containers using their hostnames. Follow the [workaround in the guide](./guides/dns.mdx#for-docker-users) to connect to your appservice using static IPs.
|
||||
|
||||
+3
-3
@@ -3,11 +3,11 @@ # Calls
|
||||
Matrix supports two types of calls:
|
||||
|
||||
- Element Call powered by [MatrixRTC](https://half-shot.github.io/msc-crafter/#msc/4143) and [LiveKit](https://github.com/livekit/livekit)
|
||||
- Legacy calls, supported by a STUN/TURN server.
|
||||
- Legacy calls, sometimes using Jitsi
|
||||
|
||||
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. 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 (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)
|
||||
|
||||
+87
-193
@@ -1,6 +1,8 @@
|
||||
# MatrixRTC/Element Call Setup
|
||||
# Matrix RTC/Element Call Setup
|
||||
|
||||
This guide assumes that you are using docker compose for deployment.
|
||||
:::info
|
||||
This guide assumes that you are using docker compose for deployment. LiveKit only provides Docker images.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
You can find help setting up MatrixRTC in our dedicated room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org)
|
||||
@@ -8,15 +10,15 @@ # MatrixRTC/Element Call Setup
|
||||
|
||||
## Instructions
|
||||
|
||||
### 1. Set up your domain
|
||||
### 1. Domain
|
||||
|
||||
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. Set up the LiveKit services
|
||||
### 2. Services
|
||||
|
||||
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.
|
||||
Using LiveKit with Matrix requires two services - LiveKit itself, and a 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!
|
||||
|
||||
@@ -79,23 +81,15 @@ # - "50100-50200:50100-50200/udp"
|
||||
LK_MATRIX_KEY: LK_MATRIX_SECRET
|
||||
# replace these with your key-secret pair. Example:
|
||||
# APIUxUnMnSkuFWV: t93ZVjPeoEdyx7Wbet3kG4L3NGZIZVEFvqe0UuiVc22A
|
||||
|
||||
# do not create rooms by default
|
||||
room:
|
||||
auto_create: false
|
||||
```
|
||||
|
||||
Consult [`config-sample.yaml`][livekit-config-sample-yaml] for all LiveKit options.
|
||||
|
||||
[livekit-config-sample-yaml]: https://github.com/livekit/livekit/blob/master/config-sample.yaml
|
||||
|
||||
#### Firewall hints
|
||||
|
||||
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 your `lk-jwt-service`'s address to the `[global.matrix_rtc] > foci` field of your Continuwuity config file.
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
@@ -106,12 +100,6 @@ ### 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:
|
||||
|
||||
- `/_matrix/client/unstable/org.matrix.msc4143/rtc/transports` (MSC4143 unstable, behind auth)
|
||||
@@ -144,11 +132,6 @@ ### 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>
|
||||
@@ -204,7 +187,6 @@ ### 4. Configure your Reverse Proxy
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Example docker compose file with caddy-docker-proxy labels</summary>
|
||||
```yaml
|
||||
@@ -280,9 +262,76 @@ ### 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.
|
||||
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.
|
||||
|
||||
First, you will need 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).
|
||||
|
||||
@@ -347,19 +396,16 @@ ## Testing
|
||||
{"url":"wss://livekit.example.com","jwt":"a_really_really_long_string"}
|
||||
```
|
||||
|
||||
Use this token to test at the [LiveKit Connection Tester][livekit-connection-test]. If everything works there, then you have set up LiveKit successfully!
|
||||
|
||||
[livekit-connection-test]: https://livekit.com/webrtc/connection-test
|
||||
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!
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
To debug any issues, you can place a call or redo the Testing instructions, and check the container logs for any specific errors. Use `docker compose logs --follow` to follow these logs in real-time.
|
||||
To debug any issues, you can place a call or redo the Testing instructions, and check the container logs for any specific errors. Use `docker-compose logs --follow` to follow these logs in real-time.
|
||||
|
||||
### Common errors in Element Call UI
|
||||
|
||||
- `MISSING_MATRIX_RTC_FOCUS`/`MISSING_MATRIX_RTC_TRANSPORT`: LiveKit is missing from Continuwuity's config file
|
||||
- `MISSING_MATRIX_RTC_FOCUS`: 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.
|
||||
|
||||
@@ -394,19 +440,6 @@ # --- 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.
|
||||
@@ -425,156 +458,17 @@ ## Related Documentation
|
||||
|
||||
Guides:
|
||||
|
||||
- [Element Call self-hosting documentation from element-hq][element-call-selfhosting]
|
||||
- [Community guide with overview of LiveKit's mechanisms][tom-livekit-guide]
|
||||
- [Community guide using systemd][kimiblock-livekit-guide]
|
||||
|
||||
[element-call-selfhosting]: https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md
|
||||
[tom-livekit-guide]: https://tomfos.tr/matrix/livekit/
|
||||
[kimiblock-livekit-guide]: https://blog.kimiblock.top/2024/12/24/hosting-element-call/
|
||||
|
||||
Configurations:
|
||||
|
||||
- [Livekit's `config-sample.yaml`][livekit-config-sample-yaml] - LiveKit configuration file with full options
|
||||
- [Element Call self-hosting documentation](https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md)
|
||||
- [Community guide with overview of LiveKit's mechanisms](https://tomfos.tr/matrix/livekit/)
|
||||
- [Community guide using systemd](https://blog.kimiblock.top/2024/12/24/hosting-element-call/)
|
||||
|
||||
Specifications:
|
||||
|
||||
- [MSC4143 - MatrixRTC proposal][MSC4143]
|
||||
- [MSC4195 - LiveKit proposal][MSC4195]
|
||||
|
||||
[MSC4143]: https://github.com/matrix-org/matrix-spec-proposals/pull/4143
|
||||
[MSC4195]: https://github.com/matrix-org/matrix-spec-proposals/pull/4195
|
||||
- [MSC4143 - MatrixRTC proposal](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)
|
||||
- [MSC4195 - LiveKit proposal](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
|
||||
|
||||
Source code:
|
||||
|
||||
- [Element Call][element-call-github]
|
||||
- [lk-jwt-service][lk-jwt-service-github]
|
||||
- [LiveKit server][livekit-server-github]
|
||||
|
||||
[element-call-github]: https://github.com/element-hq/element-call
|
||||
[lk-jwt-service-github]: https://github.com/element-hq/lk-jwt-service
|
||||
[livekit-server-github]: https://github.com/livekit/livekit
|
||||
|
||||
Other:
|
||||
|
||||
- [Matrix VOIP and LiveKit][sspaeth-matrix-voip] - Community member deep dive on current VOIP solutions on Matrix
|
||||
|
||||
[sspaeth-matrix-voip]: https://sspaeth.de/2026/04/matrix-voip-and-livekit/
|
||||
|
||||
## Appendix
|
||||
|
||||
### Additional TURNS-over-443 configuration
|
||||
|
||||
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.
|
||||
|
||||
[sspaeth-matrix-voip-turn]: https://sspaeth.de/2026/04/matrix-voip-and-livekit/#turn
|
||||
|
||||
You can either use LiveKit's built-in TURN server, or integrate LiveKit with [coturn](./turn).
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Using LiveKit's built-in TURN server</summary>
|
||||
|
||||
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".
|
||||
- [Element Call](https://github.com/element-hq/element-call)
|
||||
- [lk-jwt-service](https://github.com/element-hq/lk-jwt-service)
|
||||
- [LiveKit server](https://github.com/livekit/livekit)
|
||||
|
||||
+120
-284
@@ -1,95 +1,36 @@
|
||||
# Setting up TURN/STUN
|
||||
|
||||
[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.
|
||||
[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.
|
||||
|
||||
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)
|
||||
:::
|
||||
|
||||
[turn]: https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT
|
||||
[stun]: https://en.wikipedia.org/wiki/STUN
|
||||
[coturn]: https://github.com/coturn/coturn
|
||||
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.
|
||||
|
||||
## Installing Coturn
|
||||
|
||||
### 1. Domain
|
||||
|
||||
Coturn should live on its own domain or subdomain. In this guide we use `coturn.example.com` - this should be replaced with a domain you control.
|
||||
|
||||
### 2. Configuration
|
||||
### Configuration
|
||||
|
||||
Create a configuration file called `coturn.conf` containing:
|
||||
|
||||
```ini
|
||||
use-auth-secret
|
||||
static-auth-secret=<a secret key>
|
||||
realm=coturn.example.com
|
||||
realm=<your server domain>
|
||||
```
|
||||
|
||||
:::tip Tip: Generate a long, secure secret with the following command
|
||||
:::tip Generating a secure secret
|
||||
A common way to generate a suitable alphanumeric secret key is by using:
|
||||
```bash
|
||||
pwgen -s 64 1
|
||||
```
|
||||
:::
|
||||
|
||||
If you want to enable TURN-over-TLS (TURNS), add the appropriate cert/key paths to your `coturn.conf` by adding the following lines:
|
||||
|
||||
```ini
|
||||
cert=/etc/letsencrypt/coturn.example.com.crt
|
||||
pkey=/etc/letsencrypt/coturn.example.com.key
|
||||
```
|
||||
|
||||
The cert and key must be encoded in PEM format and are readable by the coturn user.
|
||||
|
||||
Check out the [`turnserver.conf`][turnserver-conf] example for all coturn options.
|
||||
|
||||
[turnserver-conf]: https://github.com/coturn/coturn/blob/master/examples/etc/turnserver.conf
|
||||
|
||||
### 3. Running the coturn container
|
||||
|
||||
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).
|
||||
|
||||
[coturn-image]: https://hub.docker.com/r/coturn/coturn
|
||||
[coturn-docker-docs]: https://github.com/coturn/coturn/blob/master/docker/coturn/README.md#why-so-many-ports-opened
|
||||
|
||||
Create a `docker-compose.yml` file as follows and run `docker compose up -d`:
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
coturn:
|
||||
container_name: coturn
|
||||
image: docker.io/coturn/coturn
|
||||
restart: unless-stopped
|
||||
network_mode: "host"
|
||||
volumes:
|
||||
- ./coturn.conf:/etc/coturn/turnserver.conf
|
||||
# replace this with actual paths to your certificates
|
||||
- /path/to/certs:/etc/letsencrypt
|
||||
```
|
||||
|
||||
### 4. Opening ports
|
||||
#### Port Configuration
|
||||
|
||||
By default, coturn uses the following ports:
|
||||
- `3478` (UDP/TCP): Standard TURN/STUN port
|
||||
- `5349` (UDP/TCP): TURN/STUN over TLS
|
||||
- `49152-65535` (UDP): Media relay ports
|
||||
|
||||
You will need to allow them through your firewall. If you use UFW, the commands are:
|
||||
|
||||
```bash
|
||||
ufw allow 3478/udp
|
||||
ufw allow 3478/tcp
|
||||
ufw allow 5349/tcp
|
||||
ufw allow 5349/udp
|
||||
ufw allow 49152-65535/udp
|
||||
```
|
||||
|
||||
::: tip For LiveKit users
|
||||
|
||||
If you're also running LiveKit, you'll need configure non-overlapping port ranges to avoid port conflicts:
|
||||
If you're also running LiveKit, you'll need to avoid port conflicts. Configure non-overlapping port ranges:
|
||||
|
||||
```ini
|
||||
# In coturn.conf
|
||||
@@ -97,33 +38,57 @@ # In coturn.conf
|
||||
max-port=65535
|
||||
```
|
||||
|
||||
```bash
|
||||
# With ufw
|
||||
ufw allow 50201:65535/udp
|
||||
```
|
||||
|
||||
This leaves ports `50100-50200` available for LiveKit's default configuration.
|
||||
|
||||
### Running with Docker
|
||||
|
||||
Run the [Coturn](https://hub.docker.com/r/coturn/coturn) image using:
|
||||
|
||||
```bash
|
||||
docker run -d --network=host \
|
||||
-v $(pwd)/coturn.conf:/etc/coturn/turnserver.conf \
|
||||
coturn/coturn
|
||||
```
|
||||
|
||||
### Running with Docker Compose
|
||||
|
||||
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).
|
||||
:::
|
||||
|
||||
### 5. Security Recommendations
|
||||
### Security Recommendations
|
||||
|
||||
For Coturn hardening and security best practices, see Synapse's [Coturn documentation][synapse-coturn-guide],
|
||||
which includes important firewall and access control recommendations.
|
||||
|
||||
[synapse-coturn-guide]: https://element-hq.github.io/synapse/latest/setup/turn/coturn.html#configuration
|
||||
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.
|
||||
|
||||
## Configuring Continuwuity
|
||||
|
||||
Once your TURN server is running, configure Continuwuity to provide credentials to clients. Add the following to your Continuwuity configuration file:
|
||||
|
||||
### Shared Secret Authentication (Recommended)
|
||||
|
||||
This is the most secure method and generates time-limited credentials automatically:
|
||||
|
||||
```toml
|
||||
# TURN URIs that clients should connect to
|
||||
turn_uris = [
|
||||
"turn:coturn.example.com:3478?transport=udp",
|
||||
"turn:coturn.example.com:3478?transport=tcp",
|
||||
# Add this if you're using TURN-over-TLS (note the `turns:` prefix)
|
||||
"turns:coturn.example.com:5349?transport=tcp"
|
||||
"turn:coturn.example.com?transport=udp",
|
||||
"turn:coturn.example.com?transport=tcp",
|
||||
"turns:coturn.example.com?transport=udp",
|
||||
"turns:coturn.example.com?transport=tcp"
|
||||
]
|
||||
|
||||
# Shared secret for generating credentials (must match coturn's static-auth-secret)
|
||||
@@ -133,18 +98,54 @@ # Optional: Read secret from a file instead (takes priority over turn_secret)
|
||||
# turn_secret_file = "/etc/continuwuity/.turn_secret"
|
||||
|
||||
# TTL for generated credentials in seconds (default: 86400 = 24 hours)
|
||||
turn_ttl = 10800
|
||||
turn_ttl = 86400
|
||||
```
|
||||
|
||||
Restart Continuwuity, and the new changes should now be applied.
|
||||
:::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
|
||||
|
||||
## Testing Your TURN Server
|
||||
|
||||
### Testing Credentials
|
||||
|
||||
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:
|
||||
Verify that Continuwuity is correctly serving TURN credentials to clients:
|
||||
|
||||
```bash
|
||||
curl "https://matrix.example.com/_matrix/client/r0/voip/turnServer" \
|
||||
@@ -158,221 +159,56 @@ ### Testing Credentials
|
||||
"username": "1752792167:@jade:example.com",
|
||||
"password": "KjlDlawdPbU9mvP4bhdV/2c/h65=",
|
||||
"uris": [
|
||||
"turns:coturn.example.com:3478?transport=tcp",
|
||||
"turn:coturn.example.com:3478?transport=udp",
|
||||
"turn:coturn.example.com:5349?transport=tcp"
|
||||
"turns:coturn.example.com?transport=udp",
|
||||
"turns:coturn.example.com?transport=tcp",
|
||||
"turn:coturn.example.com?transport=udp",
|
||||
"turn:coturn.example.com?transport=tcp"
|
||||
],
|
||||
"ttl": 86400
|
||||
}
|
||||
```
|
||||
|
||||
:::note MSC4166 Compliance
|
||||
If no TURN URIs are configured (`turn_uris` is empty), Continuwuity will return a 404 Not Found response, as specified in MSC4166.
|
||||
:::
|
||||
|
||||
### Testing Connectivity
|
||||
|
||||
Open the [Trickle ICE][trickle-ice] testing page in a browser and then:
|
||||
Use [Trickle ICE](https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/) to verify that the TURN credentials actually work:
|
||||
|
||||
1. Copy the URIs and credentials from the response above
|
||||
2. Paste them into the Trickle ICE testing tool, and click on "Add server"
|
||||
3. When finished adding all URIs and credentials, click "Gather candidates"
|
||||
1. Copy the credentials from the response above
|
||||
2. Paste them into the Trickle ICE testing tool
|
||||
3. Click "Gather candidates"
|
||||
4. Look for successful `relay` candidates in the results
|
||||
|
||||
If you see `relay` candidates in the results, your TURN/STUN server is working correctly! You should now be able to place and receive legacy calls.
|
||||
|
||||
[trickle-ice]: https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
|
||||
If you see relay candidates, your TURN server is working correctly!
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
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`.
|
||||
### Clients can't connect to TURN server
|
||||
|
||||
### Errors with Trickle ICE
|
||||
- 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
|
||||
|
||||
- `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.
|
||||
### Port conflicts with LiveKit
|
||||
|
||||
### 404 when calling the turnServer endpoint
|
||||
- Make sure coturn's `min-port` starts above LiveKit's `port_range_end` (default: 50200)
|
||||
- Or adjust LiveKit's port range to avoid coturn's default range
|
||||
|
||||
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.
|
||||
### 404 when calling turnServer endpoint
|
||||
|
||||
[msc4166]: https://github.com/matrix-org/matrix-spec-proposals/pull/4166
|
||||
- Verify that `turn_uris` is not empty in your Continuwuity config
|
||||
- This behavior is correct per MSC4166 if no TURN URIs are configured
|
||||
|
||||
## Related Documentation
|
||||
### Credentials expire too quickly
|
||||
|
||||
- Adjust the `turn_ttl` value in your Continuwuity configuration
|
||||
- Default is 86400 seconds (24 hours)
|
||||
|
||||
### Related Documentation
|
||||
|
||||
- [MatrixRTC/LiveKit Setup](./livekit.mdx) - Configure group calling with LiveKit
|
||||
- [Coturn GitHub][coturn] - Official coturn repository
|
||||
- [`turnserver.conf`][turnserver-conf] - Coturn TURN SERVER configuration file with full options
|
||||
- [Synapse TURN Guide][synapse-turn-guide] - TURN server guide for Synapse
|
||||
- [Synapse Coturn Guide][synapse-coturn-guide] - Coturn-specific guide for Synapse, with important security recommendations
|
||||
|
||||
[synapse-turn-guide]: https://element-hq.github.io/synapse/latest/turn-howto.html
|
||||
|
||||
## Appendix
|
||||
|
||||
### Using Eturnal
|
||||
|
||||
If you instead prefer to use [eturnal][eturnal], you can refer to the guides below:
|
||||
|
||||
- [Community guidance][eturnal-continuwuity] on using eturnal with Legacy Calls, LiveKit calls, and more
|
||||
- Synapse's [eturnal documentation][synapse-eturnal-guide]
|
||||
|
||||
[eturnal]: https://eturnal.net
|
||||
[eturnal-continuwuity]: https://muoi.me/~stratself/articles/an-eturnal-to-rule-them-all/
|
||||
[synapse-eturnal-guide]: https://element-hq.github.io/synapse/latest/setup/turn/eturnal.html
|
||||
|
||||
### TURNS-over-443
|
||||
|
||||
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:
|
||||
|
||||
```ini
|
||||
# In coturn.conf
|
||||
|
||||
# Comment out options to use a secret
|
||||
# use-auth-secret
|
||||
# static-auth-secret=<a secret key>
|
||||
|
||||
# Define a username-password pair
|
||||
user=your_username:your_password
|
||||
```
|
||||
|
||||
```toml
|
||||
# In continuwuity.toml
|
||||
turn_uris = [
|
||||
"turn:coturn.example.com?transport=udp",
|
||||
"turn:coturn.example.com?transport=tcp"
|
||||
]
|
||||
|
||||
turn_username = "your_username"
|
||||
turn_password = "your_password"
|
||||
```
|
||||
|
||||
</details>
|
||||
- [Coturn GitHub](https://github.com/coturn/coturn) - Official coturn repository
|
||||
- [Synapse TURN Guide](https://element-hq.github.io/synapse/latest/turn-howto.html) - Additional security recommendations
|
||||
|
||||
@@ -9,7 +9,7 @@ ### Choose an image
|
||||
| Image | Notes |
|
||||
| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||
| [https://forgejo.ellis.link/continuwuation/continuwuity:**latest**][latest] | Latest tagged release. (recommended) |
|
||||
| [https://forgejo.ellis.link/continuwuation/continuwuity:**main**][main] | Latest `main` branch commit. Built with [CI][release-image] |
|
||||
| [https://forgejo.ellis.link/continuwuation/continuwuity:**main**][main] | Latest `main` branch commit. |
|
||||
| [https://forgejo.ellis.link/continuwuation/continuwuity:**latest-maxperf**][latest-maxperf] | Latest tagged release, [performance optimised version](./generic.mdx#performance-optimised-builds). |
|
||||
| [https://forgejo.ellis.link/continuwuation/continuwuity:**main-maxperf**][main-maxperf] | Latest `main` branch commit, [performance optimised version](./generic.mdx#performance-optimised-builds). |
|
||||
|
||||
@@ -17,7 +17,6 @@ ### Choose an image
|
||||
[main]: https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main
|
||||
[latest-maxperf]: https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/latest-maxperf
|
||||
[main-maxperf]: https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main-maxperf
|
||||
[release-image]: https://forgejo.ellis.link/continuwuation/continuwuity/actions/?workflow=release-image.yml
|
||||
|
||||
If you want a specific version or commit hash, you can browse for them [here][oci-all-versions].
|
||||
|
||||
@@ -26,11 +25,13 @@ ### Choose an image
|
||||
- `ghcr.io/continuwuity/continuwuity` ([Github Registry][ghcr-io])
|
||||
- `docker.io/jadedblueeyes/continuwuity` ([Docker Hub][docker-hub])
|
||||
- `registry.gitlab.com/continuwuity/continuwuity` ([Gitlab Registry][gitlab-registry])
|
||||
- `git.nexy7574.co.uk/mirrored/continuwuity` ([Nexy's forge][nexy-forge]. Releases only, no `main` tags)
|
||||
|
||||
[oci-all-versions]: https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/versions
|
||||
[ghcr-io]: https://github.com/continuwuity/continuwuity/pkgs/container/continuwuity/versions?filters%5Bversion_type%5D=tagged
|
||||
[docker-hub]: https://hub.docker.com/r/jadedblueeyes/continuwuity/
|
||||
[gitlab-registry]: https://gitlab.com/continuwuity/continuwuity/container_registry/8871720
|
||||
[nexy-forge]: https://git.nexy7574.co.uk/mirrored/-/packages/container/continuwuity/versions
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -62,8 +63,8 @@ ### Choose Your Reverse Proxy
|
||||
|
||||
These examples include reverse proxy configurations for Matrix federation, which will route your Matrix domain (and optionally .well-known paths) to Continuwuity.
|
||||
|
||||
:::important Docker DNS Performance
|
||||
Docker's default DNS resolver is known to [**cause timeout issues**](../troubleshooting#dns-issues) for Matrix federation. To bypass it and use a more performant resolver, mount a custom `/etc/resolv.conf` config file into the Continuwuity container:
|
||||
:::note Docker DNS Performance
|
||||
Docker's default DNS resolver are known to [cause timeout issues](../troubleshooting#dns-issues) for Matrix federation. To bypass it and use a more performant resolver, mount a custom `/etc/resolv.conf` config file into the Continuwuity container.
|
||||
|
||||
```yaml title='docker-compose.yml'
|
||||
services:
|
||||
@@ -84,19 +85,8 @@ ### Choose Your Reverse Proxy
|
||||
#### Caddy (using Caddyfile)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>docker-compose.with-caddy.yml ([view raw](/deploying/docker-compose.with-caddy.yml))</summary>
|
||||
|
||||
Create a Caddyfile with the following content:
|
||||
|
||||
```
|
||||
https://example.com:443, https://example.com:8448 {
|
||||
reverse_proxy http://homeserver:8008
|
||||
}
|
||||
```
|
||||
|
||||
Then, for the docker-compose:
|
||||
|
||||
```yaml file="../public/deploying/docker-compose.with-caddy.yml"
|
||||
|
||||
```
|
||||
@@ -174,7 +164,7 @@ ### Starting Your Server
|
||||
4. Check your server logs for a registration token:
|
||||
|
||||
```bash
|
||||
docker compose logs continuwuity 2>&1
|
||||
docker-compose logs continuwuity 2>&1
|
||||
```
|
||||
|
||||
You'll see output as below.
|
||||
@@ -197,19 +187,6 @@ ## Testing
|
||||
|
||||
Check your container logs using `docker-compose logs --follow` to debug any issues. See the [Troubleshooting](../troubleshooting.mdx) page for common errors and how to fix them.
|
||||
|
||||
## Updating
|
||||
|
||||
To update to a new version of Continuwuity, use the following commands:
|
||||
|
||||
```bash
|
||||
# stop the services in docker-compose.yaml
|
||||
docker compose down
|
||||
# pull latest images for the services in docker-compose.yaml
|
||||
docker compose pull
|
||||
# spin up the containers again
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Other deployment methods
|
||||
|
||||
### Docker - Quick Run
|
||||
|
||||
+37
-33
@@ -29,12 +29,19 @@ ### Prebuilt binary
|
||||
|
||||
#### Performance-optimised builds
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
If you're using Docker instead, equivalent performance-optimised
|
||||
images are available with the `-maxperf` suffix (e.g.
|
||||
`forgejo.ellis.link/continuwuation/continuwuity:latest-maxperf`).
|
||||
These images use the `release-max-perf` build profile with
|
||||
[link-time optimisation (LTO)][lto-rust-docs]
|
||||
and, for amd64, target the haswell CPU architecture.
|
||||
|
||||
[lto-rust-docs]: https://doc.rust-lang.org/cargo/reference/profiles.html#lto
|
||||
|
||||
@@ -52,7 +59,28 @@ ### Nix
|
||||
|
||||
### Compiling
|
||||
|
||||
Alternatively, you may compile the binary yourself. See the [Appendix subsection](#compiling-continuwuity) for more details.
|
||||
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.
|
||||
|
||||
## Adding a Continuwuity user
|
||||
|
||||
@@ -151,11 +179,12 @@ ### Caddy
|
||||
|
||||
Caddy is the recommended reverse proxy as it is easy to use, has good defaults,
|
||||
and handle TLS certificates automatically. After installing Caddy via your preferred
|
||||
method, add the following content to your `/etc/caddy/Caddyfile` file
|
||||
method, create `/etc/caddy/conf.d/conduwuit_caddyfile` and enter the following
|
||||
(substitute `example.com` with your actual server name):
|
||||
|
||||
```
|
||||
example.com, example.com:8448 {
|
||||
# TCP reverse_proxy
|
||||
reverse_proxy 127.0.0.1:8008
|
||||
}
|
||||
```
|
||||
@@ -178,7 +207,7 @@ ### Other Reverse Proxies
|
||||
|
||||
- `/_matrix/client` - core Client-Server APIs. These should be available on port :443
|
||||
|
||||
- `/_continuwuity/` - Continuwuity's integrated account management interface and authentication path for OAuth-compatible clients
|
||||
- `/_continuwuity/` - Continuwuity's integrated account management interface for OAuth-compatible clients
|
||||
|
||||
You can optionally reverse proxy the following individual routes:
|
||||
|
||||
@@ -186,7 +215,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/resources` if you would like to see the Continuwuity landing page
|
||||
- `/` and `/_continuwuity/logo.svg` 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.
|
||||
|
||||
@@ -257,10 +286,10 @@ ## How do I know it works?
|
||||
As a quick health check, you can also use these cURL commands:
|
||||
|
||||
```bash
|
||||
curl https://example.com/_continuwuity/server_version
|
||||
curl https://example.com/_conduwuit/server_version
|
||||
|
||||
# If using port 8448
|
||||
curl https://example.com:8448/_continuwuity/server_version
|
||||
curl https://example.com:8448/_conduwuit/server_version
|
||||
|
||||
# If federation is enabled
|
||||
curl https://example.com:8448/_matrix/federation/v1/version
|
||||
@@ -276,28 +305,3 @@ ## What's next?
|
||||
- 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.
|
||||
|
||||
+64
-82
@@ -53,19 +53,12 @@ # Defaults to members of the admin room if unset
|
||||
After doing the steps above, Continuwuity will serve these 3 JSON files:
|
||||
|
||||
- `/.well-known/matrix/client`: for Client-Server discovery
|
||||
|
||||
- `/.well-known/matrix/server`: for Server-Server (federation) discovery
|
||||
|
||||
- `/.well-known/matrix/support`: admin contact details (strongly recommended).
|
||||
- By default, this include members of the admin room.
|
||||
- `/.well-known/matrix/support`: admin contact details (strongly recommended to have)
|
||||
|
||||
To enable full discovery, you will need to reverse proxy these paths from the base domain back to Continuwuity.
|
||||
|
||||
## Serving well-known files
|
||||
|
||||
You can either reverse proxy the well-known paths to Continuwuity, or serve static JSON files yourself.
|
||||
|
||||
### Option 1: Reverse proxying well-known files to Continuwuity
|
||||
## Reverse proxying well-known files to Continuwuity
|
||||
|
||||
<details>
|
||||
|
||||
@@ -103,7 +96,7 @@ ### Option 1: Reverse proxying well-known files to Continuwuity
|
||||
|
||||
For **Docker** users, consult the compose files in the [Appendix section](#docker-compose-examples).
|
||||
|
||||
After applying these changes, restart Continuwuity and your reverse proxy. Visit these routes and check that the responses match the examples below:
|
||||
After applying these changes, restart Continuwuity and your reverse proxy.Visit these routes and check that the responses match the examples below:
|
||||
|
||||
<details open>
|
||||
|
||||
@@ -129,12 +122,12 @@ ### Option 1: Reverse proxying well-known files to Continuwuity
|
||||
|
||||
</details>
|
||||
|
||||
### Option 2: Manually serving static files for well-known
|
||||
### Serving well-known files manually
|
||||
|
||||
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.
|
||||
|
||||
:::important Important: always configure [global.well_known]
|
||||
Even if you choose to serve the well-known files manually, 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 in order to redirect clients properly to email, OAuth, and account management endpoints.
|
||||
:::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.
|
||||
:::
|
||||
|
||||
<details>
|
||||
@@ -197,79 +190,16 @@ ### Issues with alternative setups
|
||||
|
||||
In these scenarios, further configurations would be needed. Refer to the [Related Documentation](#related-documentation) section for resolution steps and see how they could apply to your use case.
|
||||
|
||||
## Related Documentation
|
||||
---
|
||||
|
||||
### Matrix Specification
|
||||
|
||||
See the following sections of the Matrix Specification for more details on client and server resolution mechanisms:
|
||||
|
||||
- [Server-to-Server resolution](https://spec.matrix.org/latest/server-server-api/#resolving-server-names)
|
||||
- [Client-to-Server resolution](https://spec.matrix.org/latest/client-server-api/#server-discovery)
|
||||
- [MSC1929: Homeserver Admin Contact and Support page](https://github.com/matrix-org/matrix-spec-proposals/pull/1929)
|
||||
|
||||
### Community guides
|
||||
|
||||
- [Federation Setup guide by MTRNord](https://connectivity-tester.mtrnord.blog/docs/getting-started/federation-setup)
|
||||
|
||||
## Appendix
|
||||
|
||||
### Docker Compose examples
|
||||
|
||||
The following Compose files are taken from [Docker deployment instructions](../deploying/docker.mdx) and reconfigured to support split-domain delegation. Note the updated `CONTINUWUITY_WELL_KNOWN` variable and relevant changes in reverse proxy rules.
|
||||
|
||||
<details>
|
||||
<summary>Caddy (using Caddyfile) - delegated.docker-compose.with-caddy.yml ([view raw](/advanced/delegated.docker-compose.with-caddy.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-caddy.yml"
|
||||
|
||||
```
|
||||
|
||||
```txt title="Caddyfile"
|
||||
https://matrix.example.com:443 {
|
||||
reverse_proxy http://homeserver:8008
|
||||
}
|
||||
https://example.com:443 {
|
||||
reverse_proxy /.well-known/matrix* http://homeserver:8008
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Caddy (using labels) - delegated.docker-compose.with-caddy-labels.yml ([view raw](/advanced/delegated.docker-compose.with-caddy-labels.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-caddy-labels.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Traefik (for existing setup) - delegated.docker-compose.for-traefik.yml ([view raw](/advanced/delegated.docker-compose.for-traefik.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.for-traefik.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Traefik included - delegated.docker-compose.with-traefik.yml ([view raw](/advanced/delegated.docker-compose.with-traefik.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-traefik.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Using SRV records (not recommended)
|
||||
## Using SRV records (not recommended)
|
||||
|
||||
:::warning
|
||||
The following methods use DNS SRV records, and are **not recommended** due to increased complexity with few benefits. Additionally, they only work for federation traffic.
|
||||
|
||||
If you have already set up well-known delegation as above, you can safely skip this part.
|
||||
The following methods are **not recommended** due to increased complexity with little benefits. If you have already set up `.well-known` delegation as above, you can safely skip this part.
|
||||
:::
|
||||
|
||||
The following methods uses SRV DNS records and only work with federation traffic. They are only included for completeness.
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Using only SRV records</summary>
|
||||
@@ -311,7 +241,7 @@ ### Using SRV records (not recommended)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Using SRV records as a fallback for well-known delegation</summary>
|
||||
<summary>Using SRV records as a fallback for .well-known delegation</summary>
|
||||
|
||||
Assume your delegation is as below:
|
||||
|
||||
@@ -333,3 +263,55 @@ ### Using SRV records (not recommended)
|
||||
On the target's IP at port 443, you'll need to provide a valid route and cert for `example.com`.
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
See the following Matrix Specs for full details on client/server resolution mechanisms:
|
||||
|
||||
- [Server-to-Server resolution](https://spec.matrix.org/v1.17/server-server-api/#resolving-server-names) (see this for more information on SRV records)
|
||||
- [Client-to-Server resolution](https://spec.matrix.org/v1.17/client-server-api/#server-discovery)
|
||||
- [MSC1929: Homeserver Admin Contact and Support page](https://github.com/matrix-org/matrix-spec-proposals/pull/1929)
|
||||
|
||||
## Appendix
|
||||
|
||||
### Docker Compose examples
|
||||
|
||||
The following Compose files are taken from [Docker instructions](../deploying/docker.mdx) and reconfigured to support split-domain delegation. Note the updated `CONTINUWUITY_WELL_KNOWN` variable and relevant changes in reverse proxy rules.
|
||||
|
||||
<details>
|
||||
<summary>Caddy (using Caddyfile) - delegated.docker-compose.with-caddy.yml ([view raw](/advanced/delegated.docker-compose.with-caddy.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-caddy.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Caddy (using labels) - delegated.docker-compose.with-caddy-labels.yml ([view raw](/advanced/delegated.docker-compose.with-caddy-labels.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-caddy-labels.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Traefik (for existing setup) - delegated.docker-compose.for-traefik.yml ([view raw](/advanced/delegated.docker-compose.for-traefik.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.for-traefik.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Traefik included - delegated.docker-compose.with-traefik.yml ([view raw](/advanced/delegated.docker-compose.with-traefik.yml))</summary>
|
||||
|
||||
```yaml file="../public/advanced/delegated.docker-compose.with-traefik.yml"
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
+18
-55
@@ -8,7 +8,7 @@ # DNS Tuning (recommended)
|
||||
|
||||
## Overview
|
||||
|
||||
For generic deployments, install your resolver of choice and configure your host system's `/etc/resolv.conf` to point to it. The resolver should ideally reside on the same host as Continuwuity.
|
||||
For generic deployments, install your resolver of choice and configure `/etc/resolv.conf` to point to it. The resolver should ideally reside on the same host as Continuwuity.
|
||||
|
||||
```txt title="/etc/resolv.conf"
|
||||
nameserver 127.0.0.1
|
||||
@@ -18,7 +18,7 @@ ## Overview
|
||||
|
||||
### For Docker users
|
||||
|
||||
By default, Docker bridge networks uses a poorly performing resolver to intercept and respond to container hostnames. **This resolver should also be avoided**. Instead, mount a custom `/etc/resolv.conf` file into the container, and hardcode a resolver address to bypass Docker's.
|
||||
Docker bridge networks uses a non-performant resolver to intercept and respond to container hostnames, and **this should also be avoided**. Instead, mount a custom `/etc/resolv.conf` file into the container, and hardcode a resolver address to bypass Docker's.
|
||||
|
||||
It is recommended to run a dedicated resolver container for Continuwuity, as to separate from the host's resolver setup. To do this, create a custom bridge network and IP range, and explicitly define an IP address for the resolver container.
|
||||
|
||||
@@ -27,28 +27,23 @@ ### For Docker users
|
||||
|
||||
```yaml title="docker-compose.yml"
|
||||
networks:
|
||||
# re-use the `proxy` network, as shown in the Docker deployment docs
|
||||
# (https://continuwuity.org/deploying/docker#choose-your-reverse-proxy)
|
||||
# and configure it with a custom subnet
|
||||
proxy:
|
||||
matrix_net:
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: "10.10.10.0/24"
|
||||
|
||||
services:
|
||||
homeserver:
|
||||
# ...
|
||||
volume:
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf:ro
|
||||
networks:
|
||||
- proxy
|
||||
homeserver:
|
||||
# ...
|
||||
volume:
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf:ro
|
||||
|
||||
unbound:
|
||||
# ...
|
||||
networks:
|
||||
proxy:
|
||||
ipv4_address: 10.10.10.20
|
||||
unbound:
|
||||
# ...
|
||||
networks:
|
||||
matrix_net:
|
||||
ipv4_address: 10.10.10.20
|
||||
```
|
||||
|
||||
```txt title="continuwuity-resolv.conf"
|
||||
@@ -57,41 +52,9 @@ # and configure it with a custom subnet
|
||||
|
||||
</details>
|
||||
|
||||
:::warning Breaking resolution with container hostnames
|
||||
|
||||
After you mount a custom `/etc/resolv.conf`, you won't be able to connect to other containers using their hostnames, such as for [appservices](../appservices.mdx) in the same Docker network. To work around this, force your appservice to use a static IP address, and refer to its static IP during registration.
|
||||
|
||||
<details>
|
||||
<summary>Example Docker deployment with an appservice</summary>
|
||||
|
||||
```yaml title="docker-compose.yml"
|
||||
# ... other parts of compose file ...
|
||||
|
||||
appservice:
|
||||
# ...
|
||||
networks:
|
||||
proxy:
|
||||
ipv4_address: 10.10.10.30
|
||||
```
|
||||
|
||||
~~~txt
|
||||
!admin appservices register
|
||||
|
||||
```
|
||||
id: appservice-name
|
||||
url: http://10.10.10.30:29318
|
||||
# rest of the registration file
|
||||
```
|
||||
|
||||
~~~
|
||||
|
||||
</details>
|
||||
|
||||
:::
|
||||
|
||||
### For IPv4-only users
|
||||
|
||||
If you don't have IPv6 connectivity, change `ip_lookup_strategy` to `1` in Continuwuity's configuration in order to onlyresolve IPv4 addresses and remove unnecessary IPv6 queries.
|
||||
If you don't have IPv6 connectivity, changing `ip_lookup_strategy` to only resolve for IPv4 will reduce unnecessary AAAA queries.
|
||||
|
||||
```toml title="continuwuity.toml"
|
||||
[global]
|
||||
@@ -109,13 +72,13 @@ ## Unbound
|
||||
|
||||
- Increase `rrset-cache-size` and `msg-cache-size` to something much higher than the default `4M`, such as `64M`.
|
||||
|
||||
- Increase `discard-timeout` to something like `4800` to wait longer for upstream resolvers, as recursion can take a long time to respond to some domains. Continuwuity defaults to `dns_timeout = 10` seconds, so dropping requests early would lead to unnecessary retries and/or failures.
|
||||
- Increase `discard-timeout` to something like `4800` to wait longer for upstream resolvers, as recursion can take a long time to respond to some domains. Continuwuity default to `dns_timeout = 10` seconds, so dropping requests early would lead to unnecessary retries and/or failures.
|
||||
|
||||
### Using a forwarder (optional)
|
||||
### Recursion versus forwarding
|
||||
|
||||
Unbound employs **recursive resolution** by default, contacting many nameservers around the world in the process. While this is generally viable for most users, sometimes these recursive queries can be too slow to fully resolve. As an alternative, you may consider **forwarding** your queries to public resolvers, and benefit from faster responses from their caches.
|
||||
Unbound by default employs **recursive resolution** and contacts many servers around the world. While this allows updated and authoritative answers and are generally viable for most users, sometimes these recursive queries can be too slow to fully resolve. As an alternative, you can consider **forwarding** your queries to public resolvers, and benefit from faster responses from their CDNs.
|
||||
|
||||
However, do note that most popular upstreams (such as Google DNS or Quad9) employ IP ratelimiting, so a generous Unbound cache is still needed to avoid making too many queries.
|
||||
Do note that most popular upstreams (such as Google DNS or Quad9) employ IP ratelimiting, so a generous cache is still needed to avoid making too many queries.
|
||||
|
||||
If you want to use forwarders, configure it as follows:
|
||||
|
||||
@@ -181,7 +144,7 @@ ### Technitium DNS
|
||||
|
||||
## Testing
|
||||
|
||||
As a rough stress test, you can run `!admin query resolver flush-cache -a` or `!admin server clear-caches` to clear your destinations cache - this will then trigger a netburst of DNS queries. If your resolver can handle this load without issue, then it should be ready for regular Continuwuity activity.
|
||||
As a rough stress test, you can run `!admin query resolver flush-cache -a` or `!admin server clear-caches` to trigger a netburst of DNS queries. If your resolver can handle these loads without problem, then it should be ready for regular Continuwuity activity.
|
||||
|
||||
To test connectivity against a specific server, use `!admin debug ping <SERVER_NAME>` and `!admin debug resolve-true-destination <SERVER_NAME>`.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ # Performance tuning
|
||||
|
||||
## DNS tuning (recommended)
|
||||
|
||||
DNS tuning is important to ensure a smooth experience for federated servers. Please see the dedicated [DNS tuning guide](./dns.mdx).
|
||||
Please see the dedicated [DNS tuning guide](./dns.mdx).
|
||||
|
||||
## Cache capacities
|
||||
|
||||
@@ -115,8 +115,6 @@ ### Tuning your trusted servers
|
||||
|
||||
:::info Vet your trusted servers!
|
||||
Trusted servers are your first point of contact when obtaining public keys from other servers, and they could theoretically impersonate other servers and cause significant harm to your deployment. Please thoroughly verify your trusted servers' credibility before adding them to your configuration.
|
||||
|
||||
If you need suggestions for trusted servers, ask in the Continuwuity main room.
|
||||
:::
|
||||
|
||||
Trusted servers are queried sequentially in the order they are listed. If you have multiple trusted servers configured, put the faster ones first:
|
||||
|
||||
+35
-48
@@ -42,16 +42,12 @@ ## Database (RocksDB)
|
||||
creating unnecessary I/O amplification. RocksDB is built with io_uring support
|
||||
via liburing for improved read performance.
|
||||
|
||||
RocksDB troubleshooting can be found [in the RocksDB section of troubleshooting](./troubleshooting.mdx#rocksdb--database-issues).
|
||||
RocksDB troubleshooting can be found [in the RocksDB section of troubleshooting](troubleshooting.md).
|
||||
|
||||
### Compression
|
||||
|
||||
Some RocksDB settings can be adjusted, such as the chosen compression method and level.
|
||||
See the RocksDB section in the [example config](./reference/config.mdx), and the
|
||||
[database compression section](./guides/performance.mdx#tuning-database-compression)
|
||||
in the performance tuning documentation for more.
|
||||
|
||||
#### Caveats for btrfs users
|
||||
Some RocksDB settings can be adjusted such as the compression method chosen. See
|
||||
the RocksDB section in the [example config](./reference/config.mdx).
|
||||
|
||||
btrfs users have reported that database compression does not need to be disabled
|
||||
on Continuwuity as the filesystem already does not attempt to compress. This can be
|
||||
@@ -61,12 +57,10 @@ #### Caveats for btrfs users
|
||||
unbuffered Direct IO inoperable, significantly slowing down read and write
|
||||
performance. See [the Btrfs docs](https://btrfs.readthedocs.io/en/latest/Compression.html#compatibility).
|
||||
|
||||
:::important
|
||||
Compression is done using the COW mechanism so it’s incompatible with
|
||||
`nodatacow`. Direct IO read works on compressed files but will fall back to
|
||||
buffered writes and leads to no compression even if force compression is set.
|
||||
Currently `nodatasum` and compression don’t work together.
|
||||
:::
|
||||
> Compression is done using the COW mechanism so it’s incompatible with
|
||||
> nodatacow. Direct IO read works on compressed files but will fall back to
|
||||
> buffered writes and leads to no compression even if force compression is set.
|
||||
> Currently nodatasum and compression don’t work together.
|
||||
|
||||
### Files in database
|
||||
|
||||
@@ -84,47 +78,37 @@ ### Files in database
|
||||
|
||||
## Backups
|
||||
|
||||
### Database online backup
|
||||
|
||||
f you'd like to run an online backup of your database - that is, a backup with
|
||||
no downtime - check the [`!admin server` command](./reference/admin/server.md)
|
||||
for the required commands and the `database_backup_path` config options in
|
||||
the example config.
|
||||
|
||||
Please note that the format of the database backup is not the exact same as the
|
||||
format of offline backups. This is unfortunately a bad design choice by Facebook
|
||||
as we are using the database backup engine API from RocksDB, however the data
|
||||
is still there and can still be joined together.
|
||||
Currently only RocksDB supports online backups. If you'd like to backup your
|
||||
database online without any downtime, see the `!admin server` command for the
|
||||
backup commands and the `database_backup_path` config options in the example
|
||||
config. Please note that the format of the database backup is not the exact
|
||||
same. This is unfortunately a bad design choice by Facebook as we are using the
|
||||
database backup engine API from RocksDB, however the data is still there and can
|
||||
still be joined together.
|
||||
|
||||
To restore a backup from an online RocksDB backup:
|
||||
|
||||
- Shutdown Continuwuity
|
||||
- Create a new directory for merging together the data
|
||||
- In the online backup created, copy all `.sst` files in
|
||||
- shutdown Continuwuity
|
||||
- create a new directory for merging together the data
|
||||
- in the online backup created, copy all `.sst` files in
|
||||
`$DATABASE_BACKUP_PATH/shared_checksum` to your new directory
|
||||
- trim all the strings so instead of `######_sxxxxxxxxx.sst`, it reads
|
||||
`######.sst`. A way of doing this with sed and bash is `for file in *.sst; do mv
|
||||
"$file" "$(echo "$file" | sed 's/_s.*/.sst/')"; done`
|
||||
- Copy all the files in `$DATABASE_BACKUP_PATH/private/1` (or the latest backup number
|
||||
- copy all the files in `$DATABASE_BACKUP_PATH/1` (or the latest backup number
|
||||
if you have multiple) to your new directory
|
||||
- Set your `database_path` config option to your new directory, or replace your
|
||||
- set your `database_path` config option to your new directory, or replace your
|
||||
old one with the new one you crafted
|
||||
- Start up Continuwuity again and it should open as normal
|
||||
|
||||
Note: You can verify the necessary files to copy by comparing them with contents in the `$DATABASE_BACKUP_PATH/meta/1` (or latest backup number) file.
|
||||
|
||||
### Database offline backup
|
||||
- start up Continuwuity again and it should open as normal
|
||||
|
||||
If you'd like to do an offline backup, shutdown Continuwuity and copy your
|
||||
`database_path` directory elsewhere. This can be restored with no modifications
|
||||
needed.
|
||||
|
||||
### Media backup
|
||||
Backing up media is also just copying the `media/` directory from your database
|
||||
directory.
|
||||
|
||||
Media is stored in the `media/` subdirectory from your database directory.
|
||||
Backing up media is also just copying that subdirectory.
|
||||
|
||||
## Media management
|
||||
## Media
|
||||
|
||||
Media still needs various work, however Continuwuity implements media deletion via:
|
||||
|
||||
@@ -133,16 +117,19 @@ ## Media management
|
||||
- Delete list of MXC URIs
|
||||
- Delete remote media in the past `N` seconds/minutes via filesystem metadata on
|
||||
the file created time (`btime`) or file modified time (`mtime`)
|
||||
- Delete all media from a local user
|
||||
- Delete all media from a remote server
|
||||
- Delete cached URL previews
|
||||
|
||||
See the [`!admin media` commands](./reference/admin/media.md) for further information.
|
||||
All media in Continuwuity is stored at `$DATABASE_DIR/media`.
|
||||
See the `!admin media` command for further information. All media in Continuwuity
|
||||
is stored at `$DATABASE_DIR/media`. This will be configurable soon.
|
||||
|
||||
While Continuwuity does not implement built-in S3 support, using an S3 filesystem
|
||||
mount on the `media/` path will work. Continuwuity also sends a `Cache-Control`
|
||||
header of 1 year with the `immutable` directive for all media requests
|
||||
(download and thumbnail) to reduce unnecessary bandwidth and load.
|
||||
If you are finding yourself needing extensive granular control over media, we
|
||||
recommend looking into [Matrix Media
|
||||
Repo](https://github.com/t2bot/matrix-media-repo). Continuwuity intends to
|
||||
implement various utilities for media, but MMR is dedicated to extensive media
|
||||
management.
|
||||
|
||||
Built-in S3 support is also planned, but for now using a "S3 filesystem" on
|
||||
`media/` works. Continuwuity also sends a `Cache-Control` header of 1 year and
|
||||
immutable for all media requests (download and thumbnail) to reduce unnecessary
|
||||
media requests from browsers, reduce bandwidth usage, and reduce load.
|
||||
|
||||
[rocksdb-compaction]: https://github.com/facebook/rocksdb/wiki/Compaction
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"id": 16,
|
||||
"mention_room": true,
|
||||
"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 low severity 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!"
|
||||
"date": "2026-07-13",
|
||||
"message": "[Continuwuity 26.6.2](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v26.6.1) has just been released! This release fixes a severe bug with OIDC that could cause users' accounts to be flagged as deactivated. If you use OIDC, please update as soon as possible."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,55 +1,54 @@
|
||||
# Continuwuity - With Caddy Labels
|
||||
|
||||
services:
|
||||
caddy:
|
||||
# This compose file uses caddy-docker-proxy as the reverse proxy for Continuwuity!
|
||||
# For more info, visit https://github.com/lucaslorentz/caddy-docker-proxy
|
||||
image: "docker.io/lucaslorentz/caddy-docker-proxy:ci-alpine"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
- CADDY_INGRESS_NETWORKS=caddy
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
caddy: example.com
|
||||
caddy.reverse_proxy: /.well-known/matrix/* homeserver:8008
|
||||
caddy:
|
||||
# This compose file uses caddy-docker-proxy as the reverse proxy for Continuwuity!
|
||||
# For more info, visit https://github.com/lucaslorentz/caddy-docker-proxy
|
||||
image: "docker.io/lucaslorentz/caddy-docker-proxy:ci-alpine"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
- CADDY_INGRESS_NETWORKS=caddy
|
||||
networks:
|
||||
- caddy
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
caddy: example.com
|
||||
caddy.reverse_proxy: /.well-known/matrix/* homeserver:8008
|
||||
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
# - ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com # EDIT THIS
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
# CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
#- ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com # EDIT THIS
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
|
||||
# Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://matrix.example.com,
|
||||
server=matrix.example.com:443
|
||||
}
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
labels:
|
||||
caddy: matrix.example.com
|
||||
caddy.reverse_proxy: "{{upstreams 8008}}"
|
||||
# Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://matrix.example.com,
|
||||
server=matrix.example.com:443
|
||||
}
|
||||
|
||||
networks:
|
||||
- caddy
|
||||
labels:
|
||||
caddy: matrix.example.com
|
||||
caddy.reverse_proxy: "{{upstreams 8008}}"
|
||||
volumes:
|
||||
db:
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
caddy:
|
||||
|
||||
@@ -1,46 +1,57 @@
|
||||
# Continuwuity - Using Caddy Docker Image
|
||||
|
||||
services:
|
||||
caddy:
|
||||
image: "docker.io/caddy:latest"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
networks:
|
||||
- caddy
|
||||
volumes:
|
||||
- ./data:/data
|
||||
# mount your created Caddyfile into the container
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
restart: unless-stopped
|
||||
caddy:
|
||||
image: "docker.io/caddy:latest"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
networks:
|
||||
- caddy
|
||||
volumes:
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
configs:
|
||||
- source: Caddyfile
|
||||
target: /etc/caddy/Caddyfile
|
||||
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
# - ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
# CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
#- ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
|
||||
## Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://example.com,
|
||||
server=example.com:443
|
||||
}
|
||||
## Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://matrix.example.com,
|
||||
server=matrix.example.com:443
|
||||
}
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
- caddy
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
caddy:
|
||||
|
||||
volumes:
|
||||
db:
|
||||
|
||||
configs:
|
||||
Caddyfile:
|
||||
content: |
|
||||
https://matrix.example.com:443 {
|
||||
reverse_proxy http://homeserver:8008
|
||||
}
|
||||
https://example.com:443 {
|
||||
reverse_proxy /.well-known/matrix* http://homeserver:8008
|
||||
}
|
||||
|
||||
@@ -1,52 +1,51 @@
|
||||
# Continuwuity - With Caddy Labels
|
||||
|
||||
services:
|
||||
caddy:
|
||||
# This compose file uses caddy-docker-proxy as the reverse proxy for Continuwuity!
|
||||
# For more info, visit https://github.com/lucaslorentz/caddy-docker-proxy
|
||||
image: "docker.io/lucaslorentz/caddy-docker-proxy:ci-alpine"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
- CADDY_INGRESS_NETWORKS=caddy
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
caddy:
|
||||
# This compose file uses caddy-docker-proxy as the reverse proxy for Continuwuity!
|
||||
# For more info, visit https://github.com/lucaslorentz/caddy-docker-proxy
|
||||
image: "docker.io/lucaslorentz/caddy-docker-proxy:ci-alpine"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
- CADDY_INGRESS_NETWORKS=caddy
|
||||
networks:
|
||||
- caddy
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
# - ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
# CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
#- ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
|
||||
# Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://example.com,
|
||||
server=example.com:443
|
||||
}
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
labels:
|
||||
caddy: example.com
|
||||
caddy.reverse_proxy: "{{upstreams 8008}}"
|
||||
# Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
CONTINUWUITY_WELL_KNOWN: |
|
||||
{
|
||||
client=https://example.com,
|
||||
server=example.com:443
|
||||
}
|
||||
|
||||
networks:
|
||||
- caddy
|
||||
labels:
|
||||
caddy: example.com
|
||||
caddy.reverse_proxy: "{{upstreams 8008}}"
|
||||
volumes:
|
||||
db:
|
||||
db:
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
caddy:
|
||||
|
||||
@@ -1,48 +1,56 @@
|
||||
# Continuwuity - Using Caddy Docker Image
|
||||
|
||||
services:
|
||||
caddy:
|
||||
image: "docker.io/caddy:latest"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
- 8448:8448
|
||||
networks:
|
||||
- proxy
|
||||
volumes:
|
||||
- ./data:/data
|
||||
# mount your created Caddyfile into the container
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
restart: unless-stopped
|
||||
caddy:
|
||||
image: "docker.io/caddy:latest"
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
- 8448:8448
|
||||
networks:
|
||||
- caddy
|
||||
volumes:
|
||||
- ./data:/data
|
||||
restart: unless-stopped
|
||||
configs:
|
||||
- source: Caddyfile
|
||||
target: /etc/caddy/Caddyfile
|
||||
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
# - ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
# CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
homeserver:
|
||||
image: "forgejo.ellis.link/continuwuation/continuwuity:latest"
|
||||
restart: unless-stopped
|
||||
command: /sbin/conduwuit
|
||||
volumes:
|
||||
- db:/var/lib/continuwuity
|
||||
- ./continuwuity-resolv.conf:/etc/resolv.conf # use custom resolvers rather than Docker's
|
||||
#- ./continuwuity.toml:/etc/continuwuity.toml
|
||||
environment:
|
||||
CONTINUWUITY_SERVER_NAME: example.com
|
||||
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||
CONTINUWUITY_PORT: 8008
|
||||
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
|
||||
|
||||
## (Optional) Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
## If you do this, remove all routes to port :8448 from the compose and Caddyfile
|
||||
# CONTINUWUITY_WELL_KNOWN: |
|
||||
# {
|
||||
# client=https://example.com,
|
||||
# server=example.com:443
|
||||
# }
|
||||
## (Optional) Serve .well-known files to tell others to reach Continuwuity on port :443
|
||||
## If you do this, remove all routes to port :8448 from the compose and Caddyfile
|
||||
# CONTINUWUITY_WELL_KNOWN: |
|
||||
# {
|
||||
# client=https://example.com,
|
||||
# server=example.com:443
|
||||
# }
|
||||
|
||||
networks:
|
||||
- proxy
|
||||
networks:
|
||||
- caddy
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
caddy:
|
||||
|
||||
volumes:
|
||||
db:
|
||||
db:
|
||||
|
||||
configs:
|
||||
Caddyfile:
|
||||
content: |
|
||||
https://example.com:443, https://example.com:8448 {
|
||||
reverse_proxy http://homeserver:8008
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ # `!admin rooms`
|
||||
Commands for managing rooms
|
||||
|
||||
|
||||
## `!admin rooms list`
|
||||
## `!admin rooms list-rooms`
|
||||
|
||||
List all rooms the server knows about
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ ## `!admin server admin-notice`
|
||||
|
||||
Send a message to the admin room
|
||||
|
||||
## `!admin server reload`
|
||||
## `!admin server reload-mods`
|
||||
|
||||
Hot-reload the server
|
||||
|
||||
|
||||
@@ -4,14 +4,10 @@ # `!admin users`
|
||||
Commands for managing local users
|
||||
|
||||
|
||||
## `!admin users create`
|
||||
## `!admin users create-user`
|
||||
|
||||
Create a new user
|
||||
|
||||
## `!admin users issue-token`
|
||||
|
||||
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
|
||||
@@ -92,7 +88,7 @@ ## `!admin users disable-login`
|
||||
|
||||
Disables login for the specified user without deactivating or locking their account. This prevents the user from obtaining new access tokens, but does not invalidate existing sessions.
|
||||
|
||||
## `!admin users list`
|
||||
## `!admin users list-users`
|
||||
|
||||
List local users in the database
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
## Configuration file reference
|
||||
|
||||
This configuration file reflect the latest developments on the `main` branch. To check the configuration from a specific Continuwuity version, browse the [tags](https://forgejo.ellis.link/continuwuation/continuwuity/tags) and navigate to the `conduwuit-example.toml` file for that version.
|
||||
|
||||
---
|
||||
|
||||
```toml file="../../conduwuit-example.toml"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ### Slow joins to rooms
|
||||
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](./guides/performance.mdx#tuning-your-trusted-servers) listed in `trusted_servers` in your configuration, and ensure
|
||||
multiple fast, trusted servers listed in `trusted_servers` in your configuration, and ensure
|
||||
`query_trusted_key_servers_first_on_join` is set to true (the default).
|
||||
If you need suggestions for trusted servers, ask in the Continuwuity main room.
|
||||
|
||||
@@ -23,8 +23,6 @@ ### Slow joins to rooms
|
||||
the bug caused your homeserver to forget to tell your client. **To fix this, clear your client's cache.** Both Element and Cinny
|
||||
have a button to clear their cache in the "About" section of their settings.
|
||||
|
||||
[Tuning your DNS](./guides/dns.mdx) can also help make initial joins faster.
|
||||
|
||||
### Configuration not working as expected
|
||||
|
||||
Sometimes you can make a mistake in your configuration that
|
||||
@@ -66,7 +64,7 @@ ### DNS server overload
|
||||
|
||||
### Intermittent federation failures to a specific server
|
||||
|
||||
There may be circumstances where servers fail to connect to each other, probably due to a bad DNS cache. In such cases, issuing `!admin debug ping <SERVER_NAME>` would return some errors, and `!admin query resolver cache <SERVER_NAME>` would return a wrong destination endpoint.
|
||||
There may be circumstances where servers fail to connect to each other, probably due to a bad DNS cache. In such cases, issuing `!admin debug ping <SERVER_NAME>` would return some errors.
|
||||
|
||||
To fix this, you can run `!admin query resolver flush-cache <SERVER_NAME>` to clear the bad cache for that domain, and outbound requests should work again.
|
||||
|
||||
@@ -123,7 +121,7 @@ ## Debugging
|
||||
|
||||
Note that users should not really need to debug things. If you find yourself
|
||||
debugging and find the issue, please let us know and/or how we can fix it.
|
||||
Various debug commands can be [found in `!admin debug`](./reference/admin/debug).
|
||||
Various debug commands can be found in `!admin debug`.
|
||||
|
||||
### Debug/Trace log level
|
||||
|
||||
|
||||
Generated
+126
-110
@@ -16,21 +16,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz",
|
||||
"integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
|
||||
"integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/wasi-threads": "1.2.3",
|
||||
"@emnapi/wasi-threads": "1.2.2",
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/runtime": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
|
||||
"integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
|
||||
"integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
@@ -39,9 +39,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/wasi-threads": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz",
|
||||
"integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
|
||||
"integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
@@ -125,13 +125,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rsbuild/core": {
|
||||
"version": "2.1.10",
|
||||
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.1.10.tgz",
|
||||
"integrity": "sha512-lwxC5w88U2AMv6aNwG3VH7+AV33N4JJQjD//egVWFsMbV+OE/bnfCsurSpX8s3lGyRYkJMwUVN+YXMbmmYZFfw==",
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.1.5.tgz",
|
||||
"integrity": "sha512-7TW4U1SH7VxQZzSTIOzvwj5lo9uNTmGpsmTXFr4axQAE4giLDKP3kVUA1ZW4P3/Mz4QQJJyvZP29mVcb8kZCfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rspack/core": "~2.1.8",
|
||||
"@rspack/core": "~2.1.3",
|
||||
"@swc/helpers": "^0.5.23"
|
||||
},
|
||||
"bin": {
|
||||
@@ -169,30 +169,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rspack/binding": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.1.8.tgz",
|
||||
"integrity": "sha512-tmAyHzDbPiy8V7HvQqtuPsbs6dPgwV0YjzW5XrPRV9gzf+Hdm7pvsZJKE1QKO9WV5RuvGYav98xIX6O+abZxzQ==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.1.3.tgz",
|
||||
"integrity": "sha512-4UGXJqUHmm36tWG1GgFZz3p8sQ5JuSgWI+gq1xPPoihS41uYJL3cXuJnirTeWsmVrusmYZTQhgU3tl3VYGcJYg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"@rspack/binding-darwin-arm64": "2.1.8",
|
||||
"@rspack/binding-darwin-x64": "2.1.8",
|
||||
"@rspack/binding-linux-arm64-gnu": "2.1.8",
|
||||
"@rspack/binding-linux-arm64-musl": "2.1.8",
|
||||
"@rspack/binding-linux-riscv64-gnu": "2.1.8",
|
||||
"@rspack/binding-linux-riscv64-musl": "2.1.8",
|
||||
"@rspack/binding-linux-x64-gnu": "2.1.8",
|
||||
"@rspack/binding-linux-x64-musl": "2.1.8",
|
||||
"@rspack/binding-wasm32-wasi": "2.1.8",
|
||||
"@rspack/binding-win32-arm64-msvc": "2.1.8",
|
||||
"@rspack/binding-win32-ia32-msvc": "2.1.8",
|
||||
"@rspack/binding-win32-x64-msvc": "2.1.8"
|
||||
"@rspack/binding-darwin-arm64": "2.1.3",
|
||||
"@rspack/binding-darwin-x64": "2.1.3",
|
||||
"@rspack/binding-linux-arm64-gnu": "2.1.3",
|
||||
"@rspack/binding-linux-arm64-musl": "2.1.3",
|
||||
"@rspack/binding-linux-riscv64-gnu": "2.1.3",
|
||||
"@rspack/binding-linux-riscv64-musl": "2.1.3",
|
||||
"@rspack/binding-linux-x64-gnu": "2.1.3",
|
||||
"@rspack/binding-linux-x64-musl": "2.1.3",
|
||||
"@rspack/binding-wasm32-wasi": "2.1.3",
|
||||
"@rspack/binding-win32-arm64-msvc": "2.1.3",
|
||||
"@rspack/binding-win32-ia32-msvc": "2.1.3",
|
||||
"@rspack/binding-win32-x64-msvc": "2.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@rspack/binding-darwin-arm64": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.1.8.tgz",
|
||||
"integrity": "sha512-kia+eWtyWPvR4ntg1bWYoVU8nLPbUg2fG3zgBEocsTcsh5ZENSiEPxEKymDgMyIMONUqj611E0775cdUBoNmqw==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.1.3.tgz",
|
||||
"integrity": "sha512-oOGI0RSL89Ehu9T22rugmfUY9OC2eBqLMeWRYsu7bhlUrjoXeVfGBBSEXCse666BQ1sAiM8hD/k7nqVria/okQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -204,9 +204,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-darwin-x64": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.1.8.tgz",
|
||||
"integrity": "sha512-08pBkFhlD3Y3Qzh94w/Fc3skaIE3e96kl2P14m8+tnYTcglpOfpA2OwS3iHt9fOqy0HjoAVe6/MW3cBgs5iabA==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.1.3.tgz",
|
||||
"integrity": "sha512-sVqWXNiFTMXAyN362y6IA+eJc8LXZKfHdhEJ/zDuMmRp+u2IvhgaF8tk3vX/OmeB9jydVjySijuiqk8No/FoCA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -218,9 +218,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-arm64-gnu": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.1.8.tgz",
|
||||
"integrity": "sha512-KLniMc9GzhKpVqhPzaJo3KJwzdAllXVVqZIk/uL1QipXOxs57fgM4u7IexKPFVla0o/u1PQG/Ah2YLDmda24Ow==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.1.3.tgz",
|
||||
"integrity": "sha512-aCy9Zli/2Qf+Ee5otXfFQ6mhv5fEyn0wIoBVmouqtJoqOO21et6UTtJ+LHLsMDolwGLyHERAljeSFSmYX3/O5A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -235,9 +235,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-arm64-musl": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.1.8.tgz",
|
||||
"integrity": "sha512-yUKAxHNGnICtw5RnxFWu4dHtsz/tdt7rbeFcsINNVre9HcrRxf5XP+FbOGL/SMxd9oM9XCo10paU2WckTKwbEA==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.1.3.tgz",
|
||||
"integrity": "sha512-flIE7eluz0d21Fn28EVm3vPwoJooOSqtmjLFVSuOMcoCbwV9clfor195oIrAppp/W7dL/3XquFuVfrsa01Jy8Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -252,9 +252,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-riscv64-gnu": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.1.8.tgz",
|
||||
"integrity": "sha512-gg4S1jaitwYPHR9HZ3zNGH1EK2GXINm66p4kEpOP1gbc+akyOouVF/dMcu9NGPlRg58FbEhVRZYKu7Z/zcpKHg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.1.3.tgz",
|
||||
"integrity": "sha512-yojg8elye1nhsNeGncw0NrZ4pMGF7NVebR80CLg72TXyzfYwFJlFTdU5yUYb1Gy+JXIvrSCwzQt2QkyiEvmkfg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -269,9 +269,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-riscv64-musl": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.1.8.tgz",
|
||||
"integrity": "sha512-b/aU5j1h368SLNyz5u+flqpZVhzSZ1UIslaj9sZJuAvqkGWv3xsjc/28/PTo/RYXCxd0FNVAxTxWHKvRiAAS8w==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.1.3.tgz",
|
||||
"integrity": "sha512-6PvbXb3FOK4X3S5QGvoSW/sqExmsvAoPnQ/YSFrXvTphkXFezA7wnobmGBHT8JQP31hcFRzJHIZSIOKktzSzzg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -286,9 +286,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-x64-gnu": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.1.8.tgz",
|
||||
"integrity": "sha512-EyegohSx0BJRqieCg9f/caCqFARRWkqI5hwJt6k530MoOTLeq8I3vsbeg24/2MktwIC1dmJi8bl0+WhPKQs4eQ==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.1.3.tgz",
|
||||
"integrity": "sha512-lMXjoGKf0SnviH596fmTszgtnXLHmWOoE90G8grG9MvKVa3pelRmfps5ewZL9s8ENf3NXRfOxIhIf/M9as6MqA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -303,9 +303,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-linux-x64-musl": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.1.8.tgz",
|
||||
"integrity": "sha512-I6E+goN+UQ297q4r1qdbiAyNCI3t0+a5Y0xDIAPOZfRDRxDTnH/LF8/y65gjsJoKRKyn7zxRC0T/NURTkRNQ9A==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.1.3.tgz",
|
||||
"integrity": "sha512-0esT35v7pW2ZsJTMc/zDUHwpNXlPqyUCyuiLJvrAAUcdENrgOVe4DmFrgVJ2hwqI4GjeN1VBnGRJ8c+edAHH5w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -320,9 +320,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-wasm32-wasi": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.1.8.tgz",
|
||||
"integrity": "sha512-om7GAKWAU3lcSvbCon2m7mzw8v9OTrO2LW2MZ1lGe/uVJJmwGGkl9HVoXFyWFLrN6YVFyx8iP+AkN4owDWB9Cw==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.1.3.tgz",
|
||||
"integrity": "sha512-UsrDjD59UEP0mhfN/Z+uTc3vLgiUvIr+mn92WC1sbQi9gtZohTYvaQYFhWuMkBqsACGcmZp704JAbbSrVrVYCA==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
@@ -330,15 +330,15 @@
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emnapi/core": "1.11.3",
|
||||
"@emnapi/runtime": "1.11.3",
|
||||
"@emnapi/core": "1.11.1",
|
||||
"@emnapi/runtime": "1.11.1",
|
||||
"@napi-rs/wasm-runtime": "1.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@rspack/binding-win32-arm64-msvc": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.1.8.tgz",
|
||||
"integrity": "sha512-WDnsP/SUb9zbxyGX9XjPw5AXrX86u5oidn0MDdfJduOOqdCSpHwmRjlQ8NUJhbBq9WqVJMFlcab7NwZVWX/yyg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.1.3.tgz",
|
||||
"integrity": "sha512-42RS/SwKBTkNvXIPZXqTn0yEFN8zwGRfRe/ly0GDvPp/KxpLMFWxJmLxgtoLompU+0UCGvV4KpcBENt3oWs6BA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -350,9 +350,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-win32-ia32-msvc": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.1.8.tgz",
|
||||
"integrity": "sha512-QiMQMPNDiY3dhhaIdaFPzcPDC06cEYkNY89ea+EmDvNVgZq6V+2mFS/WnzZVMeEbGAYJCjsv/ABhhLT1hlYMvg==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.1.3.tgz",
|
||||
"integrity": "sha512-thk43H1JHHbetNF3txcsGXeOwZi2m6Luf/uVUqNORXjxr5VV8woHAgaAx4QXVZRg70z1VDjd8mBWnHBnKI0FGA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -364,9 +364,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/binding-win32-x64-msvc": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.1.8.tgz",
|
||||
"integrity": "sha512-b7sA5eB64vo2mbsuc//MOYzVLeCKHPn0dfP/GmNEoHdWbhRgZ/orZLWurYMQj04ELTLW6YCJEy59g5KRzNYHfw==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.1.3.tgz",
|
||||
"integrity": "sha512-ObaUcj+BHo/aBL1weyM3orApaHyAR5Phr3YNEpQEifxjZbNKM1iO5X5prN4OqEv3H+7o5e/Wh9Fy3N7Vvd+psA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -378,13 +378,13 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rspack/core": {
|
||||
"version": "2.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.1.8.tgz",
|
||||
"integrity": "sha512-na1kyA6Mj8/LWw9O3A8NsrG9rNKN3Iq2WiXrEuIwsU5r/Nl/evm3hO7bWKHxgsRyydI6W7okwx3MXgf8rzel6g==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.1.3.tgz",
|
||||
"integrity": "sha512-1iGnxLrP+iyY0ZSjLZeQTaxrISpQz4yLyqJPmaF/l4uw27/dBcrloszAeLOJQ9jiv7EJtU0T5zB+LOFPpivIxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rspack/binding": "2.1.8"
|
||||
"@rspack/binding": "2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
@@ -419,21 +419,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rspress/core": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/core/-/core-2.0.19.tgz",
|
||||
"integrity": "sha512-m0KfQNNXxjP975652nIOwUTqrvbJapRp4NpnoQMc5heawGhkC4+F7zTHvxY+huvzGYnKtL2fMMTrgWhEjKkrug==",
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/core/-/core-2.0.18.tgz",
|
||||
"integrity": "sha512-DBpsr/6XAItQkZPL5FSjthLGuzdG9ks/7EOxkqaaXp93uAT54LO0PD5Dkoy6ydup1PnvkpHyiHpUyDcnHHTVhg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mdx-js/mdx": "^3.1.1",
|
||||
"@mdx-js/react": "^3.1.1",
|
||||
"@rsbuild/core": "^2.1.8",
|
||||
"@rsbuild/core": "^2.1.5",
|
||||
"@rsbuild/plugin-react": "~2.1.0",
|
||||
"@rspress/shared": "2.0.19",
|
||||
"@rspress/shared": "2.0.18",
|
||||
"@shikijs/rehype": "^4.2.0",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/react": "^19.2.17",
|
||||
"@unhead/react": "^2.1.16",
|
||||
"@types/unist": "^3.0.3",
|
||||
"@unhead/react": "^2.1.15",
|
||||
"body-scroll-lock": "4.0.0-beta.0",
|
||||
"clsx": "2.1.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
@@ -444,9 +443,10 @@
|
||||
"mdast-util-mdxjs-esm": "^2.0.1",
|
||||
"medium-zoom": "1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"react": "^19.2.8",
|
||||
"react-dom": "^19.2.8",
|
||||
"react": "^19.2.7",
|
||||
"react-dom": "^19.2.7",
|
||||
"react-lazy-with-preload": "^2.2.1",
|
||||
"react-reconciler": "0.33.0",
|
||||
"react-render-to-markdown": "19.1.0",
|
||||
"react-router-dom": "^7.18.1",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
@@ -460,9 +460,9 @@
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"shiki": "^4.2.0",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-remove": "^4.0.0",
|
||||
"unist-util-visit": "^5.1.0",
|
||||
"unist-util-visit-children": "^3.0.0",
|
||||
"vfile": "^6.0.3"
|
||||
"unist-util-visit-children": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"rspress": "bin/rspress.js"
|
||||
@@ -472,9 +472,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rspress/plugin-client-redirects": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-client-redirects/-/plugin-client-redirects-2.0.19.tgz",
|
||||
"integrity": "sha512-BUwgEyj8vCkU58cV3Gp97aTSnfGJm7aXh40K0Dot1BqsCQ8ekdsMuaLXrICROdP9/ctd4oALtLBkOE+PKTa4Sg==",
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-client-redirects/-/plugin-client-redirects-2.0.18.tgz",
|
||||
"integrity": "sha512-q70ufN0S125kl0QlucO7JuiZ0WJaxFOtPPoGu7eWwam9fb+i4YsWnOWtAKSKGH4JP5+897mgpDPP+dmfl9DPCw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -485,9 +485,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rspress/plugin-sitemap": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-sitemap/-/plugin-sitemap-2.0.19.tgz",
|
||||
"integrity": "sha512-9ydrpj9hmmXWKWKIXUqJ1UrfxSvfxhHZRBZLb5OkTlOuQBNAg6BpsrW1WHoJqJr7p+3zqlz7S/9HTzSA3+EYcA==",
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/plugin-sitemap/-/plugin-sitemap-2.0.18.tgz",
|
||||
"integrity": "sha512-XfaXzZx+ASN9OMTc0fOvW8QmbmyCyDWkO8xJj4XF4E0YJtsu7j/65+v8/KXXdwpywOfUIQ6M94/meRTy2urNmQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -498,16 +498,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rspress/shared": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/shared/-/shared-2.0.19.tgz",
|
||||
"integrity": "sha512-INrETllWuR49lksqCz+xeLSO6rKtHA+5Ix2YQWcP9nerCuTSyGYwH8eBC0HrIacJkGHxB8wkkbV99tyzGtY8Wg==",
|
||||
"version": "2.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@rspress/shared/-/shared-2.0.18.tgz",
|
||||
"integrity": "sha512-GJswqJQCPSxvBt5r+gJzz8Em8EEK/sOmCQjTpemTvldvxr1Lva85BGVnSQZOgofnM0nrjt18kn4mmnuuSstbpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rsbuild/core": "^2.1.8",
|
||||
"@rsbuild/core": "^2.1.5",
|
||||
"@shikijs/rehype": "^4.2.0",
|
||||
"@types/react": "^19.2.17",
|
||||
"mdast-util-mdx-jsx": "^3.2.0",
|
||||
"unified": "^11.0.5"
|
||||
}
|
||||
},
|
||||
@@ -725,6 +723,7 @@
|
||||
"integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
}
|
||||
@@ -1084,13 +1083,13 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@unhead/react": {
|
||||
"version": "2.1.17",
|
||||
"resolved": "https://registry.npmjs.org/@unhead/react/-/react-2.1.17.tgz",
|
||||
"integrity": "sha512-KmcYksDjlLozL0fxUjIDwH/0k6+Lg2HWHLUPlkRW8Gl08hdB1AbLB5iU9QxFvkaT8p0Q4dFEqZWnz3g6RMeiRA==",
|
||||
"version": "2.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@unhead/react/-/react-2.1.15.tgz",
|
||||
"integrity": "sha512-5hfAaZ3XJq9JkspRzZdSPsMrXXA8v/SKiEOxZcN9L40o44byF/50bcQuOLgSSCAx8802mI5VG32KZXWTtsLu9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"unhead": "2.1.17"
|
||||
"unhead": "2.1.15"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/harlan-zw"
|
||||
@@ -1273,7 +1272,8 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
@@ -3176,9 +3176,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "19.2.8",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
|
||||
"integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
|
||||
"version": "19.2.7",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
|
||||
"integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -3186,16 +3186,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "19.2.8",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
|
||||
"integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
|
||||
"version": "19.2.7",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
|
||||
"integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.8"
|
||||
"react": "^19.2.7"
|
||||
}
|
||||
},
|
||||
"node_modules/react-lazy-with-preload": {
|
||||
@@ -3736,9 +3736,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/unhead": {
|
||||
"version": "2.1.17",
|
||||
"resolved": "https://registry.npmjs.org/unhead/-/unhead-2.1.17.tgz",
|
||||
"integrity": "sha512-HLMKXOszRhAPBrr6VlqCeVeJq2kbC4kXwzGLEZvvojPLWNYTJw22xG7Bfwhsvs31+IBet3Wl8ADg9dwYdyphfQ==",
|
||||
"version": "2.1.15",
|
||||
"resolved": "https://registry.npmjs.org/unhead/-/unhead-2.1.15.tgz",
|
||||
"integrity": "sha512-MCt5T90mCWyr3Z6pUCdM9lVRXoMoVBlL7z7U4CYVIiaDiuzad/UCfLuMqz5MeNmpZUgoBCQnrucJimU7EZR+XA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3810,6 +3810,22 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/unist-util-remove": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz",
|
||||
"integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/unist": "^3.0.0",
|
||||
"unist-util-is": "^6.0.0",
|
||||
"unist-util-visit-parents": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/unist-util-stringify-position": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum RoomCommand {
|
||||
/// List all rooms the server knows about
|
||||
#[command(name = "list", alias = "list-rooms")]
|
||||
#[clap(alias = "list")]
|
||||
ListRooms {
|
||||
page: Option<usize>,
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ pub enum ServerCommand {
|
||||
},
|
||||
|
||||
/// Hot-reload the server
|
||||
#[command(name = "reload", alias = "reload-mods")]
|
||||
#[clap(alias = "reload")]
|
||||
ReloadMods,
|
||||
|
||||
#[cfg(unix)]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use service::registration_tokens::TokenExpires;
|
||||
|
||||
impl crate::Context<'_> {
|
||||
pub(super) async fn issue_registration_token(&self, expires: super::TokenExpires) -> Result {
|
||||
pub(super) async fn issue_token(&self, expires: super::TokenExpires) -> Result {
|
||||
let expires = {
|
||||
if expires.immortal {
|
||||
None
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
pub enum TokenCommand {
|
||||
/// Issue a new registration token
|
||||
#[clap(name = "issue")]
|
||||
IssueRegistrationToken {
|
||||
IssueToken {
|
||||
/// When this token will expire.
|
||||
#[command(flatten)]
|
||||
expires: TokenExpires,
|
||||
|
||||
+16
-33
@@ -20,7 +20,7 @@
|
||||
tag::{TagEvent, TagEventContent, TagInfo},
|
||||
},
|
||||
};
|
||||
use service::users::{AccountStatus, DeviceToken, HashedPassword};
|
||||
use service::users::{AccountStatus, HashedPassword};
|
||||
|
||||
use crate::{
|
||||
get_room_info,
|
||||
@@ -59,42 +59,13 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
||||
|
||||
self.services
|
||||
.users
|
||||
.create_local_account(
|
||||
&user_id,
|
||||
Some(HashedPassword::new(password)?),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.create_local_account(&user_id, Some(HashedPassword::new(password)?), None)
|
||||
.await?;
|
||||
|
||||
self.write_str(&format!("Created user {user_id} with password `{password}`"))
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn issue_access_token(&self, username: String, password: String) -> Result {
|
||||
let user_id = parse_active_local_user_id(self.services, &username).await?;
|
||||
|
||||
let user_id = self
|
||||
.services
|
||||
.users
|
||||
.check_password(&user_id, &password)
|
||||
.await?;
|
||||
let token = DeviceToken::new_random();
|
||||
|
||||
let device_id = self
|
||||
.services
|
||||
.users
|
||||
.create_device(&user_id, None, Some(token.clone()), None, None)
|
||||
.await?;
|
||||
|
||||
self.write_str(&format!(
|
||||
"Created device `{device_id}` with access token `{}` for {user_id}",
|
||||
token.into_token()
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) -> Result {
|
||||
// Validate user id
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
@@ -131,6 +102,7 @@ pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) ->
|
||||
}
|
||||
|
||||
pub(super) async fn suspend(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
@@ -143,7 +115,7 @@ pub(super) async fn suspend(&self, user_id: String) -> Result {
|
||||
// TODO: Record the actual user that sent the suspension where possible
|
||||
self.services
|
||||
.users
|
||||
.suspend_account(&user_id, self.sender_or_service_user())
|
||||
.suspend_account(&user_id, self.sender)
|
||||
.await;
|
||||
|
||||
self.write_str(&format!("User {user_id} has been suspended."))
|
||||
@@ -151,6 +123,7 @@ pub(super) async fn suspend(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn unsuspend(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
@@ -962,6 +935,7 @@ pub(super) async fn force_leave_remote_room(
|
||||
}
|
||||
|
||||
pub(super) async fn lock(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
@@ -974,7 +948,7 @@ pub(super) async fn lock(&self, user_id: String) -> Result {
|
||||
|
||||
self.services
|
||||
.users
|
||||
.lock_account(&user_id, self.sender_or_service_user())
|
||||
.lock_account(&user_id, self.sender)
|
||||
.await;
|
||||
|
||||
self.write_str(&format!("User {user_id} has been locked."))
|
||||
@@ -982,6 +956,7 @@ pub(super) async fn lock(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn unlock(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
self.services.users.unlock_account(&user_id).await;
|
||||
@@ -991,6 +966,7 @@ pub(super) async fn unlock(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn logout(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
@@ -1016,6 +992,7 @@ pub(super) async fn logout(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn disable_login(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
@@ -1034,6 +1011,7 @@ pub(super) async fn disable_login(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn enable_login(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_active_local_user_id(self.services, &user_id).await?;
|
||||
|
||||
self.services.users.enable_login(&user_id);
|
||||
@@ -1042,6 +1020,7 @@ pub(super) async fn enable_login(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn get_email(&self, user_id: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
|
||||
match self
|
||||
@@ -1060,6 +1039,8 @@ pub(super) async fn get_email(&self, user_id: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn get_user_by_email(&self, email: String) -> Result {
|
||||
self.bail_restricted()?;
|
||||
|
||||
let Ok(email) = Address::try_from(email) else {
|
||||
return Err!("Invalid email address.");
|
||||
};
|
||||
@@ -1082,6 +1063,8 @@ pub(super) async fn get_user_by_email(&self, email: String) -> Result {
|
||||
}
|
||||
|
||||
pub(super) async fn change_email(&self, user_id: String, email: Option<String>) -> Result {
|
||||
self.bail_restricted()?;
|
||||
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
let Ok(new_email) = email.map(Address::try_from).transpose() else {
|
||||
return Err!("Invalid email address.");
|
||||
|
||||
+2
-11
@@ -10,7 +10,7 @@
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum UserCommand {
|
||||
/// Create a new user
|
||||
#[command(name = "create", alias = "create-user")]
|
||||
#[clap(alias = "create")]
|
||||
CreateUser {
|
||||
/// Username of the new user
|
||||
username: String,
|
||||
@@ -18,15 +18,6 @@ pub enum UserCommand {
|
||||
password: Option<String>,
|
||||
},
|
||||
|
||||
/// 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.
|
||||
#[clap(name = "issue-token")]
|
||||
IssueAccessToken {
|
||||
username: String,
|
||||
password: String,
|
||||
},
|
||||
|
||||
/// Reset user password
|
||||
ResetPassword {
|
||||
/// Log out existing sessions
|
||||
@@ -163,7 +154,7 @@ pub enum UserCommand {
|
||||
},
|
||||
|
||||
/// List local users in the database
|
||||
#[command(name = "list", alias = "list-users")]
|
||||
#[clap(alias = "list")]
|
||||
ListUsers,
|
||||
|
||||
/// Lists all the rooms (local and remote) that the specified user is
|
||||
|
||||
@@ -62,6 +62,8 @@ zstd_compression = [
|
||||
"reqwest/zstd",
|
||||
]
|
||||
|
||||
admin_api = []
|
||||
|
||||
[dependencies]
|
||||
async-trait.workspace = true
|
||||
axum-extra.workspace = true
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pub mod rooms;
|
||||
@@ -1,36 +0,0 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result};
|
||||
use futures::StreamExt;
|
||||
use ruma::OwnedRoomId;
|
||||
use ruminuwuity::admin::continuwuity::rooms;
|
||||
|
||||
use crate::Ruma;
|
||||
|
||||
/// # `GET /_continuwuity/admin/rooms/list`
|
||||
///
|
||||
/// Lists all rooms known to this server, excluding banned ones.
|
||||
pub(crate) async fn list_rooms(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<rooms::list::v1::Request>,
|
||||
) -> Result<rooms::list::v1::Response> {
|
||||
let sender_user = body.identity.expect_sender_user()?;
|
||||
if !services.users.is_admin(sender_user).await {
|
||||
return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
|
||||
}
|
||||
|
||||
let mut rooms: Vec<OwnedRoomId> = services
|
||||
.rooms
|
||||
.metadata
|
||||
.iter_ids()
|
||||
.filter_map(|room_id| async move {
|
||||
if !services.rooms.metadata.is_banned(&room_id).await {
|
||||
Some(room_id.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.await;
|
||||
rooms.sort();
|
||||
Ok(rooms::list::v1::Response::new(rooms))
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
pub mod ban;
|
||||
pub mod list;
|
||||
@@ -25,6 +25,7 @@
|
||||
};
|
||||
use service::{mailer::messages, uiaa::UiaaInitiator, users::HashedPassword};
|
||||
|
||||
use super::DEVICE_ID_LENGTH;
|
||||
use crate::{Ruma, router::ClientIdentity};
|
||||
|
||||
pub(crate) mod register;
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result, debug_info, info};
|
||||
use conduwuit::{
|
||||
Err, Result, debug_info, info,
|
||||
utils::{self},
|
||||
};
|
||||
use conduwuit_service::Services;
|
||||
use futures::StreamExt;
|
||||
use lettre::{Address, message::Mailbox};
|
||||
@@ -21,6 +24,7 @@
|
||||
users::{DeviceToken, HashedPassword},
|
||||
};
|
||||
|
||||
use super::DEVICE_ID_LENGTH;
|
||||
use crate::{Ruma, client_ip::ClientIp};
|
||||
|
||||
/// # `POST /_matrix/client/v3/register`
|
||||
@@ -95,13 +99,7 @@ pub(crate) async fn register_route(
|
||||
|
||||
services
|
||||
.users
|
||||
.create_local_account(
|
||||
&user_id,
|
||||
Some(password),
|
||||
identity.email,
|
||||
Some(&client),
|
||||
body.initial_device_display_name.as_deref(),
|
||||
)
|
||||
.create_local_account(&user_id, Some(password), identity.email)
|
||||
.await?;
|
||||
|
||||
user_id
|
||||
@@ -116,21 +114,26 @@ pub(crate) async fn register_route(
|
||||
)));
|
||||
}
|
||||
|
||||
// Generate new device id if the user didn't specify one
|
||||
let device_id = body
|
||||
.device_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| utils::random_string(DEVICE_ID_LENGTH).into());
|
||||
|
||||
// Generate new token for the device
|
||||
let new_token = DeviceToken::new_random();
|
||||
|
||||
// Create device for this account
|
||||
let device_id = services
|
||||
services
|
||||
.users
|
||||
.create_device(
|
||||
&user_id,
|
||||
body.device_id.clone(),
|
||||
&device_id,
|
||||
Some(new_token.clone()),
|
||||
body.initial_device_display_name.clone(),
|
||||
Some(client.to_string()),
|
||||
)
|
||||
.await?;
|
||||
|
||||
(Some(new_token), Some(device_id))
|
||||
} else {
|
||||
// Don't create a device for inhibited logins
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result};
|
||||
use futures::future::{join, join3};
|
||||
use futures::join;
|
||||
use ruma::api::client::admin::{is_user_locked, lock_user};
|
||||
|
||||
use crate::Ruma;
|
||||
@@ -12,15 +12,7 @@ pub(crate) async fn get_lock_status(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<is_user_locked::v1::Request>,
|
||||
) -> Result<is_user_locked::v1::Response> {
|
||||
let (admin, status) = join(
|
||||
services.users.is_admin(body.identity.expect_sender_user()?),
|
||||
services.users.status(&body.user_id),
|
||||
)
|
||||
.await;
|
||||
|
||||
if !admin {
|
||||
return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
|
||||
}
|
||||
let status = services.users.status(&body.user_id).await;
|
||||
|
||||
status.ensure_active()?;
|
||||
|
||||
@@ -36,22 +28,14 @@ pub(crate) async fn put_lock_status(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<lock_user::v1::Request>,
|
||||
) -> Result<lock_user::v1::Response> {
|
||||
let sender_user = body.identity.expect_sender_user()?;
|
||||
let sender_user = body.identity.sender_user();
|
||||
|
||||
let (sender_admin, status, target_admin) = join3(
|
||||
services.users.is_admin(sender_user),
|
||||
services.users.status(&body.user_id),
|
||||
services.users.is_admin(&body.user_id),
|
||||
)
|
||||
.await;
|
||||
|
||||
if !sender_admin {
|
||||
return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
|
||||
}
|
||||
let (status, target_admin) =
|
||||
join!(services.users.status(&body.user_id), services.users.is_admin(&body.user_id),);
|
||||
|
||||
status.ensure_active()?;
|
||||
|
||||
if body.user_id == *sender_user {
|
||||
if sender_user.is_some_and(|sender_user| body.user_id == sender_user) {
|
||||
return Err!(Request(Forbidden("You cannot lock yourself")));
|
||||
}
|
||||
|
||||
@@ -79,7 +63,7 @@ pub(crate) async fn put_lock_status(
|
||||
// Notify the admin room that an account has been un/suspended
|
||||
services
|
||||
.admin
|
||||
.send_text(&format!("{} has been {} by {}.", body.user_id, action, sender_user))
|
||||
.send_text(&format!("{} has been {} by {}.", body.user_id, action, body.identity))
|
||||
.await;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod lock;
|
||||
pub(crate) mod site;
|
||||
mod suspend;
|
||||
|
||||
pub(crate) use self::{lock::*, suspend::*};
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
pub(crate) mod rooms;
|
||||
pub(crate) mod users;
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use crate::{Ruma, client::leave_room};
|
||||
|
||||
/// # `PUT /_continuwuity/admin/rooms/{roomID}/ban`
|
||||
/// # `PUT /_continuwuity/admin/v1/rooms/{roomID}/ban`
|
||||
///
|
||||
/// Bans or unbans a room.
|
||||
pub(crate) async fn ban_room(
|
||||
@@ -0,0 +1,178 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::{
|
||||
Event, Result,
|
||||
utils::stream::{BroadbandExt, WidebandExt},
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use ruma::{
|
||||
OwnedRoomId,
|
||||
events::{
|
||||
StateEventType,
|
||||
room::{
|
||||
create::RoomCreateEventContent,
|
||||
encryption::PossiblyRedactedRoomEncryptionEventContent,
|
||||
tombstone::PossiblyRedactedRoomTombstoneEventContent,
|
||||
},
|
||||
},
|
||||
};
|
||||
use ruminuwuity::admin::continuwuity::rooms;
|
||||
use tokio::join;
|
||||
|
||||
use crate::Ruma;
|
||||
|
||||
/// # `GET /_continuwuity/admin/rooms`
|
||||
///
|
||||
/// Lists all room IDs known to this server, excluding banned ones.
|
||||
///
|
||||
/// This is the legacy version of the endpoint, which does not support
|
||||
/// pagination or including banned rooms. It is recommended to use the
|
||||
/// `/v1/rooms` endpoint instead. This endpoint may be removed in a future
|
||||
/// release.
|
||||
pub(crate) async fn legacy_list_rooms(
|
||||
State(services): State<crate::State>,
|
||||
_body: Ruma<rooms::list::unstable::Request>,
|
||||
) -> Result<rooms::list::unstable::Response> {
|
||||
let mut rooms: Vec<OwnedRoomId> = services
|
||||
.rooms
|
||||
.metadata
|
||||
.iter_ids()
|
||||
.filter_map(|room_id| async move {
|
||||
if !services.rooms.metadata.is_banned(&room_id).await {
|
||||
Some(room_id.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.await;
|
||||
rooms.sort();
|
||||
Ok(rooms::list::unstable::Response::new(rooms))
|
||||
}
|
||||
|
||||
/// # `GET /_continuwuity/admin/v1/rooms`
|
||||
///
|
||||
/// Lists rooms known to this server.
|
||||
pub(crate) async fn list_rooms(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<rooms::list::v1::Request>,
|
||||
) -> Result<rooms::list::v1::Response> {
|
||||
let include_banned_rooms = body.include_banned_rooms;
|
||||
let rooms = services
|
||||
.rooms
|
||||
.metadata
|
||||
.iter_ids()
|
||||
.wide_filter_map(|room_id| async move {
|
||||
if include_banned_rooms || !services.rooms.metadata.is_banned(&room_id).await {
|
||||
Some(room_id.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.skip(body.offset.unwrap_or_default())
|
||||
.take(body.limit.unwrap_or(100).min(100))
|
||||
.broad_filter_map(|room_id| async move {
|
||||
let (
|
||||
banned,
|
||||
disabled,
|
||||
member_count,
|
||||
local_member_count,
|
||||
resident_server_count,
|
||||
published,
|
||||
create_event,
|
||||
encryption_event,
|
||||
name_event,
|
||||
topic_event,
|
||||
canonical_alias_event,
|
||||
join_rules_event,
|
||||
history_visibility_event,
|
||||
tombstone_event,
|
||||
) = join!(
|
||||
services.rooms.metadata.is_banned(&room_id),
|
||||
services.rooms.metadata.is_disabled(&room_id),
|
||||
services.rooms.state_cache.room_joined_count(&room_id),
|
||||
services
|
||||
.rooms
|
||||
.state_cache
|
||||
.active_local_users_in_room(&room_id)
|
||||
.count(),
|
||||
services.rooms.state_cache.room_servers(&room_id).count(),
|
||||
services.rooms.directory.is_public_room(&room_id),
|
||||
services.rooms.state_accessor.room_state_get(
|
||||
&room_id,
|
||||
&StateEventType::RoomCreate,
|
||||
""
|
||||
),
|
||||
services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get_content::<PossiblyRedactedRoomEncryptionEventContent>(
|
||||
&room_id,
|
||||
&StateEventType::RoomEncryption,
|
||||
""
|
||||
),
|
||||
services.rooms.state_accessor.room_state_get_content(
|
||||
&room_id,
|
||||
&StateEventType::RoomName,
|
||||
""
|
||||
),
|
||||
services.rooms.state_accessor.room_state_get_content(
|
||||
&room_id,
|
||||
&StateEventType::RoomTopic,
|
||||
""
|
||||
),
|
||||
services.rooms.state_accessor.room_state_get_content(
|
||||
&room_id,
|
||||
&StateEventType::RoomCanonicalAlias,
|
||||
""
|
||||
),
|
||||
services.rooms.state_accessor.room_state_get_content(
|
||||
&room_id,
|
||||
&StateEventType::RoomJoinRules,
|
||||
""
|
||||
),
|
||||
services.rooms.state_accessor.room_state_get_content(
|
||||
&room_id,
|
||||
&StateEventType::RoomHistoryVisibility,
|
||||
""
|
||||
),
|
||||
services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get_content::<PossiblyRedactedRoomTombstoneEventContent>(
|
||||
&room_id,
|
||||
&StateEventType::RoomTombstone,
|
||||
""
|
||||
),
|
||||
);
|
||||
let Ok(create_event) = create_event else {
|
||||
return None;
|
||||
};
|
||||
let create_content = create_event
|
||||
.get_content::<RoomCreateEventContent>()
|
||||
.expect("m.room.create content must be valid");
|
||||
Some(rooms::list::v1::MinimalRoomInfo {
|
||||
room_id,
|
||||
banned,
|
||||
disabled,
|
||||
member_count: usize::try_from(member_count.unwrap_or_default())
|
||||
.expect("u64 should fit in usize"),
|
||||
local_member_count,
|
||||
resident_server_count,
|
||||
creators: vec![create_event.sender],
|
||||
encrypted: encryption_event.is_ok_and(|c| c.algorithm.is_some()),
|
||||
federated: create_content.federate,
|
||||
published,
|
||||
version: create_content.room_version,
|
||||
name: name_event.unwrap_or(None),
|
||||
topic: topic_event.unwrap_or(None),
|
||||
canonical_alias: canonical_alias_event.unwrap_or(None),
|
||||
join_rules: join_rules_event.unwrap_or(None),
|
||||
history_visibility: history_visibility_event.unwrap_or(None),
|
||||
predecessor: create_content.predecessor.map(|c| c.room_id),
|
||||
successor: tombstone_event.map_or(None, |c| c.replacement_room),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
.await;
|
||||
Ok(rooms::list::v1::Response::new(rooms))
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mod ban;
|
||||
mod list;
|
||||
|
||||
pub(crate) use ban::ban_room;
|
||||
pub(crate) use list::*;
|
||||
@@ -0,0 +1,142 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::{
|
||||
err, error, info,
|
||||
utils::{IterStream, stream::BroadbandExt},
|
||||
warn,
|
||||
};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use ruma::{api::client::profile::PropagateTo, profile::ProfileFieldValue};
|
||||
use ruminuwuity::admin::continuwuity::users;
|
||||
use service::users::{HashedPassword, ProfileFieldChange};
|
||||
|
||||
use crate::router::Ruma;
|
||||
|
||||
/// # `POST /_continuwuity/admin/v1/users/create`
|
||||
///
|
||||
/// Creates a new user.
|
||||
pub(crate) async fn create_user(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<users::create::v1::Request>,
|
||||
) -> conduwuit::Result<users::create::v1::Response> {
|
||||
let email = body
|
||||
.email
|
||||
.clone()
|
||||
.map(lettre::Address::try_from)
|
||||
.transpose()
|
||||
.map_err(|e| err!(Request(BadJson("Invalid email address: {e}"))))?;
|
||||
|
||||
let ref user_id = services
|
||||
.users
|
||||
.determine_registration_user_id(Some(body.localpart.clone()), email.as_ref(), None)
|
||||
.await?;
|
||||
|
||||
services.users.create_shadow_account(user_id).await?;
|
||||
|
||||
services
|
||||
.users
|
||||
.convert_to_local_account(user_id, HashedPassword::new(&body.password)?)
|
||||
.await?;
|
||||
|
||||
if let Some(email) = &email {
|
||||
services
|
||||
.threepid
|
||||
.associate_localpart_email(user_id.localpart(), email)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if body.suspended {
|
||||
services
|
||||
.users
|
||||
.suspend_account(user_id, body.identity.sender_user())
|
||||
.await;
|
||||
}
|
||||
if body.locked {
|
||||
services
|
||||
.users
|
||||
.lock_account(user_id, body.identity.sender_user())
|
||||
.await;
|
||||
}
|
||||
if body.login_disabled {
|
||||
services.users.disable_login(user_id);
|
||||
}
|
||||
if let Some(ref value) = body.display_name {
|
||||
services
|
||||
.users
|
||||
.set_profile_field(
|
||||
user_id,
|
||||
ProfileFieldChange::Set(ProfileFieldValue::DisplayName(value.to_owned())),
|
||||
PropagateTo::None,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
if let Some(ref value) = body.avatar_url {
|
||||
services
|
||||
.users
|
||||
.set_profile_field(
|
||||
user_id,
|
||||
ProfileFieldChange::Set(ProfileFieldValue::AvatarUrl(value.to_owned())),
|
||||
PropagateTo::None,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
if body.admin {
|
||||
services
|
||||
.admin
|
||||
.make_user_admin(user_id)
|
||||
.await
|
||||
.inspect_err(|e| error!("failed to make new user {user_id} an admin: {e}"))
|
||||
.ok();
|
||||
}
|
||||
|
||||
body.auto_join_rooms
|
||||
.clone()
|
||||
.into_iter()
|
||||
.stream()
|
||||
.chain(
|
||||
if body.skip_auto_join {
|
||||
vec![]
|
||||
} else {
|
||||
services.config.auto_join_rooms.clone()
|
||||
}
|
||||
.into_iter()
|
||||
.stream(),
|
||||
)
|
||||
.broad_filter_map(|room| async move {
|
||||
services
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_with_servers(&room, None)
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
warn!(
|
||||
"Failed to resolve room alias to room ID when attempting to auto join \
|
||||
{room}: {e}"
|
||||
);
|
||||
})
|
||||
.ok()
|
||||
})
|
||||
.for_each_concurrent(None, |(room_id, servers)| async move {
|
||||
match services
|
||||
.rooms
|
||||
.membership
|
||||
.join_room(
|
||||
user_id,
|
||||
&room_id,
|
||||
Some("Automatically joining this room upon registration".to_owned()),
|
||||
servers.as_ref(),
|
||||
)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
| Err(e) => {
|
||||
warn!("Failed to automatically join {user_id} to {room_id}: {e}");
|
||||
},
|
||||
| _ => {
|
||||
info!("Automatically joined room {user_id} to {room_id}");
|
||||
},
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
Ok(users::create::v1::Response::new(user_id.to_owned()))
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
use axum::extract::State;
|
||||
use conduwuit::utils::stream::WidebandExt;
|
||||
use futures::StreamExt;
|
||||
use ruminuwuity::admin::continuwuity::users;
|
||||
use tokio::join;
|
||||
|
||||
use crate::router::Ruma;
|
||||
|
||||
/// # `GET /_continuwuity/admin/v1/users`
|
||||
///
|
||||
/// Lists all users on this homeserver.
|
||||
pub(crate) async fn list_users(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<users::list::v1::Request>,
|
||||
) -> conduwuit::Result<users::list::v1::Response> {
|
||||
let users = services
|
||||
.users
|
||||
.stream_local_users()
|
||||
.skip(body.offset.unwrap_or_default())
|
||||
.take(body.limit.unwrap_or(100).min(100))
|
||||
.wide_filter_map(|user_id| async move {
|
||||
let (status, suspended, locked, admin, login_disabled) = join!(
|
||||
services.users.status(&user_id),
|
||||
services.users.is_suspended(&user_id),
|
||||
services.users.is_locked(&user_id),
|
||||
services.users.is_admin(&user_id),
|
||||
services.users.is_login_disabled(&user_id),
|
||||
);
|
||||
Some(users::list::v1::User {
|
||||
user_id: user_id.clone(),
|
||||
deactivated: !status.is_active(),
|
||||
suspended: suspended.unwrap_or_default(),
|
||||
locked: locked.unwrap_or_default(),
|
||||
admin,
|
||||
login_disabled,
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
Ok(users::list::v1::Response::new(users))
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
mod create;
|
||||
mod list;
|
||||
|
||||
pub(crate) use create::*;
|
||||
pub(crate) use list::*;
|
||||
@@ -67,7 +67,7 @@ pub(crate) async fn put_suspended_status(
|
||||
let action = if body.suspended {
|
||||
services
|
||||
.users
|
||||
.suspend_account(&body.user_id, sender_user)
|
||||
.suspend_account(&body.user_id, body.identity.sender_user())
|
||||
.await;
|
||||
"suspended"
|
||||
} else {
|
||||
|
||||
@@ -88,7 +88,7 @@ pub(crate) async fn update_device_route(
|
||||
.users
|
||||
.create_device(
|
||||
sender_user,
|
||||
Some(body.device_id.clone()),
|
||||
&body.device_id,
|
||||
None,
|
||||
body.display_name.clone(),
|
||||
Some(client.to_string()),
|
||||
|
||||
@@ -90,5 +90,8 @@
|
||||
pub(super) use voip::*;
|
||||
pub(super) use well_known::*;
|
||||
|
||||
/// generated device ID length
|
||||
const DEVICE_ID_LENGTH: usize = 10;
|
||||
|
||||
/// generated user access token length
|
||||
const TOKEN_LENGTH: usize = 32;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user