Compare commits

..

1 Commits

Author SHA1 Message Date
Ginger
eba0130f8e fix(complement): Fix complement conflicting with first-run
- Disabled first-run mode when running Complement tests
- Updated logging config under complement to be a bit less verbose
- Changed test result and log output locations
2026-03-03 18:43:53 +00:00
156 changed files with 1506 additions and 4726 deletions

View File

@@ -44,7 +44,7 @@ runs:
- name: Login to builtin registry
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
registry: ${{ env.BUILTIN_REGISTRY }}
username: ${{ inputs.registry_user }}
@@ -52,7 +52,7 @@ runs:
- name: Set up Docker Buildx
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
# Use persistent BuildKit if BUILDKIT_ENDPOINT is set (e.g. tcp://buildkit:8125)
driver: ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }}
@@ -61,7 +61,7 @@ runs:
- name: Extract metadata (tags) for Docker
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
flavor: |
latest=auto

View File

@@ -67,7 +67,7 @@ runs:
uses: ./.forgejo/actions/rust-toolchain
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
with:
# Use persistent BuildKit if BUILDKIT_ENDPOINT is set (e.g. tcp://buildkit:8125)
driver: ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }}
@@ -75,11 +75,11 @@ runs:
- name: Set up QEMU
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
uses: docker/setup-qemu-action@v4
uses: docker/setup-qemu-action@v3
- name: Login to builtin registry
if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }}
uses: docker/login-action@v4
uses: docker/login-action@v3
with:
registry: ${{ env.BUILTIN_REGISTRY }}
username: ${{ inputs.registry_user }}
@@ -87,7 +87,7 @@ runs:
- name: Extract metadata (labels, annotations) for Docker
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@v5
with:
images: ${{ inputs.images }}
# default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509
@@ -152,7 +152,7 @@ runs:
- name: inject cache into docker
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
uses: https://github.com/reproducible-containers/buildkit-cache-dance@v3.3.2
uses: https://github.com/reproducible-containers/buildkit-cache-dance@v3.3.0
with:
cache-map: |
{

View File

@@ -62,6 +62,10 @@ sync:
target: registry.gitlab.com/continuwuity/continuwuity
type: repository
<<: *tags-main
- source: *source
target: git.nexy7574.co.uk/mirrored/continuwuity
type: repository
<<: *tags-releases
- source: *source
target: ghcr.io/continuwuity/continuwuity
type: repository

View File

@@ -30,22 +30,22 @@ jobs:
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "distribution=$DISTRIBUTION" >> $GITHUB_OUTPUT
echo "Debian distribution: $DISTRIBUTION ($VERSION)"
#- name: Work around llvm-project#153385
# id: llvm-workaround
# run: |
# if [ -f /usr/share/apt/default-sequoia.config ]; then
# echo "Applying workaround for llvm-project#153385"
# mkdir -p /etc/crypto-policies/back-ends/
# cp /usr/share/apt/default-sequoia.config /etc/crypto-policies/back-ends/apt-sequoia.config
# sed -i 's/\(sha1\.second_preimage_resistance = \)2026-02-01/\12026-06-01/' /etc/crypto-policies/back-ends/apt-sequoia.config
# else
# echo "No workaround needed for llvm-project#153385"
# fi
- name: Work around llvm-project#153385
id: llvm-workaround
run: |
if [ -f /usr/share/apt/default-sequoia.config ]; then
echo "Applying workaround for llvm-project#153385"
mkdir -p /etc/crypto-policies/back-ends/
cp /usr/share/apt/default-sequoia.config /etc/crypto-policies/back-ends/apt-sequoia.config
sed -i 's/\(sha1\.second_preimage_resistance = \)2026-02-01/\12026-06-01/' /etc/crypto-policies/back-ends/apt-sequoia.config
else
echo "No workaround needed for llvm-project#153385"
fi
- name: Pick compatible clang version
id: clang-version
run: |
# both latest need to use clang-23, but oldstable and previous can just use clang
if [[ "${{ matrix.container }}" == "ubuntu-latest" ]]; then
if [[ "${{ matrix.container }}" == "ubuntu-latest" || "${{ matrix.container }}" == "debian-latest" ]]; then
echo "Using clang-23 package for ${{ matrix.container }}"
echo "version=clang-23" >> $GITHUB_OUTPUT
else

View File

@@ -1,103 +0,0 @@
name: Check Changelog
on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
issues: write
jobs:
check-changelog:
name: Check for changelog
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
sparse-checkout: .
- name: Check for changelog entry
id: check_files
run: |
git fetch origin ${GITHUB_BASE_REF}
# Check for Added (A) or Modified (M) files in changelog.d
CHANGELOG_CHANGES=$(git diff --name-status origin/${GITHUB_BASE_REF} HEAD -- changelog.d/)
SRC_CHANGES=$(git diff --name-status origin/${GITHUB_BASE_REF} HEAD -- src/)
echo "Changes in changelog.d/:"
echo "$CHANGELOG_CHANGES"
echo "Changes in src/:"
echo "$SRC_CHANGES"
if echo "$CHANGELOG_CHANGES" | grep -q "^[AM]"; then
echo "has_changelog=true" >> $GITHUB_OUTPUT
else
echo "has_changelog=false" >> $GITHUB_OUTPUT
fi
if [ -n "$SRC_CHANGES" ]; then
echo "src_changed=true" >> $GITHUB_OUTPUT
else
echo "src_changed=false" >> $GITHUB_OUTPUT
fi
- name: Manage PR Comment
uses: https://github.com/actions/github-script@v8
env:
HAS_CHANGELOG: ${{ steps.check_files.outputs.has_changelog }}
SRC_CHANGED: ${{ steps.check_files.outputs.src_changed }}
with:
script: |
const hasChangelog = process.env.HAS_CHANGELOG === 'true';
const srcChanged = process.env.SRC_CHANGED === 'true';
const commentSignature = '<!-- changelog-check-action -->';
const commentBody = `${commentSignature}\nPlease add a changelog fragment to \`changelog.d/\` describing your changes.`;
const { data: currentUser } = await github.rest.users.getAuthenticated();
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.id === currentUser.id &&
comment.body.includes(commentSignature)
);
const shouldWarn = srcChanged && !hasChangelog;
if (!shouldWarn) {
if (botComment) {
console.log('Changelog found or not required. Deleting existing warning comment.');
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
});
}
} else {
if (!botComment) {
console.log('Changelog missing and required. Creating warning comment.');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: commentBody,
});
}
}

View File

@@ -59,7 +59,7 @@ jobs:
registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
- name: Build and push Docker image by digest
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
file: "docker/Dockerfile"
@@ -146,7 +146,7 @@ jobs:
registry_password: ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
- name: Build and push max-perf Docker image by digest
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
file: "docker/Dockerfile"

View File

@@ -43,7 +43,7 @@ jobs:
name: Renovate
runs-on: ubuntu-latest
container:
image: ghcr.io/renovatebot/renovate:43.59.4@sha256:f951508dea1e7d71cbe6deca298ab0a05488e7631229304813f630cc06010892
image: ghcr.io/renovatebot/renovate:42.70.2@sha256:3c2ac1b94fa92ef2fa4d1a0493f2c3ba564454720a32fdbcac2db2846ff1ee47
options: --tmpfs /tmp:exec
steps:
- name: Checkout

View File

@@ -23,7 +23,7 @@ jobs:
persist-credentials: true
token: ${{ secrets.FORGEJO_TOKEN }}
- uses: https://github.com/cachix/install-nix-action@19effe9fe722874e6d46dd7182e4b8b7a43c4a99 # v31.10.0
- uses: https://github.com/cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0
with:
nix_path: nixpkgs=channel:nixos-unstable

4
.github/FUNDING.yml vendored
View File

@@ -1,4 +1,4 @@
github: [JadedBlueEyes, nexy7574, gingershaped]
custom:
- https://timedout.uk/donate.html
- https://jade.ellis.link/sponsors
- https://ko-fi.com/nexy7574
- https://ko-fi.com/JadedBlueEyes

View File

@@ -1,6 +1,5 @@
default_install_hook_types:
- pre-commit
- pre-push
- commit-msg
default_stages:
- pre-commit
@@ -24,7 +23,7 @@ repos:
- id: check-added-large-files
- repo: https://github.com/crate-ci/typos
rev: v1.44.0
rev: v1.43.5
hooks:
- id: typos
- id: typos
@@ -32,7 +31,7 @@ repos:
stages: [commit-msg]
- repo: https://github.com/crate-ci/committed
rev: v1.1.11
rev: v1.1.10
hooks:
- id: committed
@@ -46,14 +45,3 @@ repos:
pass_filenames: false
stages:
- pre-commit
- repo: local
hooks:
- id: cargo-clippy
name: cargo clippy
entry: cargo clippy -- -D warnings
language: system
pass_filenames: false
types: [rust]
stages:
- pre-push

View File

@@ -1,32 +1,3 @@
# Continuwuity 0.5.6 (2026-03-03)
## Security
- Admin escape commands received over federation will never be executed, as this is never valid in a genuine situation. Contributed by @Jade.
- Fixed data amplification vulnerability (CWE-409) that affected configurations with server-side compression enabled (non-default). Contributed by @nex.
## 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))
- 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))
## 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 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 `!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.
# Continuwuity v0.5.5 (2026-02-15)
## Features

View File

@@ -22,21 +22,25 @@ ### Pre-commit Checks
- Validating YAML, JSON, and TOML files
- Checking for merge conflicts
You can run these checks locally by installing [prek](https://github.com/j178/prek):
You can run these checks locally by installing [prefligit](https://github.com/j178/prefligit):
```bash
# Install prek using cargo-binstall
cargo binstall prek
# Requires UV: https://docs.astral.sh/uv/getting-started/installation/
# Mac/linux: curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows: powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Install prefligit using cargo-binstall
cargo binstall prefligit
# Install git hooks to run checks automatically
prek install
prefligit install
# Run all checks
prek --all-files
prefligit --all-files
```
Alternatively, you can use [pre-commit][pre-commit]:
Alternatively, you can use [pre-commit](https://pre-commit.com/):
```bash
# Requires python
@@ -50,9 +54,7 @@ # Run all checks manually
pre-commit run --all-files
```
These same checks are run in CI via the prek-checks workflow to ensure consistency. These must pass before the PR is merged.
[pre-commit]: https://pre-commit.com/
These same checks are run in CI via the prefligit-checks workflow to ensure consistency. These must pass before the PR is merged.
### Running tests locally
@@ -111,7 +113,7 @@ ### Writing documentation
### Commit Messages
Continuwuity follows the [Conventional Commits][conventional-commits] specification for commit messages. This provides a standardized format that makes the commit history more readable and enables automated tools to generate changelogs.
Continuwuity follows the [Conventional Commits](https://www.conventionalcommits.org/) specification for commit messages. This provides a standardized format that makes the commit history more readable and enables automated tools to generate changelogs.
The basic structure is:
@@ -170,7 +172,6 @@ ### Creating pull requests
their contributions accepted. This includes users who have been banned from
continuwuity Matrix rooms for Code of Conduct violations.
[conventional-commits]: https://www.conventionalcommits.org/
[issues]: https://forgejo.ellis.link/continuwuation/continuwuity/issues
[continuwuity-matrix]: https://matrix.to/#/#continuwuity:continuwuity.org?via=continuwuity.org&via=ellis.link&via=explodie.org&via=matrix.org
[complement]: https://github.com/matrix-org/complement/
@@ -178,32 +179,3 @@ ### Creating pull requests
[nodejs-download]: https://nodejs.org/en/download
[rspress]: https://rspress.rs/
[documentation.yml]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/.forgejo/workflows/documentation.yml
#### Writing news fragments
In order to make writing our changelogs easier, we make use of [Towncrier]. Towncrier builds changelogs based on
"news fragments", which are little markdown files in the `changelog.d/` directory that describe individual changes.
When you make a pull request that changes functionality, fixes a bug, or adds documentation, please add a news fragment
describing your change. The file name *MUST* be in the format of `{pull_request_number}.{type}`, where `{type}` is one
of the following:
- `feature` - for new features
- `bugfix` - for bug fixes
- `doc` - for documentation changes
- `misc` - for other changes that don't fit the above categories
For example:
```bash
$ echo "Fixed the quantum flux stabiliser. Contributed by @alice." > changelog.d/42.bugfix
```
(Note: If you want to credit yourself, you should reference your forgejo handle, however links to other platforms are also acceptable.)
When the next release is made, Towncrier will automatically include your news fragment in the changelog.
You can read more about writing news fragments in the [Towncrier tutorial][tt].
[Towncrier]: https://towncrier.readthedocs.io/
[tt]: https://towncrier.readthedocs.io/en/stable/tutorial.html#creating-news-fragments

903
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ license = "Apache-2.0"
# See also `rust-toolchain.toml`
readme = "README.md"
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
version = "0.5.7-alpha.1"
version = "0.5.5"
[workspace.metadata.crane]
name = "conduwuit"
@@ -99,7 +99,7 @@ features = [
[workspace.dependencies.axum-extra]
version = "0.12.0"
default-features = false
features = ["typed-header", "tracing", "cookie"]
features = ["typed-header", "tracing"]
[workspace.dependencies.axum-server]
version = "0.7.2"
@@ -144,7 +144,6 @@ features = [
"socks",
"hickory-dns",
"http2",
"stream",
]
[workspace.dependencies.serde]
@@ -159,7 +158,7 @@ features = ["raw_value"]
# Used for appservice registration files
[workspace.dependencies.serde-saphyr]
version = "0.0.21"
version = "0.0.19"
# Used to load forbidden room/user regex from config
[workspace.dependencies.serde_regex]
@@ -278,7 +277,7 @@ features = [
]
[workspace.dependencies.hyper-util]
version = "=0.1.20"
version = "=0.1.17"
default-features = false
features = [
"server-auto",
@@ -332,7 +331,7 @@ version = "0.4.0"
# used for MPMC channels
[workspace.dependencies.async-channel]
version = "2.5.0"
version = "2.3.1"
[workspace.dependencies.async-trait]
version = "0.1.88"
@@ -344,7 +343,7 @@ version = "0.1.2"
[workspace.dependencies.ruma]
git = "https://forgejo.ellis.link/continuwuation/ruwuma"
#branch = "conduwuit-changes"
rev = "a97b91adcc012ef04991d823b8b5a79c6686ae48"
rev = "bb12ed288a31a23aa11b10ba0fad22b7f985eb88"
features = [
"compat",
"rand",
@@ -364,7 +363,6 @@ features = [
"unstable-msc2870",
"unstable-msc3026",
"unstable-msc3061",
"unstable-msc3814",
"unstable-msc3245",
"unstable-msc3266",
"unstable-msc3381", # polls
@@ -388,7 +386,7 @@ features = [
[workspace.dependencies.rust-rocksdb]
git = "https://forgejo.ellis.link/continuwuation/rust-rocksdb-zaidoon1"
rev = "31fb8f772c7afcdc0061ab6a40cfa3a1be2fccd9"
rev = "61d9d23872197e9ace4a477f2617d5c9f50ecb23"
default-features = false
features = [
"multi-threaded-cf",
@@ -451,7 +449,7 @@ version = "0.46.0"
# jemalloc usage
[workspace.dependencies.tikv-jemalloc-sys]
git = "https://forgejo.ellis.link/continuwuation/jemallocator"
rev = "df86ff89d4b1e223b9f7d2dd2fbb7f202da7f554"
rev = "82af58d6a13ddd5dcdc7d4e91eae3b63292995b8"
default-features = false
features = [
"background_threads_runtime_support",
@@ -459,7 +457,7 @@ features = [
]
[workspace.dependencies.tikv-jemallocator]
git = "https://forgejo.ellis.link/continuwuation/jemallocator"
rev = "df86ff89d4b1e223b9f7d2dd2fbb7f202da7f554"
rev = "82af58d6a13ddd5dcdc7d4e91eae3b63292995b8"
default-features = false
features = [
"background_threads_runtime_support",
@@ -467,7 +465,7 @@ features = [
]
[workspace.dependencies.tikv-jemalloc-ctl]
git = "https://forgejo.ellis.link/continuwuation/jemallocator"
rev = "df86ff89d4b1e223b9f7d2dd2fbb7f202da7f554"
rev = "82af58d6a13ddd5dcdc7d4e91eae3b63292995b8"
default-features = false
features = ["use_std"]
@@ -493,7 +491,7 @@ features = [
]
[workspace.dependencies.rustyline-async]
version = "0.4.9"
version = "0.4.3"
default-features = false
[workspace.dependencies.termimad]
@@ -526,7 +524,7 @@ version = "0.4.13"
version = "2.0"
[workspace.dependencies.core_affinity]
version = "0.8.3"
version = "0.8.1"
[workspace.dependencies.libc]
version = "0.2"
@@ -550,6 +548,9 @@ version = "0.12.0"
default-features = false
features = ["sync", "tls-rustls", "rustls-provider"]
[workspace.dependencies.resolv-conf]
version = "0.7.5"
[workspace.dependencies.yansi]
version = "1.0.1"
@@ -568,25 +569,25 @@ version = "0.15.0"
# adds event for CTRL+\: https://forgejo.ellis.link/continuwuation/rustyline-async/src/branch/main/.patchy/0001-add-event-for-ctrl.patch
[patch.crates-io.rustyline-async]
git = "https://forgejo.ellis.link/continuwuation/rustyline-async"
rev = "b13aca2cc08d5f78303746cd192d9a03d73e768e"
rev = "e9f01cf8c6605483cb80b3b0309b400940493d7f"
# adds LIFO queue scheduling; this should be updated with PR progress.
[patch.crates-io.event-listener]
git = "https://forgejo.ellis.link/continuwuation/event-listener"
rev = "b2c19bcaf5a0a69c38c034e417bda04a9b991529"
rev = "fe4aebeeaae435af60087ddd56b573a2e0be671d"
[patch.crates-io.async-channel]
git = "https://forgejo.ellis.link/continuwuation/async-channel"
rev = "e990f0006b68dc9bace7a3c95fc90b5c4e44948d"
rev = "92e5e74063bf2a3b10414bcc8a0d68b235644280"
# adds affinity masks for selecting more than one core at a time
[patch.crates-io.core_affinity]
git = "https://forgejo.ellis.link/continuwuation/core_affinity_rs"
rev = "7c7a9dea35382743a63837cdd1d977efdb8f1b8a"
rev = "9c8e51510c35077df888ee72a36b4b05637147da"
# reverts hyperium#148 conflicting with our delicate federation resolver hooks
[patch.crates-io.hyper-util]
git = "https://forgejo.ellis.link/continuwuation/hyper-util"
rev = "09fcd3bf4656c81a8ad573bee410ab2b57f60b86"
rev = "5886d5292bf704c246206ad72d010d674a7b77d0"
#
# Our crates
@@ -966,6 +967,3 @@ needless_raw_string_hashes = "allow"
# TODO: Enable this lint & fix all instances
collapsible_if = "allow"
# TODO: break these apart
cognitive_complexity = "allow"

View File

@@ -1 +0,0 @@
Added support for using an admin command to issue self-service password reset links.

View File

@@ -1 +0,0 @@
Stopped left rooms from being unconditionally sent on initial sync, hopefully fixing spurious appearances of left rooms in some clients (and making sync faster as a bonus). Contributed by @ginger

View File

@@ -1 +0,0 @@
Fixed room alias deletion so removing one local alias no longer removes other aliases from room alias listings.

View File

@@ -1 +0,0 @@
Fixed corrupted appservice registrations causing the server to enter a crash loop. Contributed by @nex.

View File

@@ -1 +0,0 @@
Re-added support for reading registration tokens from a file. Contributed by @ginger and @benbot.

1
changelog.d/1393.bugfix Normal file
View File

@@ -0,0 +1 @@
Removed non-compliant nor functional room alias lookups over federation. Contributed by @nex

1
changelog.d/1399.feature Normal file
View File

@@ -0,0 +1 @@
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.

1
changelog.d/1418.bugfix Normal file
View File

@@ -0,0 +1 @@
Removed ability to set rocksdb as read only. Doing so would cause unintentional and buggy behaviour. Contributed by @Terryiscool160.

1
changelog.d/1421.bugfix Normal file
View File

@@ -0,0 +1 @@
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.

1
changelog.d/1428.feature Normal file
View File

@@ -0,0 +1 @@
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.

View File

@@ -1 +0,0 @@
Added Testing and Troubleshooting instructions for Livekit documentation. Contributed by @stratself.

View File

@@ -0,0 +1 @@
Added MSC3202 Device masquerading (not all of MSC3202). This should fix issues with enabling MSC4190 for some Mautrix bridges. Contributed by @Jade

1
changelog.d/1441.bugfix Normal file
View File

@@ -0,0 +1 @@
Removed the `allow_public_room_directory_without_auth` config option. Contributed by @0xnim.

1
changelog.d/1442.feature Normal file
View File

@@ -0,0 +1 @@
Implement MSC4143 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

1
changelog.d/1445.bugfix Normal file
View File

@@ -0,0 +1 @@
Fixed sliding sync v5 list ranges always starting from 0, causing extra rooms to be unnecessarily processed and returned. Contributed by @0xnim

View File

@@ -1 +0,0 @@
Prevent removing the admin room alias (`#admins`) to avoid accidentally breaking admin room functionality. Contributed by @0xnim

View File

@@ -1 +0,0 @@
Add new config option to allow or disallow search engine indexing through a `<meta ../>` tag. Defaults to blocking indexing (`content="noindex"`). Contributed by @s1lv3r and @ginger.

View File

@@ -1 +0,0 @@
Stripped `join_authorised_via_users_server` from json if user is already in room (@partha:cxy.run)

View File

@@ -1 +0,0 @@
Fixed internal server errors for fetching thumbnails. Contributed by @PerformativeJade

View File

@@ -0,0 +1 @@
Updated `list-backups` admin command to output one backup per line.

View File

@@ -0,0 +1 @@
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.

View File

@@ -15,18 +15,6 @@ disallowed-macros = [
{ path = "log::trace", reason = "use conduwuit_core::trace" },
]
[[disallowed-methods]]
path = "tokio::spawn"
reason = "use and pass conduwuit_core::server::Server::runtime() to spawn from"
[[disallowed-methods]]
path = "reqwest::Response::bytes"
reason = "bytes is unsafe, use limit_read via the conduwuit_core::utils::LimitReadExt trait instead"
[[disallowed-methods]]
path = "reqwest::Response::text"
reason = "text is unsafe, use limit_read_text via the conduwuit_core::utils::LimitReadExt trait instead"
[[disallowed-methods]]
path = "reqwest::Response::json"
reason = "json is unsafe, use limit_read_text via the conduwuit_core::utils::LimitReadExt trait instead"
disallowed-methods = [
{ path = "tokio::spawn", reason = "use and pass conduuwit_core::server::Server::runtime() to spawn from" },
]

View File

@@ -25,10 +25,6 @@
#
# Also see the `[global.well_known]` config section at the very bottom.
#
# If `client` is not set under `[global.well_known]`, the server name will
# be used as the base domain for user-facing links (such as password
# reset links) created by Continuwuity.
#
# Examples of delegation:
# - https://continuwuity.org/.well-known/matrix/server
# - https://continuwuity.org/.well-known/matrix/client
@@ -480,25 +476,18 @@
#yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse = false
# A static registration token that new users will have to provide when
# creating an account. This token does not supersede tokens from other
# sources, such as the `!admin token` command or the
# `registration_token_file` configuration option.
# creating an account. If unset and `allow_registration` is true,
# you must set
# `yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse`
# to true to allow open registration without any conditions.
#
# If you do not want to set a static token, the `!admin token` commands
# may also be used to manage registration tokens.
#
# example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
#
#registration_token =
# A path to a file containing static registration tokens, one per line.
# Tokens in this file do not supersede tokens from other sources, such as
# the `!admin token` command or the `registration_token` configuration
# option.
#
# The file will be read once, when Continuwuity starts. It is not
# currently reread when the server configuration is reloaded. If the file
# cannot be read, Continuwuity will fail to start.
#
#registration_token_file =
# The public site key for reCaptcha. If this is provided, reCaptcha
# becomes required during registration. If both captcha *and*
# registration token are enabled, both will be required during
@@ -1509,11 +1498,6 @@
#
#url_preview_user_agent = "continuwuity/<version> (bot; +https://continuwuity.org)"
# Determines whether audio and video files will be downloaded for URL
# previews.
#
#url_preview_allow_audio_video = false
# List of forbidden room aliases and room IDs as strings of regex
# patterns.
#
@@ -1799,11 +1783,6 @@
#
#config_reload_signal = true
# Allow search engines and crawlers to index Continuwuity's built-in
# webpages served under the `/_continuwuity/` prefix.
#
#allow_web_indexing = false
[global.tls]
# Path to a valid TLS certificate file.

View File

@@ -10,7 +10,7 @@ RUN rm -f /etc/apt/apt.conf.d/docker-clean
# Match Rustc version as close as possible
# rustc -vV
ARG LLVM_VERSION=21
ARG LLVM_VERSION=20
# ENV RUSTUP_TOOLCHAIN=${RUST_VERSION}
# Install repo tools
@@ -48,7 +48,7 @@ EOF
# Developer tool versions
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
ENV BINSTALL_VERSION=1.17.8
ENV BINSTALL_VERSION=1.17.5
# renovate: datasource=github-releases depName=psastras/sbom-rs
ENV CARGO_SBOM_VERSION=0.9.1
# renovate: datasource=crate depName=lddtree
@@ -180,11 +180,6 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
export RUSTFLAGS="${RUSTFLAGS}"
fi
RUST_PROFILE_DIR="${RUST_PROFILE}"
if [[ "${RUST_PROFILE}" == "dev" ]]; then
RUST_PROFILE_DIR="debug"
fi
TARGET_DIR=($(cargo metadata --no-deps --format-version 1 | \
jq -r ".target_directory"))
mkdir /out/sbin
@@ -196,8 +191,8 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
jq -r ".packages[] | select(.name == \"$PACKAGE\") | .targets[] | select( .kind | map(. == \"bin\") | any ) | .name"))
for BINARY in "${BINARIES[@]}"; do
echo $BINARY
xx-verify $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE_DIR}/$BINARY
cp $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE_DIR}/$BINARY /out/sbin/$BINARY
xx-verify $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE}/$BINARY
cp $TARGET_DIR/$(xx-cargo --print-target-triple)/${RUST_PROFILE}/$BINARY /out/sbin/$BINARY
done
EOF

View File

@@ -18,7 +18,7 @@ RUN --mount=type=cache,target=/etc/apk/cache apk add \
# Developer tool versions
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
ENV BINSTALL_VERSION=1.17.8
ENV BINSTALL_VERSION=1.17.5
# renovate: datasource=github-releases depName=psastras/sbom-rs
ENV CARGO_SBOM_VERSION=0.9.1
# renovate: datasource=crate depName=lddtree

View File

@@ -34,11 +34,6 @@
"name": "troubleshooting",
"label": "Troubleshooting"
},
{
"type": "dir",
"name": "advanced",
"label": "Advanced"
},
"security",
{
"type": "dir-section-header",
@@ -69,11 +64,6 @@
"label": "Configuration Reference",
"name": "/reference/config"
},
{
"type": "file",
"label": "Environment Variables",
"name": "/reference/environment-variables"
},
{
"type": "dir",
"label": "Admin Command Reference",

View File

@@ -2,7 +2,7 @@
{
"text": "Guide",
"link": "/introduction",
"activeMatch": "^/(introduction|configuration|deploying|calls|appservices|maintenance|troubleshooting|advanced)"
"activeMatch": "^/(introduction|configuration|deploying|calls|appservices|maintenance|troubleshooting)"
},
{
"text": "Development",

View File

@@ -1,7 +0,0 @@
[
{
"type": "file",
"name": "delegation",
"label": "Delegation / split-domain"
}
]

View File

@@ -1,206 +0,0 @@
# Delegation/split-domain deployment
Matrix allows clients and servers to discover a homeserver's "true" destination via **`.well-known` delegation**. This is especially useful if you would like to:
- Serve Continuwuity on a subdomain while having only the base domain for your usernames
- Use a port other than `:8448` for server-to-server connections
This guide will show you how to have `@user:example.com` usernames while serving Continuwuity on `https://matrix.example.com`. It assumes you are using port 443 for both client-to-server connections and server-to-server federation.
## Configuration
First, ensure you have set up A/AAAA records for `matrix.example.com` and `example.com` pointing to your IP.
Then, ensure that the `server_name` field matches your intended username suffix. If this is not the case, you **MUST** wipe the database directory and reinstall Continuwuity with your desired `server_name`.
Then, in the `[global.well_known]` section of your config file, add the following fields:
```toml
[global.well_known]
client = "https://matrix.example.com"
# port number MUST be specified
server = "matrix.example.com:443"
# (optional) customize your support contacts
#support_page =
#support_role = "m.role.admin"
#support_email =
#support_mxid = "@user:example.com"
```
Alternatively if you are using Docker, you can set the `CONTINUWUITY_WELL_KNOWN` environment variable as below:
```yaml
services:
continuwuity:
...
environment:
CONTINUWUITY_WELL_KNOWN: |
{
client=https://matrix.example.com,
server=matrix.example.com:443
}
```
## Serving with a reverse proxy
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 to have)
To enable full discovery, you will need to reverse proxy these paths from the base domain back to Continuwuity.
<details>
<summary>For Caddy</summary>
```
matrix.example.com:443 {
reverse_proxy 127.0.0.1:8008
}
example.com:443 {
reverse_proxy /.well-known/matrix* 127.0.0.1:8008
}
```
</details>
<details>
<summary>For Traefik (via Docker labels)</summary>
```
services:
continuwuity:
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.continuwuity.rule=(Host(`matrix.example.com`) || (Host(`example.com`) && PathPrefix(`/.well-known/matrix`)))"
- "traefik.http.routers.continuwuity.service=continuwuity"
- "traefik.http.services.continuwuity.loadbalancer.server.port=8008"
```
</details>
Restart Continuwuity and your reverse proxy. Once that's done, visit these routes and check that the responses match the examples below:
<details open>
<summary>`https://example.com/.well-known/matrix/server`</summary>
```json
{
"m.server": "matrix.example.com:443"
}
```
</details>
<details open>
<summary>`https://example.com/.well-known/matrix/client`</summary>
```json
{
"m.homeserver": {
"base_url": "https://matrix.example.com/"
}
}
```
</details>
## Troubleshooting
### Cannot log in with web clients
Make sure there is an `Access-Control-Allow-Origin: *` header in your `/.well-known/matrix/client` path. While Continuwuity serves this header by default, it may be dropped by reverse proxies or other middlewares.
---
## Using SRV records (not recommended)
:::warning
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>
If you can't set up `/.well-known/matrix/server` on :443 for some reason, you can set up a SRV record (via your DNS provider) as below:
- Service and name: `_matrix-fed._tcp.example.com.`
- Priority: `10` (can be any number)
- Weight: `10` (can be any number)
- Port: `443`
- Target: `matrix.example.com.`
On the target's IP at port 443, you must configure a valid route and cert for your server name, `example.com`. Therefore, this method only works to redirect traffic into the right IP/port combo, and can not delegate your federation to a different domain.
</details>
<details>
<summary>Using SRV records + .well-known</summary>
You can also set up `/.well-known/matrix/server` with a delegated domain but no ports:
```toml
[global.well_known]
server = "matrix.example.com"
```
Then, set up a SRV record (via your DNS provider) to announce the port number as below:
- Service and name: `_matrix-fed._tcp.matrix.example.com.`
- Priority: `10` (can be any number)
- Weight: `10` (can be any number)
- Port: `443`
- Target: `matrix.example.com.`
On the target's IP at port 443, you'll need to provide a valid route and cert for `matrix.example.com`. It provides the same feature as pure `.well-known` delegation, albeit with more parts to handle.
</details>
<details>
<summary>Using SRV records as a fallback for .well-known delegation</summary>
Assume your delegation is as below:
```toml
[global.well_known]
server = "example.com:443"
```
If your Continuwuity instance becomes temporarily unreachable, other servers will not be able to find your `/.well-known/matrix/server` file, and defaults to using `server_name:8448`. This incorrect cache can persist for a long time, and would hinder re-federation when your server eventually comes back online.
If you want other servers to default to using port :443 even when it is offline, you could set up a SRV record (via your DNS provider) as follows:
- Service and name: `_matrix-fed._tcp.example.com.`
- Priority: `10` (can be any number)
- Weight: `10` (can be any number)
- Port: `443`
- Target: `example.com.`
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)

View File

@@ -10,4 +10,4 @@ # Calls
For either one to work correctly, you have to do some additional setup.
- For legacy calls to work, you need to set up a TURN/STUN server. [Read the TURN guide for tips on how to set up coturn](./calls/turn.mdx)
- For MatrixRTC / Element Call to work, you have to set up the LiveKit backend (foci). LiveKit also uses TURN/STUN to increase reliability - you can set up its built-in TURN server, or integrate with an existing one. [Read the LiveKit guide](./calls/livekit.mdx)
- For MatrixRTC / Element Call to work, you have to set up the LiveKit backend (foci). LiveKit also uses TURN/STUN to increase reliability, so you might want to configure your TURN server first. [Read the LiveKit guide](./calls/livekit.mdx)

View File

@@ -4,10 +4,6 @@ # Matrix RTC/Element Call Setup
This guide assumes that you are using docker compose for deployment. LiveKit only provides Docker images.
:::
:::tip
You can find help setting up Matrix RTC in our dedicated room - [#matrixrtc:continuwuity.org](https://matrix.to/#/%23matrixrtc%3Acontinuwuity.org)
:::
## Instructions
### 1. Domain
@@ -18,21 +14,17 @@ ### 1. Domain
### 2. Services
Using LiveKit with Matrix requires two services - LiveKit itself, and a service (`lk-jwt-service`) that grants Matrix users permission to connect to it.
Using LiveKit with Matrix requires two services - Livekit itself, and a 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!
:::tip Generating the secrets
LiveKit provides a utility to generate secure random keys
```bash
~$ docker run --rm livekit/livekit-server:latest generate-keys
API Key: APIUxUnMnSkuFWV
API Secret: t93ZVjPeoEdyx7Wbet3kG4L3NGZIZVEFvqe0UuiVc22A
docker run --rm livekit/livekit-server:latest generate-keys
```
:::
Create a `docker-compose.yml` file as following:
```yaml
services:
lk-jwt-service:
@@ -40,11 +32,10 @@ ### 2. Services
container_name: lk-jwt-service
environment:
- LIVEKIT_JWT_BIND=:8081
- LIVEKIT_URL=wss://livekit.example.com # your LiveKit domain
- LIVEKIT_FULL_ACCESS_HOMESERVERS=example.com # your server_name
# Replace these with the generated values as above
- LIVEKIT_KEY=LK_MATRIX_KEY # APIUxUnMnSkuFWV
- LIVEKIT_SECRET=LK_MATRIX_SECRET # t93ZVjPeoEdyx7Wbet3kG4L3NGZIZVEFvqe0UuiVc22A
- LIVEKIT_URL=wss://livekit.example.com
- LIVEKIT_KEY=LK_MATRIX_KEY
- LIVEKIT_SECRET=LK_MATRIX_SECRET
- LIVEKIT_FULL_ACCESS_HOMESERVERS=example.com
restart: unless-stopped
ports:
- "8081:8081"
@@ -79,8 +70,6 @@ # - "50100-50200:50100-50200/udp"
enable_loopback_candidate: false
keys:
LK_MATRIX_KEY: LK_MATRIX_SECRET
# replace these with your key-secret pair. Example:
# APIUxUnMnSkuFWV: t93ZVjPeoEdyx7Wbet3kG4L3NGZIZVEFvqe0UuiVc22A
```
#### Firewall hints
@@ -106,7 +95,7 @@ ### 4. Configure your Reverse Proxy
Reverse proxies can be configured in many different ways - so we can't provide a step by step for this.
All paths should be forwarded to LiveKit by default, with the exception of the following path prefixes, which should be forwarded to the JWT/Authentication service:
By default, all routes should be forwarded to Livekit with the exception of the following path prefixes, which should be forwarded to the JWT/Authentication service:
- `/sfu/get`
- `/healthz`
@@ -115,7 +104,7 @@ ### 4. Configure your Reverse Proxy
<details>
<summary>Example caddy config</summary>
```
livekit.example.com {
matrix-rtc.example.com {
# for lk-jwt-service
@lk-jwt-service path /sfu/get* /healthz* /get_token*
@@ -133,7 +122,7 @@ ### 4. Configure your Reverse Proxy
<summary>Example nginx config</summary>
```
server {
server_name livekit.example.com;
server_name matrix-rtc.example.com;
# for lk-jwt-service
location ~ ^/(sfu/get|healthz|get_token) {
@@ -144,7 +133,7 @@ ### 4. Configure your Reverse Proxy
proxy_buffering off;
}
# for LiveKit
# for livekit
location / {
proxy_pass http://127.0.0.1:7880$request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
@@ -184,11 +173,44 @@ ### 6. Start Everything
Start up the services using your usual method - for example `docker compose up -d`.
## Additional TURN configuration
## Additional Configuration
### Using LiveKit's built-in TURN server
### TURN Integration
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've already set up coturn, there may be a port clash between the two services. To fix this, make sure the `min-port` and `max-port` for coturn so it doesn't overlap with LiveKit's range:
```ini
min-port=50201
max-port=65535
```
To improve LiveKit's reliability, you can configure it to use your coturn server.
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 each thing using your TURN server.
Then configure livekit, making sure to replace `COTURN_SECRET`:
```yaml
# livekit.yaml
rtc:
turn_servers:
- host: coturn.ellis.link
port: 3478
protocol: tcp
secret: "COTURN_SECRET"
- host: coturn.ellis.link
port: 5349
protocol: tls # Only if you've set up TLS in your coturn
secret: "COTURN_SECRET"
- host: coturn.ellis.link
port: 3478
protocol: udp
secret: "COTURN_SECRET"
```
## 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:
@@ -199,175 +221,20 @@ ### add this to livekit.yaml ###
udp_port: 3478
relay_range_start: 50300
relay_range_end: 50400
domain: livekit.example.com
domain: matrix-rtc.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
### Add these to docker-compose ###
- "3478:3478/udp"
- "50300-50400:50300-50400/udp"
```
Recreate the LiveKit container (with `docker-compose up -d livekit`) to apply these changes. Remember to allow the new `3478/udp` and `50100:50200/udp` ports through your firewall.
### Related Documentation
### 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).
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).
Then, using that token, request another OpenID token for use with the lk-jwt-service:
```bash
~$ curl -X POST -H "Authorization: Bearer <session-access-token>" \
https://matrix.example.com/_matrix/client/v3/user/@user:example.com/openid/request_token
{"access_token":"<openid_access_token>","token_type":"Bearer","matrix_server_name":"example.com","expires_in":3600}
```
Next, create a `payload.json` file with the following content:
<details>
<summary>`payload.json`</summary>
```json
{
"room_id": "abc",
"slot_id": "xyz",
"openid_token": {
"matrix_server_name": "example.com",
"access_token": "<openid_access_token>",
"token_type": "Bearer"
},
"member": {
"id": "xyz",
"claimed_device_id": "DEVICEID",
"claimed_user_id": "@user:example.com"
}
}
```
Replace `matrix_server_name` and `claimed_user_id` with your information, and `<openid_access_token>` with the one you got from the previous step. Other values can be left as-is.
</details>
You can then send this payload to the lk-jwt-service:
```bash
~$ curl -X POST -d @payload.json https://livekit.example.com/get_token
{"url":"wss://livekit.example.com","jwt":"a_really_really_long_string"}
```
The lk-jwt-service will, after checking against Continuwuity, answer with a `jwt` token to create a LiveKit media room. 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 them in real-time.
### Common errors in Element Call UI
- `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
### Docker loopback networking issues
Some distros do not allow Docker containers to connect to its host's public IP by default. This would cause `lk-jwt-service` to fail connecting to `livekit` or `continuwuity` on the same host. As a result, you would see connection refused/connection timeouts log entries in the JWT service, even when `LIVEKIT_URL` has been configured correctly.
To alleviate this, you can try one of the following workarounds:
- Use `network_mode: host` for the `lk-jwt-service` container (instead of the default bridge networking).
- Add an `extra_hosts` file mapping livekit's (and continuwuity's) domain name to a localhost address:
```diff
# in docker-compose.yaml
services:
lk-jwt-service:
...
+ extra_hosts:
+ - "livekit.example.com:127.0.0.1"
+ - "matrix.example.com:127.0.0.1"
```
- (**untested, use at your own risk**) Implement an iptables workaround as shown [here](https://forums.docker.com/t/unable-to-connect-to-host-service-from-inside-docker-container/145749/6).
After implementing the changes and restarting your compose, you can test whether the connection works by cURLing from a sidecar container:
```bash
~$ docker run --rm --net container:lk-jwt-service docker.io/curlimages/curl https://livekit.example.com
OK
```
### 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.
As a workaround, you can enable federation, but forbid all remote servers via the following config parameters:
```toml
### in your continuwuity.toml file ###
allow_federation = true
forbidden_remote_server_names = [".*"]
```
Subscribe to issue [!1440](https://forgejo.ellis.link/continuwuation/continuwuity/issues/1440) for future updates on this matter.
## Related Documentation
Guides:
- [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:
- [MatrixRTC proposal](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)
- [LiveKit proposal](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
Source code:
- [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)
- [LiveKit GitHub](https://github.com/livekit/livekit)
- [LiveKit Connection Tester](https://livekit.io/connection-test) - use with the token returned by `/sfu/get` or `/get_token`
- [MatrixRTC proposal](https://half-shot.github.io/msc-crafter/#msc/4143)
- [Synapse documentation](https://github.com/element-hq/element-call/blob/livekit/docs/self-hosting.md)
- [Community guide](https://tomfos.tr/matrix/livekit/)
- [Community guide](https://blog.kimiblock.top/2024/12/24/hosting-element-call/)

View File

@@ -13,9 +13,8 @@ ## Basics
The config file to use can be specified on the commandline when running
Continuwuity by specifying the `-c`, `--config` flag. Alternatively, you can use
the environment variable `CONTINUWUITY_CONFIG` to specify the config file to be
used; see [the section on environment variables](#environment-variables) for
more information.
the environment variable `CONDUWUIT_CONFIG` to specify the config file to used.
Conduit's environment variables are supported for backwards compatibility.
## Option commandline flag
@@ -53,15 +52,13 @@ ## Environment variables
All of the settings that are found in the config file can be specified by using
environment variables. The environment variable names should be all caps and
prefixed with `CONTINUWUITY_`.
prefixed with `CONDUWUIT_`.
For example, if the setting you are changing is `max_request_size`, then the
environment variable to set is `CONTINUWUITY_MAX_REQUEST_SIZE`.
environment variable to set is `CONDUWUIT_MAX_REQUEST_SIZE`.
To modify config options not in the `[global]` context such as
`[global.well_known]`, use the `__` suffix split:
`CONTINUWUITY_WELL_KNOWN__SERVER`
`[global.well_known]`, use the `__` suffix split: `CONDUWUIT_WELL_KNOWN__SERVER`
Conduit and conduwuit's environment variables are also supported for backwards
compatibility, via the `CONDUIT_` and `CONDUWUIT_` prefixes respectively (e.g.
Conduit's environment variables are supported for backwards compatibility (e.g.
`CONDUIT_SERVER_NAME`).

1
docs/contributing.mdx Symbolic link
View File

@@ -0,0 +1 @@
../CONTRIBUTING.md

View File

@@ -6,9 +6,9 @@ services:
### then you are ready to go.
image: forgejo.ellis.link/continuwuation/continuwuity:latest
restart: unless-stopped
command: /sbin/conduwuit
volumes:
- db:/var/lib/continuwuity
- /etc/resolv.conf:/etc/resolv.conf:ro # Use the host's DNS resolver rather than Docker's.
#- ./continuwuity.toml:/etc/continuwuity.toml
networks:
- proxy

View File

@@ -16,14 +16,14 @@ services:
restart: unless-stopped
labels:
caddy: example.com
caddy.reverse_proxy: /.well-known/matrix/* homeserver:6167
caddy.0_respond: /.well-known/matrix/server {"m.server":"matrix.example.com:443"}
caddy.1_respond: /.well-known/matrix/client {"m.server":{"base_url":"https://matrix.example.com"},"m.homeserver":{"base_url":"https://matrix.example.com"},"org.matrix.msc3575.proxy":{"url":"https://matrix.example.com"}}
homeserver:
### If you already built the Continuwuity image with 'docker build' or want to use a registry image,
### then you are ready to go.
image: forgejo.ellis.link/continuwuation/continuwuity:latest
restart: unless-stopped
command: /sbin/conduwuit
volumes:
- db:/var/lib/continuwuity
- /etc/resolv.conf:/etc/resolv.conf:ro # Use the host's DNS resolver rather than Docker's.
@@ -42,10 +42,6 @@ services:
#CONTINUWUITY_LOG: warn,state_res=warn
CONTINUWUITY_ADDRESS: 0.0.0.0
#CONTINUWUITY_CONFIG: '/etc/continuwuity.toml' # Uncomment if you mapped config toml above
# Required for .well-known delegation - edit these according to your chosen domain
CONTINUWUITY_WELL_KNOWN__CLIENT: https://matrix.example.com
CONTINUWUITY_WELL_KNOWN__SERVER: matrix.example.com:443
networks:
- caddy
labels:

View File

@@ -6,7 +6,6 @@ services:
### then you are ready to go.
image: forgejo.ellis.link/continuwuation/continuwuity:latest
restart: unless-stopped
command: /sbin/conduwuit
volumes:
- db:/var/lib/continuwuity
- /etc/resolv.conf:/etc/resolv.conf:ro # Use the host's DNS resolver rather than Docker's.

View File

@@ -6,7 +6,6 @@ services:
### then you are ready to go.
image: forgejo.ellis.link/continuwuation/continuwuity:latest
restart: unless-stopped
command: /sbin/conduwuit
ports:
- 8448:6167
volumes:

View File

@@ -2,26 +2,28 @@ # Continuwuity for Docker
## Docker
To run Continuwuity with Docker, you can either build the image yourself or pull
it from a registry.
To run Continuwuity with Docker, you can either build the image yourself or pull it
from a registry.
### Use a registry
Available OCI images:
OCI images for Continuwuity are available in the registries listed below.
| Registry | Image | Notes |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Forgejo Registry | [forgejo.ellis.link/continuwuation/continuwuity:latest](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/latest) | Latest tagged image. |
| Forgejo Registry | [forgejo.ellis.link/continuwuation/continuwuity:main](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main) | Main branch image. |
| Forgejo Registry | [forgejo.ellis.link/continuwuation/continuwuity:latest-maxperf](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/latest-maxperf) | [Performance optimised version.](./generic.mdx#performance-optimised-builds) |
| Forgejo Registry | [forgejo.ellis.link/continuwuation/continuwuity:main-maxperf](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main-maxperf) | [Performance optimised version.](./generic.mdx#performance-optimised-builds) |
| Registry | Image | Notes |
| --------------- | --------------------------------------------------------------- | -----------------------|
| Forgejo Registry| [forgejo.ellis.link/continuwuation/continuwuity:latest](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/latest) | Latest tagged image. |
| Forgejo Registry| [forgejo.ellis.link/continuwuation/continuwuity:main](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main) | Main branch image. |
| Forgejo Registry| [forgejo.ellis.link/continuwuation/continuwuity:latest-maxperf](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/latest-maxperf) | [Performance optimised version.](./generic.mdx#performance-optimised-builds) |
| Forgejo Registry| [forgejo.ellis.link/continuwuation/continuwuity:main-maxperf](https://forgejo.ellis.link/continuwuation/-/packages/container/continuwuity/main-maxperf) | [Performance optimised version.](./generic.mdx#performance-optimised-builds) |
**Example:**
Use
```bash
docker image pull forgejo.ellis.link/continuwuation/continuwuity:main-maxperf
docker image pull $LINK
```
to pull it to your machine.
#### Mirrors
Images are mirrored to multiple locations automatically, on a schedule:
@@ -31,146 +33,39 @@ #### Mirrors
- `registry.gitlab.com/continuwuity/continuwuity`
- `git.nexy7574.co.uk/mirrored/continuwuity` (releases only, no `main`)
### Quick Run
### Run
Get a working Continuwuity server with an admin user in four steps:
#### Prerequisites
Continuwuity requires HTTPS for Matrix federation. You'll need:
- A domain name pointing to your server
- A reverse proxy with SSL/TLS certificates (Traefik, Caddy, nginx, etc.)
See [Docker Compose](#docker-compose) for complete examples.
#### Environment Variables
- `CONTINUWUITY_SERVER_NAME` - Your Matrix server's domain name
- `CONTINUWUITY_DATABASE_PATH` - Where to store your database (must match the
volume mount)
- `CONTINUWUITY_ADDRESS` - Bind address (use `0.0.0.0` to listen on all
interfaces)
- `CONTINUWUITY_ALLOW_REGISTRATION` - Set to `false` to disable registration, or
use with `CONTINUWUITY_REGISTRATION_TOKEN` to require a token (see
[reference](../reference/environment-variables.mdx#registration--user-configuration)
for details)
See the
[Environment Variables Reference](../reference/environment-variables.mdx) for
more configuration options.
#### 1. Pull the image
When you have the image, you can simply run it with
```bash
docker pull forgejo.ellis.link/continuwuation/continuwuity:latest
docker run -d -p 8448:6167 \
-v db:/var/lib/continuwuity/ \
-e CONTINUWUITY_SERVER_NAME="your.server.name" \
-e CONTINUWUITY_ALLOW_REGISTRATION=false \
--name continuwuity $LINK
```
#### 2. Start the server with initial admin user
or you can use [Docker Compose](#docker-compose).
```bash
docker run -d \
-p 6167:6167 \
-v continuwuity_db:/var/lib/continuwuity \
-e CONTINUWUITY_SERVER_NAME="matrix.example.com" \
-e CONTINUWUITY_DATABASE_PATH="/var/lib/continuwuity" \
-e CONTINUWUITY_ADDRESS="0.0.0.0" \
-e CONTINUWUITY_ALLOW_REGISTRATION="false" \
--name continuwuity \
forgejo.ellis.link/continuwuation/continuwuity:latest \
/sbin/conduwuit --execute "users create-user admin"
```
The `-d` flag lets the container run in detached mode. You may supply an
optional `continuwuity.toml` config file, the example config can be found
[here](../reference/config.mdx). You can pass in different env vars to
change config values on the fly. You can even configure Continuwuity completely by
using env vars. For an overview of possible values, please take a look at the
<a href="/examples/docker-compose.yml" target="_blank">`docker-compose.yml`</a> file.
Replace `matrix.example.com` with your actual server name and `admin` with
your preferred username.
#### 3. Get your admin password
```bash
docker logs continuwuity 2>&1 | grep "Created user"
```
You'll see output like:
```
Created user with user_id: @admin:matrix.example.com and password: `[auto-generated-password]`
```
#### 4. Configure your reverse proxy
Configure your reverse proxy to forward HTTPS traffic to Continuwuity. See
[Docker Compose](#docker-compose) for examples.
Once configured, log in with any Matrix client using `@admin:matrix.example.com`
and the generated password. You'll automatically be invited to the admin room
where you can manage your server.
If you just want to test Continuwuity for a short time, you can use the `--rm`
flag, which cleans up everything related to your container after you stop
it.
### Docker Compose
Docker Compose is the recommended deployment method. These examples include
reverse proxy configurations for Matrix federation.
If the `docker run` command is not suitable for you or your setup, you can also use one
of the provided `docker-compose` files.
#### Matrix Federation Requirements
Depending on your proxy setup, you can use one of the following files:
For Matrix federation to work, you need to serve `.well-known/matrix/client` and
`.well-known/matrix/server` endpoints. You can achieve this either by:
1. **Using a well-known service** - The compose files below include an nginx
container to serve these files
2. **Using Continuwuity's built-in delegation** (easier for Traefik) - Configure
delegation files in your config, then proxy `/.well-known/matrix/*` to
Continuwuity
**Traefik example using built-in delegation:**
```yaml
labels:
traefik.http.routers.continuwuity.rule: >-
(Host(`matrix.example.com`) ||
(Host(`example.com`) && PathPrefix(`/.well-known/matrix`)))
```
This routes your Matrix domain and well-known paths to Continuwuity.
#### Creating Your First Admin User
Add the `--execute` command to create an admin user on first startup. In your
compose file, add under the `continuwuity` service:
```yaml
services:
continuwuity:
image: forgejo.ellis.link/continuwuation/continuwuity:latest
command: /sbin/conduwuit --execute "users create-user admin"
# ... rest of configuration
```
Then retrieve the auto-generated password:
```bash
docker compose logs continuwuity | grep "Created user"
```
#### Choose Your Reverse Proxy
Select the compose file that matches your setup:
:::note DNS Performance
Docker's default DNS resolver can cause performance issues with Matrix
federation. If you experience slow federation or DNS timeouts, you may need to
use your host's DNS resolver instead. Add this volume mount to the
`continuwuity` service:
```yaml
volumes:
- /etc/resolv.conf:/etc/resolv.conf:ro
```
See [Troubleshooting - DNS Issues](../troubleshooting.mdx#potential-dns-issues-when-using-docker)
for more details and alternative solutions.
:::
##### For existing Traefik setup
### For existing Traefik setup
<details>
<summary>docker-compose.for-traefik.yml</summary>
@@ -181,7 +76,7 @@ ##### For existing Traefik setup
</details>
##### With Traefik included
### With Traefik included
<details>
<summary>docker-compose.with-traefik.yml</summary>
@@ -192,7 +87,7 @@ ##### With Traefik included
</details>
##### With Caddy Docker Proxy
### With Caddy Docker Proxy
<details>
<summary>docker-compose.with-caddy.yml</summary>
@@ -203,15 +98,9 @@ ##### With Caddy Docker Proxy
```
If you don't already have a network for Caddy to monitor, create one first:
```bash
docker network create caddy
```
</details>
##### For other reverse proxies
### For other reverse proxies
<details>
<summary>docker-compose.yml</summary>
@@ -222,7 +111,7 @@ ##### For other reverse proxies
</details>
##### Override file for customisation
### Override file
<details>
<summary>docker-compose.override.yml</summary>
@@ -233,24 +122,98 @@ ##### Override file for customisation
</details>
#### Starting Your Server
When picking the Traefik-related compose file, rename it to
`docker-compose.yml`, and rename the override file to
`docker-compose.override.yml`. Edit the latter with the values you want for your
server.
1. Choose your compose file and rename it to `docker-compose.yml`
2. If using the override file, rename it to `docker-compose.override.yml` and
edit your values
3. Start the server:
When picking the `caddy-docker-proxy` compose file, it's important to first
create the `caddy` network before spinning up the containers:
```bash
docker network create caddy
```
After that, you can rename it to `docker-compose.yml` and spin up the
containers!
Additional info about deploying Continuwuity can be found [here](generic.mdx).
### Build
Official Continuwuity images are built using **Docker Buildx** and the Dockerfile found at [`docker/Dockerfile`][dockerfile-path]. This approach uses common Docker tooling and enables efficient multi-platform builds.
The resulting images are widely compatible with Docker and other container runtimes like Podman or containerd.
The images *do not contain a shell*. They contain only the Continuwuity binary, required libraries, TLS certificates, and metadata.
<details>
<summary>Click to view the Dockerfile</summary>
You can also <a href="https://forgejo.ellis.link/continuwuation/continuwuation/src/branch/main/docker/Dockerfile" target="_blank">view the Dockerfile on Forgejo</a>.
```dockerfile file="../../docker/Dockerfile"
```
</details>
To build an image locally using Docker Buildx, you can typically run a command like:
```bash
# Build for the current platform and load into the local Docker daemon
docker buildx build --load --tag continuwuity:latest -f docker/Dockerfile .
# Example: Build for specific platforms and push to a registry.
# docker buildx build --platform linux/amd64,linux/arm64 --tag registry.io/org/continuwuity:latest -f docker/Dockerfile . --push
# Example: Build binary optimised for the current CPU (standard release profile)
# docker buildx build --load \
# --tag continuwuity:latest \
# --build-arg TARGET_CPU=native \
# -f docker/Dockerfile .
# Example: Build maxperf variant (release-max-perf profile with LTO)
# Optimised for runtime performance and smaller binary size, but requires longer build time
# docker buildx build --load \
# --tag continuwuity:latest-maxperf \
# --build-arg TARGET_CPU=native \
# --build-arg RUST_PROFILE=release-max-perf \
# -f docker/Dockerfile .
```
Refer to the Docker Buildx documentation for more advanced build options.
[dockerfile-path]: https://forgejo.ellis.link/continuwuation/continuwuation/src/branch/main/docker/Dockerfile
### Run
If you have already built the image or want to use one from the registries, you
can start the container and everything else in the compose file in detached
mode with:
```bash
docker compose up -d
```
See the [generic deployment guide](generic.mdx) for more deployment options.
> **Note:** Don't forget to modify and adjust the compose file to your needs.
### Building Custom Images
### Use Traefik as Proxy
For information on building your own Continuwuity Docker images, see the
[Building Docker Images](../development/index.mdx#building-docker-images)
section in the development documentation.
As a container user, you probably know about Traefik. It is an easy-to-use
reverse proxy for making containerized apps and services available through the
web. With the Traefik-related docker-compose files provided above, it is equally easy
to deploy and use Continuwuity, with a small caveat. If you have already looked at
the files, you should have seen the `well-known` service, which is the
small caveat. Traefik is simply a proxy and load balancer and cannot
serve any kind of content. For Continuwuity to federate, we need to either
expose ports `443` and `8448` or serve two endpoints: `.well-known/matrix/client`
and `.well-known/matrix/server`.
With the service `well-known`, we use a single `nginx` container that serves
those two files.
Alternatively, you can use Continuwuity's built-in delegation file capability. Set up the delegation files in the configuration file, and then proxy paths under `/.well-known/matrix` to continuwuity. For example, the label ``traefik.http.routers.continuwuity.rule=(Host(`matrix.ellis.link`) || (Host(`ellis.link`) && PathPrefix(`/.well-known/matrix`)))`` does this for the domain `ellis.link`.
## Voice communication

View File

@@ -1,7 +1,7 @@
# Continuwuity for FreeBSD
Continuwuity doesn't provide official FreeBSD packages; however, a community-maintained set of packages is available on [Forgejo](https://forgejo.ellis.link/katie/continuwuity-bsd). Note that these are provided as standalone packages and are not part of a FreeBSD package repository (yet), so updates need to be downloaded and installed manually.
Continuwuity currently does not provide FreeBSD builds or FreeBSD packaging. However, Continuwuity does build and work on FreeBSD using the system-provided RocksDB.
Please see the installation instructions in that repository. Direct any questions to its issue tracker or to [@katie:kat5.dev](https://matrix.to/#/@katie:kat5.dev).
Contributions to get Continuwuity packaged for FreeBSD are welcome.
For general BSD support, please join our [Continuwuity BSD](https://matrix.to/#/%23bsd:continuwuity.org) community room.
Please join our [Continuwuity BSD](https://matrix.to/#/%23bsd:continuwuity.org) community room.

View File

@@ -39,7 +39,6 @@ # Continuwuity for Kubernetes
- name: continuwuity
# use a sha hash <3
image: forgejo.ellis.link/continuwuation/continuwuity:latest
command: ["/sbin/conduwuit"]
imagePullPolicy: IfNotPresent
ports:
- name: http

View File

@@ -1 +0,0 @@
../../CONTRIBUTING.md

View File

@@ -0,0 +1,203 @@
# Contributing guide
This page is about contributing to Continuwuity. The
[development](./index.mdx) and [code style guide](./code_style.mdx) pages may be of interest for you as well.
If you would like to work on an [issue][issues] that is not assigned, preferably
ask in the Matrix room first at [#continuwuity:continuwuity.org][continuwuity-matrix],
and comment on it.
### Code Style
Please review and follow the [code style guide](./code_style) for formatting, linting, naming conventions, and other code standards.
### Pre-commit Checks
Continuwuity uses pre-commit hooks to enforce various coding standards and catch common issues before they're committed. These checks include:
- Code formatting and linting
- Typo detection (both in code and commit messages)
- Checking for large files
- Ensuring proper line endings and no trailing whitespace
- Validating YAML, JSON, and TOML files
- Checking for merge conflicts
You can run these checks locally by installing [prefligit](https://github.com/j178/prefligit):
```bash
# Requires UV: https://docs.astral.sh/uv/getting-started/installation/
# Mac/linux: curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows: powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# Install prefligit using cargo-binstall
cargo binstall prefligit
# Install git hooks to run checks automatically
prefligit install
# Run all checks
prefligit --all-files
```
Alternatively, you can use [pre-commit](https://pre-commit.com/):
```bash
# Requires python
# Install pre-commit
pip install pre-commit
# Install the hooks
pre-commit install
# Run all checks manually
pre-commit run --all-files
```
These same checks are run in CI via the prefligit-checks workflow to ensure consistency. These must pass before the PR is merged.
### Running tests locally
Tests, compilation, and linting can be run with standard Cargo commands:
```bash
# Run tests
cargo test
# Check compilation
cargo check --workspace --features full
# Run lints
cargo clippy --workspace --features full
# Auto-fix: cargo clippy --workspace --features full --fix --allow-staged;
# Format code (must use nightly)
cargo +nightly fmt
```
### Matrix tests
Continuwuity uses [Complement][complement] for Matrix protocol compliance testing. Complement tests are run manually by developers, and documentation on how to run these tests locally is currently being developed.
If your changes are done to fix Matrix tests, please note that in your pull request. If more Complement tests start failing from your changes, please review the logs and determine if they're intended or not.
[Sytest][sytest] is currently unsupported.
### Writing documentation
Continuwuity's website uses [`mdbook`][mdbook] and is deployed via CI using Cloudflare Pages
in the [`documentation.yml`][documentation.yml] workflow file. All documentation is in the `docs/`
directory at the top level.
To build the documentation locally:
1. Install mdbook if you don't have it already:
```bash
cargo install mdbook # or cargo binstall, or another method
```
2. Build the documentation:
```bash
mdbook build
```
The output of the mdbook generation is in `public/`. You can open the HTML files directly in your browser without needing a web server.
### Commit Messages
Continuwuity follows the [Conventional Commits](https://www.conventionalcommits.org/) specification for commit messages. This provides a standardized format that makes the commit history more readable and enables automated tools to generate changelogs.
The basic structure is:
```
<type>[(optional scope)]: <description>
[optional body]
[optional footer(s)]
```
The allowed types for commits are:
- `fix`: Bug fixes
- `feat`: New features
- `docs`: Documentation changes
- `style`: Changes that don't affect the meaning of the code (formatting, etc.)
- `refactor`: Code changes that neither fix bugs nor add features
- `perf`: Performance improvements
- `test`: Adding or fixing tests
- `build`: Changes to the build system or dependencies
- `ci`: Changes to CI configuration
- `chore`: Other changes that don't modify source or test files
Examples:
```
feat: add user authentication
fix(database): resolve connection pooling issue
docs: update installation instructions
```
The project uses the `committed` hook to validate commit messages in pre-commit. This ensures all commits follow the conventional format.
### Creating pull requests
Please try to keep contributions to the Forgejo Instance. While the mirrors of continuwuity
allow for pull/merge requests, there is no guarantee the maintainers will see them in a timely
manner. Additionally, please mark WIP or unfinished or incomplete PRs as drafts.
This prevents us from having to ping once in a while to double check the status
of it, especially when the CI completed successfully and everything so it
*looks* done.
Before submitting a pull request, please ensure:
1. Your code passes all CI checks (formatting, linting, typo detection, etc.). Run pre-commit for this.
2. Your code follows the [code style guide](./code_style)
3. Your commit messages follow the conventional commits format
4. Tests are added for new functionality
5. Documentation is updated if needed
6. You have written a [news fragment](#writing-news-fragments) for your changes
Direct all PRs/MRs to the `main` branch.
By sending a pull request or patch, you are agreeing that your changes are
allowed to be licenced under the Apache-2.0 licence and all of your conduct is
in line with the Contributor's Covenant, and continuwuity's Code of Conduct.
Contribution by users who violate either of these code of conducts may not have
their contributions accepted. This includes users who have been banned from
continuwuity Matrix rooms for Code of Conduct violations.
[issues]: https://forgejo.ellis.link/continuwuation/continuwuity/issues
[continuwuity-matrix]: https://matrix.to/#/#continuwuity:continuwuity.org?via=continuwuity.org&via=ellis.link&via=explodie.org&via=matrix.org
[complement]: https://github.com/matrix-org/complement/
[sytest]: https://github.com/matrix-org/sytest/
[mdbook]: https://rust-lang.github.io/mdBook/
[documentation.yml]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/.forgejo/workflows/documentation.yml
#### Writing news fragments
In order to make writing our changelogs easier, we make use of [Towncrier]. Towncrier builds changelogs based on
"news fragments", which are little markdown files in the `changelog.d/` directory that describe individual changes.
When you make a pull request that changes functionality, fixes a bug, or adds documentation, please add a news fragment
describing your change. The file name *MUST* be in the format of `{pull_request_number}.{type}`, where `{type}` is one
of the following:
- `feature` - for new features
- `bugfix` - for bug fixes
- `doc` - for documentation changes
- `misc` - for other changes that don't fit the above categories
For example:
```bash
$ echo "Fixed the quantum flux stabiliser. Contributed by @alice." > changelog.d/42.bugfix
```
(Note: If you want to credit yourself, you should reference your forgejo handle, however links to other platforms are also acceptable.)
When the next release is made, Towncrier will automatically include your news fragment in the changelog.
You can read more about writing news fragments in the [Towncrier tutorial][tt].
[Towncrier]: https://towncrier.readthedocs.io/
[tt]: https://towncrier.readthedocs.io/en/stable/tutorial.html#creating-news-fragments

View File

@@ -2,8 +2,7 @@ # Development
Information about developing the project. If you are only interested in using
it, you can safely ignore this page. If you plan on contributing, see the
[contributor's guide](./contributing.mdx) and
[code style guide](./code_style.mdx).
[contributor's guide](./contributing.mdx) and [code style guide](./code_style.mdx).
## Continuwuity project layout
@@ -13,98 +12,86 @@ ## Continuwuity project layout
`Cargo.toml`.
The crate names are generally self-explanatory:
- `admin` is the admin room
- `api` is the HTTP API, Matrix C-S and S-S endpoints, etc
- `core` is core Continuwuity functionality like config loading, error
definitions, global utilities, logging infrastructure, etc
- `database` is RocksDB methods, helpers, RocksDB config, and general database
definitions, utilities, or functions
- `macros` are Continuwuity Rust [macros][macros] like general helper macros,
logging and error handling macros, and [syn][syn] and [procedural
macros][proc-macro] used for admin room commands and others
- `core` is core Continuwuity functionality like config loading, error definitions,
global utilities, logging infrastructure, etc
- `database` is RocksDB methods, helpers, RocksDB config, and general database definitions,
utilities, or functions
- `macros` are Continuwuity Rust [macros][macros] like general helper macros, logging
and error handling macros, and [syn][syn] and [procedural macros][proc-macro]
used for admin room commands and others
- `main` is the "primary" sub-crate. This is where the `main()` function lives,
tokio worker and async initialisation, Sentry initialisation, [clap][clap]
init, and signal handling. If you are adding new [Rust features][features],
they _must_ go here.
- `router` is the webserver and request handling bits, using axum, tower,
tower-http, hyper, etc, and the [global server state][state] to access
`services`.
tokio worker and async initialisation, Sentry initialisation, [clap][clap] init,
and signal handling. If you are adding new [Rust features][features], they *must*
go here.
- `router` is the webserver and request handling bits, using axum, tower, tower-http,
hyper, etc, and the [global server state][state] to access `services`.
- `service` is the high-level database definitions and functions for data,
outbound/sending code, and other business logic such as media fetching.
outbound/sending code, and other business logic such as media fetching.
It is highly unlikely you will ever need to add a new workspace member, but if
you truly find yourself needing to, we recommend reaching out to us in the
Matrix room for discussions about it beforehand.
It is highly unlikely you will ever need to add a new workspace member, but
if you truly find yourself needing to, we recommend reaching out to us in
the Matrix room for discussions about it beforehand.
The primary inspiration for this design was apart of hot reloadable development,
to support "Continuwuity as a library" where specific parts can simply be
swapped out. There is evidence Conduit wanted to go this route too as `axum` is
technically an optional feature in Conduit, and can be compiled without the
binary or axum library for handling inbound web requests; but it was never
completed or worked.
to support "Continuwuity as a library" where specific parts can simply be swapped out.
There is evidence Conduit wanted to go this route too as `axum` is technically an
optional feature in Conduit, and can be compiled without the binary or axum library
for handling inbound web requests; but it was never completed or worked.
See the Rust documentation on [Workspaces][workspaces] for general questions and
information on Cargo workspaces.
See the Rust documentation on [Workspaces][workspaces] for general questions
and information on Cargo workspaces.
## Adding compile-time [features][features]
If you'd like to add a compile-time feature, you must first define it in the
`main` workspace crate located in `src/main/Cargo.toml`. The feature must enable
a feature in the other workspace crate(s) you intend to use it in. Then the said
workspace crate(s) must define the feature there in its `Cargo.toml`.
If you'd like to add a compile-time feature, you must first define it in
the `main` workspace crate located in `src/main/Cargo.toml`. The feature must
enable a feature in the other workspace crate(s) you intend to use it in. Then
the said workspace crate(s) must define the feature there in its `Cargo.toml`.
So, if this is adding a feature to the API such as `woof`, you define the
feature in the `api` crate's `Cargo.toml` as `woof = []`. The feature definition
in `main`'s `Cargo.toml` will be `woof = ["conduwuit-api/woof"]`.
So, if this is adding a feature to the API such as `woof`, you define the feature
in the `api` crate's `Cargo.toml` as `woof = []`. The feature definition in `main`'s
`Cargo.toml` will be `woof = ["conduwuit-api/woof"]`.
The rationale for this is due to Rust / Cargo not supporting ["workspace level
features"][9], we must make a choice of; either scattering features all over the
workspace crates, making it difficult for anyone to add or remove default
features; or define all the features in one central workspace crate that
propagate down/up to the other workspace crates. It is a Cargo pitfall, and we'd
like to see better developer UX in Rust's Workspaces.
The rationale for this is due to Rust / Cargo not supporting
["workspace level features"][9], we must make a choice of; either scattering
features all over the workspace crates, making it difficult for anyone to add
or remove default features; or define all the features in one central workspace
crate that propagate down/up to the other workspace crates. It is a Cargo pitfall,
and we'd like to see better developer UX in Rust's Workspaces.
Additionally, the definition of one single place makes "feature collection" in
our Nix flake a million times easier instead of collecting and deduping them all
from searching in all the workspace crates' `Cargo.toml`s. Though we wouldn't
need to do this if Rust supported workspace-level features to begin with.
Additionally, the definition of one single place makes "feature collection" in our
Nix flake a million times easier instead of collecting and deduping them all from
searching in all the workspace crates' `Cargo.toml`s. Though we wouldn't need to
do this if Rust supported workspace-level features to begin with.
## List of forked dependencies
During Continuwuity (and prior projects) development, we have had to fork some
dependencies to support our use-cases. These forks exist for various reasons
including features that upstream projects won't accept, faster-paced
development, Continuwuity-specific usecases, or lack of time to upstream
changes.
During Continuwuity (and prior projects) development, we have had to fork some dependencies to support our use-cases.
These forks exist for various reasons including features that upstream projects won't accept,
faster-paced development, Continuwuity-specific usecases, or lack of time to upstream changes.
All forked dependencies are maintained under the
[continuwuation organization on Forgejo](https://forgejo.ellis.link/continuwuation):
All forked dependencies are maintained under the [continuwuation organization on Forgejo](https://forgejo.ellis.link/continuwuation):
- [ruwuma][continuwuation-ruwuma] - Fork of [ruma/ruma][ruma] with various
performance improvements, more features and better client/server interop
- [rocksdb][continuwuation-rocksdb] - Fork of [facebook/rocksdb][rocksdb] via
[`@zaidoon1`][8] with liburing build fixes and GCC debug build fixes
- [jemallocator][continuwuation-jemallocator] - Fork of
[tikv/jemallocator][jemallocator] fixing musl builds, suspicious code, and
adding support for redzones in Valgrind
- [rustyline-async][continuwuation-rustyline-async] - Fork of
[zyansheep/rustyline-async][rustyline-async] with tab completion callback and
`CTRL+\` signal quit event for Continuwuity console CLI
- [rust-rocksdb][continuwuation-rust-rocksdb] - Fork of
[rust-rocksdb/rust-rocksdb][rust-rocksdb] fixing musl build issues, removing
unnecessary `gtest` include, and using our RocksDB and jemallocator forks
- [tracing][continuwuation-tracing] - Fork of [tokio-rs/tracing][tracing]
implementing `Clone` for `EnvFilter` to support dynamically changing tracing
environments
- [ruwuma][continuwuation-ruwuma] - Fork of [ruma/ruma][ruma] with various performance improvements, more features and better client/server interop
- [rocksdb][continuwuation-rocksdb] - Fork of [facebook/rocksdb][rocksdb] via [`@zaidoon1`][8] with liburing build fixes and GCC debug build fixes
- [jemallocator][continuwuation-jemallocator] - Fork of [tikv/jemallocator][jemallocator] fixing musl builds, suspicious code,
and adding support for redzones in Valgrind
- [rustyline-async][continuwuation-rustyline-async] - Fork of [zyansheep/rustyline-async][rustyline-async] with tab completion callback
and `CTRL+\` signal quit event for Continuwuity console CLI
- [rust-rocksdb][continuwuation-rust-rocksdb] - Fork of [rust-rocksdb/rust-rocksdb][rust-rocksdb] fixing musl build issues,
removing unnecessary `gtest` include, and using our RocksDB and jemallocator forks
- [tracing][continuwuation-tracing] - Fork of [tokio-rs/tracing][tracing] implementing `Clone` for `EnvFilter` to
support dynamically changing tracing environments
## Debugging with `tokio-console`
[`tokio-console`][7] can be a useful tool for debugging and profiling. To make a
`tokio-console`-enabled build of Continuwuity, enable the `tokio_console`
feature, disable the default `release_max_log_level` feature, and set the
`--cfg tokio_unstable` flag to enable experimental tokio APIs. A build might
look like this:
`tokio-console`-enabled build of Continuwuity, enable the `tokio_console` feature,
disable the default `release_max_log_level` feature, and set the `--cfg
tokio_unstable` flag to enable experimental tokio APIs. A build might look like
this:
```bash
RUSTFLAGS="--cfg tokio_unstable" cargo +nightly build \
@@ -113,84 +100,34 @@ ## Debugging with `tokio-console`
--features=systemd,element_hacks,gzip_compression,brotli_compression,zstd_compression,tokio_console
```
You will also need to enable the `tokio_console` config option in Continuwuity
when starting it. This was due to tokio-console causing gradual memory
leak/usage if left enabled.
You will also need to enable the `tokio_console` config option in Continuwuity when
starting it. This was due to tokio-console causing gradual memory leak/usage
if left enabled.
## Building Docker Images
Official Continuwuity images are built using **Docker Buildx** and the
Dockerfile found at [`docker/Dockerfile`][dockerfile-path].
The images are compatible with Docker and other container runtimes like Podman
or containerd.
The images _do not contain a shell_. They contain only the Continuwuity binary,
required libraries, TLS certificates, and metadata.
<details>
<summary>Click to view the Dockerfile</summary>
You can also
<a
href="<https://forgejo.ellis.link/continuwuation/continuwuation/src/branch/main/docker/Dockerfile>"
target="_blank"
>
view the Dockerfile on Forgejo
</a>
.
```dockerfile file="../../docker/Dockerfile"
```
</details>
### Building Locally
To build an image locally using Docker Buildx:
To build a Docker image for Continuwuity, use the standard Docker build command:
```bash
# Build for the current platform and load into the local Docker daemon
docker buildx build --load --tag continuwuity:latest -f docker/Dockerfile .
# Example: Build for specific platforms and push to a registry
# docker buildx build --platform linux/amd64,linux/arm64 --tag registry.io/org/continuwuity:latest -f docker/Dockerfile . --push
# Example: Build binary optimised for the current CPU (standard release profile)
# docker buildx build --load \
# --tag continuwuity:latest \
# --build-arg TARGET_CPU=native \
# -f docker/Dockerfile .
# Example: Build maxperf variant (release-max-perf profile with LTO)
# docker buildx build --load \
# --tag continuwuity:latest-maxperf \
# --build-arg TARGET_CPU=native \
# --build-arg RUST_PROFILE=release-max-perf \
# -f docker/Dockerfile .
docker build -f docker/Dockerfile .
```
Refer to the Docker Buildx documentation for more advanced build options.
The image can be cross-compiled for different architectures.
[dockerfile-path]:
https://forgejo.ellis.link/continuwuation/continuwuation/src/branch/main/docker/Dockerfile
[continuwuation-ruwuma]: https://forgejo.ellis.link/continuwuation/ruwuma
[continuwuation-rocksdb]: https://forgejo.ellis.link/continuwuation/rocksdb
[continuwuation-jemallocator]:
https://forgejo.ellis.link/continuwuation/jemallocator
[continuwuation-rustyline-async]:
https://forgejo.ellis.link/continuwuation/rustyline-async
[continuwuation-rust-rocksdb]:
https://forgejo.ellis.link/continuwuation/rust-rocksdb
[continuwuation-jemallocator]: https://forgejo.ellis.link/continuwuation/jemallocator
[continuwuation-rustyline-async]: https://forgejo.ellis.link/continuwuation/rustyline-async
[continuwuation-rust-rocksdb]: https://forgejo.ellis.link/continuwuation/rust-rocksdb
[continuwuation-tracing]: https://forgejo.ellis.link/continuwuation/tracing
[ruma]: https://github.com/ruma/ruma/
[rocksdb]: https://github.com/facebook/rocksdb/
[jemallocator]: https://github.com/tikv/jemallocator/
[rustyline-async]: https://github.com/zyansheep/rustyline-async/
[rust-rocksdb]: https://github.com/rust-rocksdb/rust-rocksdb/
[tracing]: https://github.com/tokio-rs/tracing/
[7]: https://docs.rs/tokio-console/latest/tokio_console/
[8]: https://github.com/zaidoon1/
[9]: https://github.com/rust-lang/cargo/issues/12162

View File

@@ -6,10 +6,10 @@
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
},
{
"id": 10,
"id": 9,
"mention_room": false,
"date": "2026-03-03",
"message": "We've just released [v0.5.6](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.6), which contains a few security improvements - plus significant reliability and performance improvements. Please update as soon as possible. \n\nWe released [v0.5.5](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.5) two weeks ago, but it skipped your admin room straight to [our announcements channel](https://matrix.to/#/!jIdNjSM5X-V5JVx2h2kAhUZIIQ08GyzPL55NFZAH1vM?via=ellis.link&via=gingershaped.computer&via=matrix.org). Make sure you're there to get important information as soon as we announce it! [Our space](https://matrix.to/#/!8cR4g-i9ucof69E4JHNg9LbPVkGprHb3SzcrGBDDJgk?via=continuwuity.org&via=ellis.link&via=matrix.org) has also gained a bunch of new and interesting rooms - be there or be square."
"date": "2026-02-09",
"message": "Yesterday we released [v0.5.4](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.4). Bugfixes, performance improvements and more moderation features! There's also a security fix, so please update as soon as possible. Don't forget to join [our announcements channel](https://matrix.to/#/!jIdNjSM5X-V5JVx2h2kAhUZIIQ08GyzPL55NFZAH1vM/%2489TY9CqRg4-ff1MGo3Ulc5r5X4pakfdzT-99RD8Docc?via=ellis.link&via=explodie.org&via=matrix.org) to get important information sooner <3 "
}
]
}

View File

@@ -1 +1 @@
{"m.homeserver":{"base_url": "https://matrix.continuwuity.org"},"org.matrix.msc4143.rtc_foci":[{"type":"livekit","livekit_service_url":"https://livekit.ellis.link"}]}
{"m.homeserver":{"base_url": "https://matrix.continuwuity.org"},"org.matrix.msc3575.proxy":{"url": "https://matrix.continuwuity.org"},"org.matrix.msc4143.rtc_foci":[{"type":"livekit","livekit_service_url":"https://livekit.ellis.link"}]}

View File

@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://continuwuity.org/schema/announcements.schema.json",
"$id": "https://continwuity.org/schema/announcements.schema.json",
"type": "object",
"properties": {
"announcements": {

View File

@@ -4,11 +4,6 @@
"name": "config",
"label": "Configuration"
},
{
"type": "file",
"name": "environment-variables",
"label": "Environment Variables"
},
{
"type": "file",
"name": "admin",

View File

@@ -27,7 +27,7 @@ ## `!admin media delete-past-remote-media`
* Delete all remote and local media from 3 days ago, up until now:
`!admin media delete-past-remote-media -a 3d
--yes-i-want-to-delete-local-media`
-yes-i-want-to-delete-local-media`
## `!admin media delete-all-from-user`

View File

@@ -1,281 +0,0 @@
# Environment Variables
Continuwuity can be configured entirely through environment variables, making it
ideal for containerised deployments and infrastructure-as-code scenarios.
This is a convenience reference and may not be exhaustive. The
[Configuration Reference](./config.mdx) is the primary source for all
configuration options.
## Prefix System
Continuwuity supports three environment variable prefixes for backwards
compatibility:
- `CONTINUWUITY_*` (current, recommended)
- `CONDUWUIT_*` (compatibility)
- `CONDUIT_*` (legacy)
All three prefixes work identically. Use double underscores (`__`) to represent
nested configuration sections from the TOML config.
**Examples:**
```bash
# Simple top-level config
CONTINUWUITY_SERVER_NAME="matrix.example.com"
CONTINUWUITY_PORT="8008"
# Nested config sections use double underscores
# This maps to [database] section in TOML
CONTINUWUITY_DATABASE__PATH="/var/lib/continuwuity"
# This maps to [tls] section in TOML
CONTINUWUITY_TLS__CERTS="/path/to/cert.pem"
```
## Configuration File Override
You can specify a custom configuration file path:
- `CONTINUWUITY_CONFIG` - Path to continuwuity.toml (current)
- `CONDUWUIT_CONFIG` - Path to config file (compatibility)
- `CONDUIT_CONFIG` - Path to config file (legacy)
## Essential Variables
These are the minimum variables needed for a working deployment:
| Variable | Description | Default |
| ---------------------------- | ---------------------------------- | ---------------------- |
| `CONTINUWUITY_SERVER_NAME` | Your Matrix server's domain name | Required |
| `CONTINUWUITY_DATABASE_PATH` | Path to RocksDB database directory | `/var/lib/conduwuit` |
| `CONTINUWUITY_ADDRESS` | IP address to bind to | `["127.0.0.1", "::1"]` |
| `CONTINUWUITY_PORT` | Port to listen on | `8008` |
## Network Configuration
| Variable | Description | Default |
| -------------------------------- | ----------------------------------------------- | ---------------------- |
| `CONTINUWUITY_ADDRESS` | Bind address (use `0.0.0.0` for all interfaces) | `["127.0.0.1", "::1"]` |
| `CONTINUWUITY_PORT` | HTTP port | `8008` |
| `CONTINUWUITY_UNIX_SOCKET_PATH` | UNIX socket path (alternative to TCP) | - |
| `CONTINUWUITY_UNIX_SOCKET_PERMS` | Socket permissions (octal) | `660` |
## Database Configuration
| Variable | Description | Default |
| ------------------------------------------ | --------------------------- | -------------------- |
| `CONTINUWUITY_DATABASE_PATH` | RocksDB data directory | `/var/lib/conduwuit` |
| `CONTINUWUITY_DATABASE_BACKUP_PATH` | Backup directory | - |
| `CONTINUWUITY_DATABASE_BACKUPS_TO_KEEP` | Number of backups to retain | `1` |
| `CONTINUWUITY_DB_CACHE_CAPACITY_MB` | Database read cache (MB) | - |
| `CONTINUWUITY_DB_WRITE_BUFFER_CAPACITY_MB` | Write cache (MB) | - |
## Cache Configuration
| Variable | Description |
| ---------------------------------------- | ------------------------ |
| `CONTINUWUITY_CACHE_CAPACITY_MODIFIER` | LRU cache multiplier |
| `CONTINUWUITY_PDU_CACHE_CAPACITY` | PDU cache entries |
| `CONTINUWUITY_AUTH_CHAIN_CACHE_CAPACITY` | Auth chain cache entries |
## DNS Configuration
Configure DNS resolution behaviour for federation and external requests.
| Variable | Description | Default |
| ------------------------------------ | ---------------------------- | -------- |
| `CONTINUWUITY_DNS_CACHE_ENTRIES` | Max DNS cache entries | `32768` |
| `CONTINUWUITY_DNS_MIN_TTL` | Minimum cache TTL (seconds) | `10800` |
| `CONTINUWUITY_DNS_MIN_TTL_NXDOMAIN` | NXDOMAIN cache TTL (seconds) | `259200` |
| `CONTINUWUITY_DNS_ATTEMPTS` | Retry attempts | - |
| `CONTINUWUITY_DNS_TIMEOUT` | Query timeout (seconds) | - |
| `CONTINUWUITY_DNS_TCP_FALLBACK` | Allow TCP fallback | - |
| `CONTINUWUITY_QUERY_ALL_NAMESERVERS` | Query all nameservers | - |
| `CONTINUWUITY_QUERY_OVER_TCP_ONLY` | TCP-only queries | - |
## Request Configuration
| Variable | Description |
| ------------------------------------ | ----------------------------- |
| `CONTINUWUITY_MAX_REQUEST_SIZE` | Max HTTP request size (bytes) |
| `CONTINUWUITY_REQUEST_CONN_TIMEOUT` | Connection timeout (seconds) |
| `CONTINUWUITY_REQUEST_TIMEOUT` | Overall request timeout |
| `CONTINUWUITY_REQUEST_TOTAL_TIMEOUT` | Total timeout |
| `CONTINUWUITY_REQUEST_IDLE_TIMEOUT` | Idle timeout |
| `CONTINUWUITY_REQUEST_IDLE_PER_HOST` | Idle connections per host |
## Federation Configuration
Control how your server federates with other Matrix servers.
| Variable | Description | Default |
| ---------------------------------------------- | ----------------------------- | ------- |
| `CONTINUWUITY_ALLOW_FEDERATION` | Enable federation | `true` |
| `CONTINUWUITY_FEDERATION_LOOPBACK` | Allow loopback federation | - |
| `CONTINUWUITY_FEDERATION_CONN_TIMEOUT` | Connection timeout | - |
| `CONTINUWUITY_FEDERATION_TIMEOUT` | Request timeout | - |
| `CONTINUWUITY_FEDERATION_IDLE_TIMEOUT` | Idle timeout | - |
| `CONTINUWUITY_FEDERATION_IDLE_PER_HOST` | Idle connections per host | - |
| `CONTINUWUITY_TRUSTED_SERVERS` | JSON array of trusted servers | - |
| `CONTINUWUITY_QUERY_TRUSTED_KEY_SERVERS_FIRST` | Query trusted first | - |
| `CONTINUWUITY_ONLY_QUERY_TRUSTED_KEY_SERVERS` | Only query trusted | - |
**Example:**
```bash
# Trust matrix.org for key verification
CONTINUWUITY_TRUSTED_SERVERS='["matrix.org"]'
```
## Registration & User Configuration
Control user registration and account creation behaviour.
| Variable | Description | Default |
| ------------------------------------------ | --------------------- | ------- |
| `CONTINUWUITY_ALLOW_REGISTRATION` | Enable registration | `true` |
| `CONTINUWUITY_REGISTRATION_TOKEN` | Token requirement | - |
| `CONTINUWUITY_SUSPEND_ON_REGISTER` | Suspend new accounts | - |
| `CONTINUWUITY_NEW_USER_DISPLAYNAME_SUFFIX` | Display name suffix | 🏳️‍⚧️ |
| `CONTINUWUITY_RECAPTCHA_SITE_KEY` | reCAPTCHA site key | - |
| `CONTINUWUITY_RECAPTCHA_PRIVATE_SITE_KEY` | reCAPTCHA private key | - |
**Example:**
```bash
# Disable open registration
CONTINUWUITY_ALLOW_REGISTRATION="false"
# Require a registration token
CONTINUWUITY_REGISTRATION_TOKEN="your_secret_token_here"
```
## Feature Configuration
| Variable | Description | Default |
| ---------------------------------------------------------- | -------------------------- | ------- |
| `CONTINUWUITY_ALLOW_ENCRYPTION` | Enable E2EE | `true` |
| `CONTINUWUITY_ALLOW_ROOM_CREATION` | Enable room creation | - |
| `CONTINUWUITY_ALLOW_UNSTABLE_ROOM_VERSIONS` | Allow unstable versions | - |
| `CONTINUWUITY_DEFAULT_ROOM_VERSION` | Default room version | `v11` |
| `CONTINUWUITY_REQUIRE_AUTH_FOR_PROFILE_REQUESTS` | Auth for profiles | - |
| `CONTINUWUITY_ALLOW_PUBLIC_ROOM_DIRECTORY_OVER_FEDERATION` | Federate directory | - |
| `CONTINUWUITY_ALLOW_PUBLIC_ROOM_DIRECTORY_WITHOUT_AUTH` | Unauth directory | - |
| `CONTINUWUITY_ALLOW_DEVICE_NAME_FEDERATION` | Device names in federation | - |
## TLS Configuration
Built-in TLS support is primarily for testing. **For production deployments,
especially when federating on the internet, use a reverse proxy** (Traefik,
Caddy, nginx) to handle TLS termination.
| Variable | Description |
| --------------------------------- | ------------------------- |
| `CONTINUWUITY_TLS__CERTS` | TLS certificate file path |
| `CONTINUWUITY_TLS__KEY` | TLS private key path |
| `CONTINUWUITY_TLS__DUAL_PROTOCOL` | Support TLS 1.2 + 1.3 |
**Example (testing only):**
```bash
CONTINUWUITY_TLS__CERTS="/etc/letsencrypt/live/matrix.example.com/fullchain.pem"
CONTINUWUITY_TLS__KEY="/etc/letsencrypt/live/matrix.example.com/privkey.pem"
```
## Logging Configuration
Control log output format and verbosity.
| Variable | Description | Default |
| ------------------------------ | ------------------ | ------- |
| `CONTINUWUITY_LOG` | Log filter level | - |
| `CONTINUWUITY_LOG_COLORS` | ANSI colours | `true` |
| `CONTINUWUITY_LOG_SPAN_EVENTS` | Log span events | `none` |
| `CONTINUWUITY_LOG_THREAD_IDS` | Include thread IDs | - |
**Examples:**
```bash
# Set log level to info
CONTINUWUITY_LOG="info"
# Enable debug logging for specific modules
CONTINUWUITY_LOG="warn,continuwuity::api=debug"
# Disable colours for log aggregation
CONTINUWUITY_LOG_COLORS="false"
```
## Observability Configuration
| Variable | Description |
| ---------------------------------------- | --------------------- |
| `CONTINUWUITY_ALLOW_OTLP` | Enable OpenTelemetry |
| `CONTINUWUITY_OTLP_FILTER` | OTLP filter level |
| `CONTINUWUITY_OTLP_PROTOCOL` | Protocol (http/grpc) |
| `CONTINUWUITY_TRACING_FLAME` | Enable flame graphs |
| `CONTINUWUITY_TRACING_FLAME_FILTER` | Flame graph filter |
| `CONTINUWUITY_TRACING_FLAME_OUTPUT_PATH` | Output directory |
| `CONTINUWUITY_SENTRY` | Enable Sentry |
| `CONTINUWUITY_SENTRY_ENDPOINT` | Sentry DSN |
| `CONTINUWUITY_SENTRY_SEND_SERVER_NAME` | Include server name |
| `CONTINUWUITY_SENTRY_TRACES_SAMPLE_RATE` | Sample rate (0.0-1.0) |
## Admin Configuration
Configure admin users and automated command execution.
| Variable | Description | Default |
| ------------------------------------------ | -------------------------------- | ----------------- |
| `CONTINUWUITY_ADMINS_LIST` | JSON array of admin user IDs | - |
| `CONTINUWUITY_ADMINS_FROM_ROOM` | Derive admins from room | - |
| `CONTINUWUITY_ADMIN_ESCAPE_COMMANDS` | Allow `\` prefix in public rooms | - |
| `CONTINUWUITY_ADMIN_CONSOLE_AUTOMATIC` | Auto-activate console | - |
| `CONTINUWUITY_ADMIN_EXECUTE` | JSON array of startup commands | - |
| `CONTINUWUITY_ADMIN_EXECUTE_ERRORS_IGNORE` | Ignore command errors | - |
| `CONTINUWUITY_ADMIN_SIGNAL_EXECUTE` | Commands on SIGUSR2 | - |
| `CONTINUWUITY_ADMIN_ROOM_TAG` | Admin room tag | `m.server_notice` |
**Examples:**
```bash
# Create admin user on startup
CONTINUWUITY_ADMIN_EXECUTE='["users create-user admin", "users make-user-admin admin"]'
# Specify admin users directly
CONTINUWUITY_ADMINS_LIST='["@alice:example.com", "@bob:example.com"]'
```
## Media & URL Preview Configuration
| Variable | Description |
| ---------------------------------------------------- | ------------------ |
| `CONTINUWUITY_URL_PREVIEW_BOUND_INTERFACE` | Bind interface |
| `CONTINUWUITY_URL_PREVIEW_DOMAIN_CONTAINS_ALLOWLIST` | Domain allowlist |
| `CONTINUWUITY_URL_PREVIEW_DOMAIN_EXPLICIT_ALLOWLIST` | Explicit allowlist |
| `CONTINUWUITY_URL_PREVIEW_DOMAIN_EXPLICIT_DENYLIST` | Explicit denylist |
| `CONTINUWUITY_URL_PREVIEW_MAX_SPIDER_SIZE` | Max fetch size |
| `CONTINUWUITY_URL_PREVIEW_TIMEOUT` | Fetch timeout |
| `CONTINUWUITY_IP_RANGE_DENYLIST` | IP range denylist |
## Tokio Runtime Configuration
These can be set as environment variables or CLI arguments:
| Variable | Description |
| ----------------------------------------- | -------------------------- |
| `TOKIO_WORKER_THREADS` | Worker thread count |
| `TOKIO_GLOBAL_QUEUE_INTERVAL` | Global queue interval |
| `TOKIO_EVENT_INTERVAL` | Event interval |
| `TOKIO_MAX_IO_EVENTS_PER_TICK` | Max I/O events per tick |
| `CONTINUWUITY_RUNTIME_HISTOGRAM_INTERVAL` | Histogram bucket size (μs) |
| `CONTINUWUITY_RUNTIME_HISTOGRAM_BUCKETS` | Bucket count |
| `CONTINUWUITY_RUNTIME_WORKER_AFFINITY` | Enable worker affinity |
## See Also
- [Configuration Reference](./config.mdx) - Complete TOML configuration
documentation
- [Admin Commands](./admin/) - Admin command reference

View File

@@ -6,7 +6,7 @@ # Troubleshooting Continuwuity
Please check that your issues are not due to problems with your Docker setup.
:::
## Continuwuity issues
## Continuwuity and Matrix issues
### Slow joins to rooms
@@ -23,16 +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.
### Configuration not working as expected
Sometimes you can make a mistake in your configuration that
means things don't get passed to Continuwuity correctly.
This is particularly easy to do with environment variables.
To check what configuration Continuwuity actually sees, you can
use the `!admin server show-config` command in your admin room.
Beware that this prints out any secrets in your configuration,
so you might want to delete the result afterwards!
### Lost access to admin room
You can reinvite yourself to the admin room through the following methods:
@@ -43,7 +33,17 @@ ### Lost access to admin room
- Or specify the `emergency_password` config option to allow you to temporarily
log into the server account (`@conduit`) from a web client
## DNS issues
## General potential issues
### Configuration not working as expected
Sometimes you can make a mistake in your configuration that
means things don't get passed to Continuwuity correctly.
This is particularly easy to do with environment variables.
To check what configuration Continuwuity actually sees, you can
use the `!admin server show-config` command in your admin room.
Beware that this prints out any secrets in your configuration,
so you might want to delete the result afterwards!
### Potential DNS issues when using Docker

54
flake.lock generated
View File

@@ -3,11 +3,11 @@
"advisory-db": {
"flake": false,
"locked": {
"lastModified": 1773786698,
"narHash": "sha256-o/J7ZculgwSs1L4H4UFlFZENOXTJzq1X0n71x6oNNvY=",
"lastModified": 1766324728,
"narHash": "sha256-9C+WyE5U3y5w4WQXxmb0ylRyMMsPyzxielWXSHrcDpE=",
"owner": "rustsec",
"repo": "advisory-db",
"rev": "99e9de91bb8b61f06ef234ff84e11f758ecd5384",
"rev": "c88b88c62bda077be8aa621d4e89d8701e39cb5d",
"type": "github"
},
"original": {
@@ -18,11 +18,11 @@
},
"crane": {
"locked": {
"lastModified": 1773189535,
"narHash": "sha256-E1G/Or6MWeP+L6mpQ0iTFLpzSzlpGrITfU2220Gq47g=",
"lastModified": 1766194365,
"narHash": "sha256-4AFsUZ0kl6MXSm4BaQgItD0VGlEKR3iq7gIaL7TjBvc=",
"owner": "ipetkov",
"repo": "crane",
"rev": "6fa2fb4cf4a89ba49fc9dd5a3eb6cde99d388269",
"rev": "7d8ec2c71771937ab99790b45e6d9b93d15d9379",
"type": "github"
},
"original": {
@@ -39,11 +39,11 @@
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1773732206,
"narHash": "sha256-HKibxaUXyWd4Hs+ZUnwo6XslvaFqFqJh66uL9tphU4Q=",
"lastModified": 1766299592,
"narHash": "sha256-7u+q5hexu2eAxL2VjhskHvaUKg+GexmelIR2ve9Nbb4=",
"owner": "nix-community",
"repo": "fenix",
"rev": "0aa13c1b54063a8d8679b28a5cd357ba98f4a56b",
"rev": "381579dee168d5ced412e2990e9637ecc7cf1c5d",
"type": "github"
},
"original": {
@@ -55,11 +55,11 @@
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"lastModified": 1765121682,
"narHash": "sha256-4VBOP18BFeiPkyhy9o4ssBNQEvfvv1kXkasAYd0+rrA=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"rev": "65f23138d8d09a92e30f1e5c87611b23ef451bf3",
"type": "github"
},
"original": {
@@ -74,11 +74,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1772408722,
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
"lastModified": 1765835352,
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
"type": "github"
},
"original": {
@@ -89,11 +89,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1773734432,
"narHash": "sha256-IF5ppUWh6gHGHYDbtVUyhwy/i7D261P7fWD1bPefOsw=",
"lastModified": 1766070988,
"narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cda48547b432e8d3b18b4180ba07473762ec8558",
"rev": "c6245e83d836d0433170a16eb185cefe0572f8b8",
"type": "github"
},
"original": {
@@ -105,11 +105,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1772328832,
"narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=",
"lastModified": 1765674936,
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742",
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
"type": "github"
},
"original": {
@@ -132,11 +132,11 @@
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1773697963,
"narHash": "sha256-xdKI77It9PM6eNrCcDZsnP4SKulZwk8VkDgBRVMnCb8=",
"lastModified": 1766253897,
"narHash": "sha256-ChK07B1aOlJ4QzWXpJo+y8IGAxp1V9yQ2YloJ+RgHRw=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "2993637174252ff60a582fd1f55b9ab52c39db6d",
"rev": "765b7bdb432b3740f2d564afccfae831d5a972e4",
"type": "github"
},
"original": {
@@ -153,11 +153,11 @@
]
},
"locked": {
"lastModified": 1773297127,
"narHash": "sha256-6E/yhXP7Oy/NbXtf1ktzmU8SdVqJQ09HC/48ebEGBpk=",
"lastModified": 1766000401,
"narHash": "sha256-+cqN4PJz9y0JQXfAK5J1drd0U05D5fcAGhzhfVrDlsI=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "71b125cd05fbfd78cab3e070b73544abe24c5016",
"rev": "42d96e75aa56a3f70cab7e7dc4a32868db28e8fd",
"type": "github"
},
"original": {

View File

@@ -12,6 +12,7 @@
rocksdbAllFeatures = self'.packages.rocksdb.override {
enableJemalloc = true;
enableLiburing = true;
};
commonAttrs = (uwulib.build.commonAttrs { }) // {

View File

@@ -27,6 +27,7 @@
commonAttrsArgs.profile = "release";
rocksdb = self'.packages.rocksdb.override {
enableJemalloc = true;
enableLiburing = true;
};
features = {
enabledFeatures = "all";

View File

@@ -7,6 +7,7 @@
rust-jemalloc-sys-unprefixed,
enableJemalloc ? false,
enableLiburing ? false,
fetchFromGitea,
@@ -31,7 +32,7 @@ in
# for some reason enableLiburing in nixpkgs rocksdb is default true
# which breaks Darwin entirely
enableLiburing = notDarwin;
enableLiburing = enableLiburing && notDarwin;
}).overrideAttrs
(old: {
src = fetchFromGitea {
@@ -73,7 +74,7 @@ in
"USE_RTTI"
]);
enableLiburing = notDarwin;
enableLiburing = enableLiburing && notDarwin;
# outputs has "tools" which we don't need or use
outputs = [ "out" ];

View File

@@ -15,7 +15,7 @@
file = inputs.self + "/rust-toolchain.toml";
# See also `rust-toolchain.toml`
sha256 = "sha256-sqSWJDUxc+zaz1nBWMAJKTAGBuGWP25GCftIOlCEAtA=";
sha256 = "sha256-SJwZ8g0zF2WrKDVmHrVG3pD2RGoQeo24MEXnNx5FyuI=";
};
in
{

View File

@@ -11,13 +11,13 @@
uwulib = inputs.self.uwulib.init pkgs;
rocksdbAllFeatures = self'.packages.rocksdb.override {
enableJemalloc = true;
enableLiburing = true;
};
in
{
# basic nix shell containing all things necessary to build continuwuity in all flavors manually (on x86_64-linux)
devShells.default = uwulib.build.craneLib.devShell {
packages = [
pkgs.nodejs
pkgs.pkg-config
pkgs.liburing
pkgs.rust-jemalloc-sys-unprefixed

656
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,6 @@
"@rspress/core": "^2.0.0",
"@rspress/plugin-client-redirects": "^2.0.0",
"@rspress/plugin-sitemap": "^2.0.0",
"typescript": "^6.0.0"
"typescript": "^5.9.3"
}
}

View File

@@ -18,7 +18,6 @@ Environment="CONTINUWUITY_DATABASE_PATH=%S/conduwuit"
Environment="CONTINUWUITY_CONFIG_RELOAD_SIGNAL=true"
LoadCredential=conduwuit.toml:/etc/conduwuit/conduwuit.toml
RefreshOnReload=yes
ExecStart=/usr/bin/conduwuit --config ${CREDENTIALS_DIRECTORY}/conduwuit.toml

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:recommended", "replacements:all", ":semanticCommitTypeAll(chore)", "helpers:pinGitHubActionDigests"],
"extends": ["config:recommended", "replacements:all"],
"dependencyDashboard": true,
"osvVulnerabilityAlerts": true,
"lockFileMaintenance": {
@@ -36,18 +36,10 @@
},
"packageRules": [
{
"description": "Batch minor and patch Rust dependency updates",
"matchManagers": ["cargo"],
"matchUpdateTypes": ["minor", "patch"],
"matchCurrentVersion": ">=1.0.0",
"groupName": "rust-non-major"
},
{
"description": "Batch patch-level zerover Rust dependency updates",
"description": "Batch patch-level Rust dependency updates",
"matchManagers": ["cargo"],
"matchUpdateTypes": ["patch"],
"matchCurrentVersion": ">=0.1.0,<1.0.0",
"groupName": "rust-zerover-patch-updates"
"groupName": "rust-patch-updates"
},
{
"description": "Limit concurrent Cargo PRs",
@@ -95,16 +87,16 @@
}
],
"customManagers": [
{
"customType": "regex",
"description": "Update _VERSION variables in Dockerfiles",
"managerFilePatterns": [
"/(^|/)([Dd]ocker|[Cc]ontainer)file[^/]*$/",
"/(^|/|\\.)([Dd]ocker|[Cc]ontainer)file$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-zA-Z0-9-._]+?) depName=(?<depName>[^\\s]+?)(?: (lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[^\\s]+?))?(?: extractVersion=(?<extractVersion>[^\\s]+?))?(?: registryUrl=(?<registryUrl>[^\\s]+?))?\\s+(?:ENV\\s+|ARG\\s+)?[A-Za-z0-9_]+?_VERSION[ =][\"']?(?<currentValue>.+?)[\"']?\\s+(?:(?:ENV\\s+|ARG\\s+)?[A-Za-z0-9_]+?_CHECKSUM[ =][\"']?(?<currentDigest>.+?)[\"']?\\s)?"
]
}
{
"customType": "regex",
"description": "Update _VERSION variables in Dockerfiles",
"managerFilePatterns": [
"/(^|/)([Dd]ocker|[Cc]ontainer)file[^/]*$/",
"/(^|/|\\.)([Dd]ocker|[Cc]ontainer)file$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>[a-zA-Z0-9-._]+?) depName=(?<depName>[^\\s]+?)(?: (lookupName|packageName)=(?<packageName>[^\\s]+?))?(?: versioning=(?<versioning>[^\\s]+?))?(?: extractVersion=(?<extractVersion>[^\\s]+?))?(?: registryUrl=(?<registryUrl>[^\\s]+?))?\\s+(?:ENV\\s+|ARG\\s+)?[A-Za-z0-9_]+?_VERSION[ =][\"']?(?<currentValue>.+?)[\"']?\\s+(?:(?:ENV\\s+|ARG\\s+)?[A-Za-z0-9_]+?_CHECKSUM[ =][\"']?(?<currentDigest>.+?)[\"']?\\s)?"
]
}
]
}

View File

@@ -10,7 +10,7 @@
[toolchain]
profile = "minimal"
channel = "1.92.0"
channel = "1.90.0"
components = [
# For rust-analyzer
"rust-src",

View File

@@ -1,6 +1,6 @@
use std::fmt::Write;
use conduwuit::{Err, Result, utils::response::LimitReadExt};
use conduwuit::{Err, Result};
use futures::StreamExt;
use ruma::{OwnedRoomId, OwnedServerName, OwnedUserId};
@@ -55,15 +55,7 @@ pub(super) async fn fetch_support_well_known(&self, server_name: OwnedServerName
.send()
.await?;
let text = response
.limit_read_text(
self.services
.config
.max_request_size
.try_into()
.expect("u64 fits into usize"),
)
.await?;
let text = response.text().await?;
if text.is_empty() {
return Err!("Response text/body is empty.");

View File

@@ -40,7 +40,7 @@ pub enum MediaCommand {
/// * Delete all remote and local media from 3 days ago, up until now:
///
/// `!admin media delete-past-remote-media -a 3d
///--yes-i-want-to-delete-local-media`
///-yes-i-want-to-delete-local-media`
#[command(verbatim_doc_comment)]
DeletePastRemoteMedia {
/// The relative time (e.g. 30s, 5m, 7d) from now within which to

View File

@@ -296,31 +296,6 @@ pub(super) async fn reset_password(
Ok(())
}
#[admin_command]
pub(super) async fn issue_password_reset_link(&self, username: String) -> Result {
use conduwuit_service::password_reset::{PASSWORD_RESET_PATH, RESET_TOKEN_QUERY_PARAM};
self.bail_restricted()?;
let mut reset_url = self
.services
.config
.get_client_domain()
.join(PASSWORD_RESET_PATH)
.unwrap();
let user_id = parse_local_user_id(self.services, &username)?;
let token = self.services.password_reset.issue_token(user_id).await?;
reset_url
.query_pairs_mut()
.append_pair(RESET_TOKEN_QUERY_PARAM, &token.token);
self.write_str(&format!("Password reset link issued for {username}: {reset_url}"))
.await?;
Ok(())
}
#[admin_command]
pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) -> Result {
if self.body.len() < 2

View File

@@ -29,12 +29,6 @@ pub enum UserCommand {
password: Option<String>,
},
/// Issue a self-service password reset link for a user.
IssuePasswordResetLink {
/// Username of the user who may use the link
username: String,
},
/// Deactivate a user
///
/// User will be removed from all rooms by default.

View File

@@ -1,121 +0,0 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduwuit::{Err, Result, at};
use futures::StreamExt;
use ruma::api::client::dehydrated_device::{
delete_dehydrated_device::unstable as delete_dehydrated_device,
get_dehydrated_device::unstable as get_dehydrated_device, get_events::unstable as get_events,
put_dehydrated_device::unstable as put_dehydrated_device,
};
use crate::Ruma;
const MAX_BATCH_EVENTS: usize = 50;
/// # `PUT /_matrix/client/../dehydrated_device`
///
/// Creates or overwrites the user's dehydrated device.
#[tracing::instrument(skip_all, fields(%client))]
pub(crate) async fn put_dehydrated_device_route(
State(services): State<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<put_dehydrated_device::Request>,
) -> Result<put_dehydrated_device::Response> {
let sender_user = body
.sender_user
.as_deref()
.expect("AccessToken authentication required");
let device_id = body.body.device_id.clone();
services
.users
.set_dehydrated_device(sender_user, body.body)
.await?;
Ok(put_dehydrated_device::Response { device_id })
}
/// # `DELETE /_matrix/client/../dehydrated_device`
///
/// Deletes the user's dehydrated device without replacement.
#[tracing::instrument(skip_all, fields(%client))]
pub(crate) async fn delete_dehydrated_device_route(
State(services): State<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<delete_dehydrated_device::Request>,
) -> Result<delete_dehydrated_device::Response> {
let sender_user = body.sender_user();
let device_id = services.users.get_dehydrated_device_id(sender_user).await?;
services.users.remove_device(sender_user, &device_id).await;
Ok(delete_dehydrated_device::Response { device_id })
}
/// # `GET /_matrix/client/../dehydrated_device`
///
/// Gets the user's dehydrated device
#[tracing::instrument(skip_all, fields(%client))]
pub(crate) async fn get_dehydrated_device_route(
State(services): State<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_dehydrated_device::Request>,
) -> Result<get_dehydrated_device::Response> {
let sender_user = body.sender_user();
let device = services.users.get_dehydrated_device(sender_user).await?;
Ok(get_dehydrated_device::Response {
device_id: device.device_id,
device_data: device.device_data,
})
}
/// # `GET /_matrix/client/../dehydrated_device/{device_id}/events`
///
/// Paginates the events of the dehydrated device.
#[tracing::instrument(skip_all, fields(%client))]
pub(crate) async fn get_dehydrated_events_route(
State(services): State<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_events::Request>,
) -> Result<get_events::Response> {
let sender_user = body.sender_user();
let device_id = &body.body.device_id;
let existing_id = services.users.get_dehydrated_device_id(sender_user).await;
if existing_id.as_ref().is_err()
|| existing_id
.as_ref()
.is_ok_and(|existing_id| existing_id != device_id)
{
return Err!(Request(Forbidden("Not the dehydrated device_id.")));
}
let since: Option<u64> = body
.body
.next_batch
.as_deref()
.map(str::parse)
.transpose()?;
let mut next_batch: Option<u64> = None;
let events = services
.users
.get_to_device_events(sender_user, device_id, since, None)
.take(MAX_BATCH_EVENTS)
.inspect(|&(count, _)| {
next_batch.replace(count);
})
.map(at!(1))
.collect()
.await;
Ok(get_events::Response {
events,
next_batch: next_batch.as_ref().map(ToString::to_string),
})
}

View File

@@ -114,19 +114,7 @@ pub(crate) async fn get_content_thumbnail_route(
content,
content_type,
content_disposition,
} = match fetch_thumbnail(&services, &mxc, user, body.timeout_ms, &dim).await {
| Ok(meta) => meta,
| Err(conduwuit::Error::Io(e)) => match e.kind() {
| std::io::ErrorKind::NotFound =>
return Err!(Request(NotFound("Thumbnail not found."))),
| std::io::ErrorKind::PermissionDenied => {
error!("Permission denied when trying to read file: {e:?}");
return Err!(Request(Unknown("Unknown error when fetching thumbnail.")));
},
| _ => return Err!(Request(Unknown("Unknown error when fetching thumbnail."))),
},
| Err(_) => return Err!(Request(Unknown("Unknown error when fetching thumbnail."))),
};
} = fetch_thumbnail(&services, &mxc, user, body.timeout_ms, &dim).await?;
Ok(get_content_thumbnail::v1::Response {
file: content.expect("entire file contents"),

View File

@@ -6,7 +6,6 @@
pub(super) mod backup;
pub(super) mod capabilities;
pub(super) mod context;
pub(super) mod dehydrated_device;
pub(super) mod device;
pub(super) mod directory;
pub(super) mod filter;
@@ -50,7 +49,6 @@
pub(super) use backup::*;
pub(super) use capabilities::*;
pub(super) use context::*;
pub(super) use dehydrated_device::*;
pub(super) use device::*;
pub(super) use directory::*;
pub(super) use filter::*;

View File

@@ -1,5 +1,3 @@
#[cfg(test)]
mod tests;
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduwuit::{
@@ -196,7 +194,6 @@ async fn send_state_event_for_key_helper(
state_key: &str,
timestamp: Option<MilliSecondsSinceUnixEpoch>,
) -> Result<OwnedEventId> {
let json: &mut Raw<AnyStateEventContent> = &mut json.clone();
allowed_to_send_state_event(services, room_id, event_type, state_key, json).await?;
let state_lock = services.rooms.state.mutex.lock(room_id).await;
let event_id = services
@@ -224,7 +221,7 @@ async fn allowed_to_send_state_event(
room_id: &RoomId,
event_type: &StateEventType,
state_key: &str,
json: &mut Raw<AnyStateEventContent>,
json: &Raw<AnyStateEventContent>,
) -> Result {
match event_type {
| StateEventType::RoomCreate => {
@@ -369,7 +366,7 @@ async fn allowed_to_send_state_event(
}
},
| StateEventType::RoomMember => match json.deserialize_as::<RoomMemberEventContent>() {
| Ok(mut membership_content) => {
| Ok(membership_content) => {
let Ok(state_key) = UserId::parse(state_key) else {
return Err!(Request(BadJson(
"Membership event has invalid or non-existent state key"
@@ -379,24 +376,20 @@ async fn allowed_to_send_state_event(
if let Some(authorising_user) =
membership_content.join_authorized_via_users_server
{
// join_authorized_via_users_server must be thrown away, if user is already a
// member of the room.
if membership_content.membership != MembershipState::Join {
return Err!(Request(BadJson(
"join_authorised_via_users_server is only for member joins"
)));
}
if services
.rooms
.state_cache
.is_joined(state_key, room_id)
.await
{
membership_content.join_authorized_via_users_server = None;
*json = Raw::<AnyStateEventContent>::from_json_string(
serde_json::to_string(&membership_content)?,
)?;
return Ok(());
}
if membership_content.membership != MembershipState::Join {
return Err!(Request(BadJson(
"join_authorised_via_users_server is only for member joins"
return Err!(Request(InvalidParam(
"{state_key} is already joined, an authorising user is not required."
)));
}

View File

@@ -1,34 +0,0 @@
use super::*;
#[test]
fn test_strip_room_member() -> Result<()> {
//Test setup
let body = r#"
{
"avatar_url": "Something",
"displayname": "Someone",
"join_authorized_via_users_server": "@someone:domain.tld",
"membership": "join"
}"#;
println!("JSON (original): {body}");
let json: &mut Raw<AnyStateEventContent> =
&mut Raw::<AnyStateEventContent>::from_json_string(body.to_owned())?;
let mut membership_content: RoomMemberEventContent =
json.deserialize_as::<RoomMemberEventContent>()?;
//Begin Test
membership_content.join_authorized_via_users_server = None;
*json = Raw::<AnyStateEventContent>::from_json_string(serde_json::to_string(
&membership_content,
)?)?;
//Compare result
let result = json.json().get();
println!("JSON (modified): {result}");
assert_eq!(
result,
r#"{"avatar_url":"Something","displayname":"Someone","membership":"join"}"#
);
Ok(())
}

View File

@@ -270,7 +270,7 @@ async fn build_state_and_timeline(
// joined since the last sync, that being the syncing user's join event. if
// it's empty something is wrong.
if joined_since_last_sync && timeline.pdus.is_empty() {
debug_warn!("timeline for newly joined room is empty");
warn!("timeline for newly joined room is empty");
}
let (summary, device_list_updates) = try_join(

View File

@@ -1,5 +1,5 @@
use conduwuit::{
Event, PduEvent, Result, at, debug_warn,
Event, PduCount, PduEvent, Result, at, debug_warn,
pdu::EventHash,
trace,
utils::{self, IterStream, future::ReadyEqExt, stream::WidebandExt as _},
@@ -68,13 +68,9 @@ pub(super) async fn load_left_room(
return Ok(None);
}
// return early if:
// - this is an initial sync and the room filter doesn't include leaves, or
// - this is an incremental sync, and we've already synced the leave, and the
// room filter doesn't include leaves
if last_sync_end_count.is_none_or(|last_sync_end_count| last_sync_end_count >= left_count)
&& !filter.room.include_leave
{
// return early if this is an incremental sync, and we've already synced this
// leave to the user, and `include_leave` isn't set on the filter.
if !filter.room.include_leave && last_sync_end_count >= Some(left_count) {
return Ok(None);
}
@@ -199,13 +195,27 @@ async fn build_left_state_and_timeline(
leave_shortstatehash: ShortStateHash,
prev_membership_event: PduEvent,
) -> Result<(TimelinePdus, Vec<PduEvent>)> {
let SyncContext { syncing_user, filter, .. } = sync_context;
let SyncContext {
syncing_user,
last_sync_end_count,
filter,
..
} = sync_context;
let timeline_start_count = services
.rooms
.timeline
.get_pdu_count(&prev_membership_event.event_id)
.await?;
let timeline_start_count = if let Some(last_sync_end_count) = last_sync_end_count {
// for incremental syncs, start the timeline after `since`
PduCount::Normal(last_sync_end_count)
} else {
// for initial syncs, start the timeline after the previous membership
// event. we don't want to include the membership event itself
// because clients get confused when they see a `join`
// membership event in a `leave` room.
services
.rooms
.timeline
.get_pdu_count(&prev_membership_event.event_id)
.await?
};
// end the timeline at the user's leave event
let timeline_end_count = services

View File

@@ -11,7 +11,7 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduwuit::{
Result, at, extract_variant,
Result, extract_variant,
utils::{
ReadyExt, TryFutureExtExt,
stream::{BroadbandExt, Tools, WidebandExt},
@@ -297,18 +297,12 @@ pub(crate) async fn build_sync_events(
.rooms
.state_cache
.rooms_left(syncing_user)
.broad_filter_map(|(room_id, leave_pdu)| async {
let left_room = load_left_room(services, context, room_id.clone(), leave_pdu).await;
match left_room {
| Ok(Some(left_room)) => Some((room_id, left_room)),
| Ok(None) => None,
| Err(err) => {
warn!(?err, %room_id, "error loading joined room");
None
},
}
.broad_filter_map(|(room_id, leave_pdu)| {
load_left_room(services, context, room_id.clone(), leave_pdu)
.map_ok(move |left_room| (room_id, left_room))
.ok()
})
.ready_filter_map(|(room_id, left_room)| left_room.map(|left_room| (room_id, left_room)))
.collect();
let invited_rooms = services
@@ -391,7 +385,6 @@ pub(crate) async fn build_sync_events(
last_sync_end_count,
Some(current_count),
)
.map(at!(1))
.collect::<Vec<_>>();
let device_one_time_keys_count = services

View File

@@ -1029,7 +1029,6 @@ async fn collect_to_device(
events: services
.users
.get_to_device_events(sender_user, sender_device, None, Some(next_batch))
.map(at!(1))
.collect()
.await,
})

View File

@@ -50,7 +50,6 @@ pub(crate) async fn get_supported_versions_route(
("org.matrix.msc2836".to_owned(), true), /* threading/threads (https://github.com/matrix-org/matrix-spec-proposals/pull/2836) */
("org.matrix.msc2946".to_owned(), true), /* spaces/hierarchy summaries (https://github.com/matrix-org/matrix-spec-proposals/pull/2946) */
("org.matrix.msc3026.busy_presence".to_owned(), true), /* busy presence status (https://github.com/matrix-org/matrix-spec-proposals/pull/3026) */
("org.matrix.msc3814".to_owned(), true), /* dehydrated devices */
("org.matrix.msc3827".to_owned(), true), /* filtering of /publicRooms by room type (https://github.com/matrix-org/matrix-spec-proposals/pull/3827) */
("org.matrix.msc3952_intentional_mentions".to_owned(), true), /* intentional mentions (https://github.com/matrix-org/matrix-spec-proposals/pull/3952) */
("org.matrix.msc3916.stable".to_owned(), true), /* authenticated media (https://github.com/matrix-org/matrix-spec-proposals/pull/3916) */

View File

@@ -160,10 +160,6 @@ pub fn build(router: Router<State>, server: &Server) -> Router<State> {
.ruma_route(&client::update_device_route)
.ruma_route(&client::delete_device_route)
.ruma_route(&client::delete_devices_route)
.ruma_route(&client::put_dehydrated_device_route)
.ruma_route(&client::delete_dehydrated_device_route)
.ruma_route(&client::get_dehydrated_device_route)
.ruma_route(&client::get_dehydrated_events_route)
.ruma_route(&client::get_tags_route)
.ruma_route(&client::update_tag_route)
.ruma_route(&client::delete_tag_route)

View File

@@ -114,7 +114,6 @@ tracing.workspace = true
url.workspace = true
parking_lot.workspace = true
lock_api.workspace = true
hyper-util.workspace = true
[target.'cfg(unix)'.dependencies]
nix.workspace = true

View File

@@ -174,7 +174,6 @@ pub fn check(config: &Config) -> Result {
if config.allow_registration
&& config.yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse
&& config.registration_token.is_none()
&& config.registration_token_file.is_none()
{
warn!(
"Open registration is enabled via setting \

View File

@@ -68,10 +68,6 @@ pub struct Config {
///
/// Also see the `[global.well_known]` config section at the very bottom.
///
/// If `client` is not set under `[global.well_known]`, the server name will
/// be used as the base domain for user-facing links (such as password
/// reset links) created by Continuwuity.
///
/// Examples of delegation:
/// - https://continuwuity.org/.well-known/matrix/server
/// - https://continuwuity.org/.well-known/matrix/client
@@ -613,25 +609,19 @@ pub struct Config {
pub yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse: bool,
/// A static registration token that new users will have to provide when
/// creating an account. This token does not supersede tokens from other
/// sources, such as the `!admin token` command or the
/// `registration_token_file` configuration option.
/// creating an account. If unset and `allow_registration` is true,
/// you must set
/// `yes_i_am_very_very_sure_i_want_an_open_registration_server_prone_to_abuse`
/// to true to allow open registration without any conditions.
///
/// If you do not want to set a static token, the `!admin token` commands
/// may also be used to manage registration tokens.
///
/// example: "o&^uCtes4HPf0Vu@F20jQeeWE7"
///
/// display: sensitive
pub registration_token: Option<String>,
/// A path to a file containing static registration tokens, one per line.
/// Tokens in this file do not supersede tokens from other sources, such as
/// the `!admin token` command or the `registration_token` configuration
/// option.
///
/// The file will be read once, when Continuwuity starts. It is not
/// currently reread when the server configuration is reloaded. If the file
/// cannot be read, Continuwuity will fail to start.
pub registration_token_file: Option<PathBuf>,
/// The public site key for reCaptcha. If this is provided, reCaptcha
/// becomes required during registration. If both captcha *and*
/// registration token are enabled, both will be required during
@@ -1739,11 +1729,6 @@ pub struct Config {
/// default: "continuwuity/<version> (bot; +https://continuwuity.org)"
pub url_preview_user_agent: Option<String>,
/// Determines whether audio and video files will be downloaded for URL
/// previews.
#[serde(default)]
pub url_preview_allow_audio_video: bool,
/// List of forbidden room aliases and room IDs as strings of regex
/// patterns.
///
@@ -2093,13 +2078,6 @@ pub struct Config {
#[serde(default)]
pub force_disable_first_run_mode: bool,
/// Allow search engines and crawlers to index Continuwuity's built-in
/// webpages served under the `/_continuwuity/` prefix.
///
/// default: false
#[serde(default)]
pub allow_web_indexing: bool,
/// display: nested
#[serde(default)]
pub ldap: LdapConfig,

View File

@@ -4,7 +4,7 @@
mod response;
mod serde;
use std::{any::Any, borrow::Cow, convert::Infallible, error::Error as _, sync::PoisonError};
use std::{any::Any, borrow::Cow, convert::Infallible, sync::PoisonError};
pub use self::{err::visit, log::*};
@@ -66,8 +66,8 @@ pub enum Error {
Poison(Cow<'static, str>),
#[error("Regex error: {0}")]
Regex(#[from] regex::Error),
#[error("{0}")]
Reqwest(FormattedReqwestError),
#[error("Request error: {0}")]
Reqwest(#[from] reqwest::Error),
#[error("{0}")]
SerdeDe(Cow<'static, str>),
#[error("{0}")]
@@ -191,7 +191,6 @@ pub fn status_code(&self) -> http::StatusCode {
| Self::Reqwest(error) => error.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
| Self::Conflict(_) => StatusCode::CONFLICT,
| Self::Io(error) => response::io_error_code(error.kind()),
| Self::Uiaa(_) => StatusCode::UNAUTHORIZED,
| _ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
@@ -236,41 +235,3 @@ pub fn infallible(_e: &Infallible) {
#[must_use]
#[allow(clippy::needless_pass_by_value)]
pub fn sanitized_message(e: Error) -> String { e.sanitized_message() }
#[derive(Debug)]
pub struct FormattedReqwestError(reqwest::Error);
impl std::ops::Deref for FormattedReqwestError {
type Target = reqwest::Error;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl std::error::Error for FormattedReqwestError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.0.source() }
}
impl std::fmt::Display for FormattedReqwestError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(hyper_error) = self.0.source()
&& hyper_error.is::<hyper_util::client::legacy::Error>()
&& let Some(real_error) = hyper_error.source()
{
if let Some(real_reason) = real_error.source() {
write!(f, "{real_error}: {real_reason}")
} else {
write!(f, "{real_error}")
}
} else {
write!(f, "Request error: {}", &self.0)
}
}
}
impl From<reqwest::Error> for FormattedReqwestError {
fn from(err: reqwest::Error) -> Self { Self(err) }
}
impl From<reqwest::Error> for Error {
fn from(err: reqwest::Error) -> Self { Self::Reqwest(err.into()) }
}

View File

@@ -1224,7 +1224,6 @@ fn can_send_event(event: &impl Event, ple: Option<&impl Event>, user_level: Int)
}
/// Confirm that the event sender has the required power levels.
#[allow(clippy::cognitive_complexity)]
fn check_power_levels(
room_version: &RoomVersion,
power_event: &impl Event,

View File

@@ -75,7 +75,6 @@
/// event is part of the same room.
//#[tracing::instrument(level = "debug", skip(state_sets, auth_chain_sets,
//#[tracing::instrument(level event_fetch))]
#[allow(clippy::cognitive_complexity)]
pub async fn resolve<'a, Pdu, Sets, SetIter, Hasher, Fetch, FetchFut, Exists, ExistsFut>(
room_version: &RoomVersionId,
state_sets: Sets,

View File

@@ -11,7 +11,6 @@
pub mod math;
pub mod mutex_map;
pub mod rand;
pub mod response;
pub mod result;
pub mod set;
pub mod stream;

View File

@@ -1,51 +0,0 @@
use futures::StreamExt;
use num_traits::ToPrimitive;
use crate::Err;
/// Reads the response body while enforcing a maximum size limit to prevent
/// memory exhaustion.
pub async fn limit_read(response: reqwest::Response, max_size: u64) -> crate::Result<Vec<u8>> {
if response.content_length().is_some_and(|len| len > max_size) {
return Err!(BadServerResponse("Response too large"));
}
let mut data = Vec::new();
let mut reader = response.bytes_stream();
while let Some(chunk) = reader.next().await {
let chunk = chunk?;
data.extend_from_slice(&chunk);
if data.len() > max_size.to_usize().expect("max_size must fit in usize") {
return Err!(BadServerResponse("Response too large"));
}
}
Ok(data)
}
/// Reads the response body as text while enforcing a maximum size limit to
/// prevent memory exhaustion.
pub async fn limit_read_text(
response: reqwest::Response,
max_size: u64,
) -> crate::Result<String> {
let text = String::from_utf8(limit_read(response, max_size).await?)?;
Ok(text)
}
#[allow(async_fn_in_trait)]
pub trait LimitReadExt {
async fn limit_read(self, max_size: u64) -> crate::Result<Vec<u8>>;
async fn limit_read_text(self, max_size: u64) -> crate::Result<String>;
}
impl LimitReadExt for reqwest::Response {
async fn limit_read(self, max_size: u64) -> crate::Result<Vec<u8>> {
limit_read(self, max_size).await
}
async fn limit_read_text(self, max_size: u64) -> crate::Result<String> {
limit_read_text(self, max_size).await
}
}

View File

@@ -70,17 +70,15 @@ fn descriptor_cf_options(
);
}
let mut opts = opts
.get_options_from_string("{{arena_block_size=2097152;}}")
opts.set_options_from_string("{{arena_block_size=2097152;}}")
.map_err(map_err)?;
#[cfg(debug_assertions)]
let opts = opts
.get_options_from_string(
"{{paranoid_checks=true;paranoid_file_checks=true;force_consistency_checks=true;\
verify_sst_unique_id_in_manifest=true;}}",
)
.map_err(map_err)?;
opts.set_options_from_string(
"{{paranoid_checks=true;paranoid_file_checks=true;force_consistency_checks=true;\
verify_sst_unique_id_in_manifest=true;}}",
)
.map_err(map_err)?;
Ok(opts)
}
@@ -107,7 +105,7 @@ fn set_table_options(opts: &mut Options, desc: &Descriptor, cache: Option<&Cache
prepopulate,
);
let mut opts = opts.get_options_from_string(&string).map_err(map_err)?;
opts.set_options_from_string(&string).map_err(map_err)?;
opts.set_block_based_table_factory(&table);

View File

@@ -138,7 +138,7 @@ fn set_logging_defaults(opts: &mut Options, config: &Config) {
if config.rocksdb_log_stderr {
opts.set_stderr_logger(rocksdb_log_level, "rocksdb");
} else {
opts.set_callback_logger(rocksdb_log_level, handle_log);
opts.set_callback_logger(rocksdb_log_level, &handle_log);
}
}

Some files were not shown because too many files have changed in this diff Show More