Compare commits

...

39 Commits

Author SHA1 Message Date
timedout 2a4b9f9323 fix: Check are_all_blocked in server_filter_level 2026-06-24 20:13:17 +01:00
timedout 63a1a3d9ab feat: Advertise stable prefix in unstable features 2026-06-24 20:05:34 +01:00
timedout f19f5c71a5 chore(1875): Remove extra changelog entry 2026-06-24 19:13:35 +01:00
timedout b009ffd31c chore(1875): Add changelogs 2026-06-24 19:03:38 +01:00
timedout b6baf66399 feat: Support MSC4380 invite blocking
fix: Re-add silently dropped support for MSC4155
2026-06-24 18:59:49 +01:00
ginger 6dac46e1ad Update SECURITY.md 2026-06-24 13:00:27 +00:00
ginger 4d40e20fdd docs: Fix typo 2026-06-23 14:56:14 +00:00
Renovate Bot 3b455218f5 chore(deps): update rust crate itertools to 0.15.0 2026-06-23 13:53:25 +00:00
Renovate Bot de24fcbb8c chore(deps): update dependency cargo-bins/cargo-binstall to v1.20.1 2026-06-23 13:38:23 +00:00
Renovate Bot 2adb9a7941 chore(deps): update actions/checkout action to v7 2026-06-23 13:20:40 +00:00
Renovate Bot d81f4df61c chore(deps): update rust crate itertools to 0.15.0 2026-06-23 13:20:22 +00:00
Renovate Bot 6b259d15ee chore(deps): update rust-non-major 2026-06-23 13:20:10 +00:00
Renovate Bot eeef60d540 chore(deps): update github-actions-digest 2026-06-23 05:01:57 +00:00
Renovate Bot a01035e63a chore(deps): update github-actions-non-major to v43.234.0 2026-06-22 05:03:19 +00:00
stratself 52c1544e6f fix: Correct date in announcements 2026-06-21 02:36:32 +00:00
Jade Ellis ed38212391 fix(ci): Correct version regex in debian build 2026-06-21 01:03:14 +01:00
Jade 86fe98c90d chore: Admin announcement 2026-06-20 23:32:56 +00:00
Henry-Hiles 4078062331 fix: change the update-flake-hashes repo to work with the new rust.nix structure 2026-06-20 15:35:09 -04:00
Henry-Hiles 40935cf96a fix: use toolchain declared in rust-toolchain.toml for cross rust-std 2026-06-20 15:32:33 -04:00
Henry-Hiles 182c5a120e fix: add rocksdb as a flake package
This fixes the flake-hashes workflow.
2026-06-20 13:45:25 -04:00
Henry-Hiles 8e71ed7b63 fix: dynamically link rocksdb on dynamic nix builds
Fixes liburing error.
2026-06-20 13:19:35 -04:00
timedout 4696cbb751 fix: SEC12 2026-06-20 16:03:43 +01:00
timedout ebea06b687 fix: SEC11 2026-06-20 16:03:43 +01:00
timedout 62b58e1a6a fix: SEC16 2026-06-20 16:03:37 +01:00
Henry-Hiles 1ba90deeba chore: Change build workflows to run every week
Old behavior was to run every day, which is wasteful.
2026-06-19 22:58:32 -04:00
Henry-Hiles 71ed283141 chore: enable __structuredAttrs on build
This is a good practice for modern nix packages
2026-06-20 02:43:52 +00:00
Henry-Hiles a7ae7b2e75 fix: resolve review comment about Haswell CPUs 2026-06-20 02:43:52 +00:00
Henry-Hiles 0d45ae7e21 chore: more descriptive name for binary build step of workflow 2026-06-20 02:43:52 +00:00
Henry-Hiles 61e121ad5c feat: improve docs for building with nix 2026-06-20 02:43:52 +00:00
Henry-Hiles 31960beb75 fix: fix max-perf-static packages not statically linking 2026-06-20 02:43:52 +00:00
Henry-Hiles bdd9b6b50c chore: add changelog 2026-06-20 02:43:52 +00:00
Henry-Hiles 216033cf20 feat: add build-nix workflow 2026-06-20 02:43:52 +00:00
Henry-Hiles 95ddb1bbe5 feat: add max-perf package 2026-06-20 02:43:52 +00:00
Henry-Hiles 1ad4ca0f67 feat: add static binary build instructions to docs 2026-06-20 02:43:52 +00:00
Henry-Hiles 95790d8152 fix: don't do check on all builds
Checks can be done with `nix flake check`, no need to slow down build process with this.
2026-06-20 02:43:52 +00:00
Henry-Hiles 02c61b3840 fix: remove un-needed env vars that crane sets automatically 2026-06-20 02:43:52 +00:00
Henry-Hiles 6ee501ac69 feat: static builds using nix, including cross 2026-06-20 02:43:52 +00:00
spaetz 252ebb4642 CI: Remove the clang detection
tomfos.tr act-runner image removed the possibility to install the latest LLVM using an installer script, so let us also remove the detection and just live with the distro's clang image.
2026-06-19 11:23:53 +00:00
Renovate Bot 0fb95df7a5 chore(deps): update rust crate tower-http to 0.7.0 2026-06-18 05:03:03 +00:00
35 changed files with 436 additions and 153 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ runs:
- name: Install timelord-cli and git-warp-time
if: steps.check-binaries.outputs.need-install == 'true'
uses: https://github.com/taiki-e/install-action@15449e3094499af05d8d964a1c884208e4b8b595 # v2
uses: https://github.com/taiki-e/install-action@9e1e5806d4a4822de933115878265be9aaa786d9 # v2
with:
tool: git-warp-time,timelord-cli@3.0.1
+5 -16
View File
@@ -10,7 +10,7 @@ on:
- "v*.*.*"
workflow_dispatch:
schedule:
- cron: '30 0 * * *'
- cron: '30 0 * * 1'
jobs:
build:
@@ -41,20 +41,9 @@ jobs:
# 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
echo "Using clang-23 package for ${{ matrix.container }}"
echo "version=clang-23" >> $GITHUB_OUTPUT
else
echo "Using default clang package for ${{ matrix.container }}"
echo "version=clang" >> $GITHUB_OUTPUT
fi
- name: Checkout repository with full history
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
fetch-depth: 0
ref: ${{ github.ref_name }}
@@ -93,10 +82,10 @@ jobs:
# VERSION is the package version, COMPONENT is used in
# apt's repository config like a git repo branch
VERSION=$BASE_VERSION
if [[ ${{ forge.ref_name }} =~ ^v+[0-9]\.+[0-9]\.+[0-9]$ ]]; then
if [[ ${{ forge.ref_name }} =~ ^v+[0-9]+\.+[0-9]+\.+[0-9]+$ ]]; then
# Use the "stable" component for tagged semver releases
COMPONENT="stable"
elif [[ ${{ forge.ref_name }} =~ ^v+[0-9]\.+[0-9]\.+[0-9] ]]; then
elif [[ ${{ forge.ref_name }} =~ ^v+[0-9]+\.+[0-9]+\.+[0-9]+ ]]; then
# Use the "unstable" component for tagged semver pre-releases
COMPONENT="unstable"
else
@@ -130,7 +119,7 @@ jobs:
run: |
apt-get update -y
# Build dependencies for rocksdb
apt-get install -y liburing-dev ${{ steps.clang-version.outputs.version }}
apt-get install -y liburing-dev clang
- name: Run cargo-deb
id: cargo-deb
+2 -2
View File
@@ -16,7 +16,7 @@ on:
# - '.forgejo/workflows/build-fedora.yml'
workflow_dispatch:
schedule:
- cron: '30 0 * * *'
- cron: '30 0 * * 2'
jobs:
build:
@@ -30,7 +30,7 @@ jobs:
echo "Fedora version: $VERSION"
- name: Checkout repository with full history
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
fetch-depth: 0
ref: ${{ github.ref_name }}
+71
View File
@@ -0,0 +1,71 @@
name: Build / Static via Nix
concurrency:
group: "build-nix-${{ forge.ref }}"
cancel-in-progress: true
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
schedule:
- cron: '30 0 * * 3'
jobs:
build:
name: "Build ${{ matrix.filename }} Binary"
runs-on: ubuntu-latest
strategy:
matrix:
include:
- package: default-static-x86_64
filename: conduwuit-linux-static-amd64
- package: default-static-aarch64
filename: conduwuit-linux-static-arm64
- package: max-perf-static-aarch64
filename: conduwuit-linux-static-arm64-maxperf
- package: max-perf-haswell-static-x86_64
filename: conduwuit-haswell-linux-static-amd64-maxperf
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
- name: Install Lix
uses: https://github.com/samueldr/lix-gha-installer-action@a0fee77b2a98bb7c5c0ed7ae6d6ad4903dbdad0d
with:
extra_nix_config: experimental-features = nix-command flakes flake-self-attrs
- name: Build static binary
run: |
nix build .#${{ matrix.package }}
install -D result/bin/conduwuit /tmp/binaries/${{ matrix.filename }}
- name: Upload binary artifact
uses: forgejo/upload-artifact@v4
with:
name: ${{ matrix.filename }}
path: /tmp/binaries/${{ matrix.filename }}
release-binaries:
name: "Release Binaries"
runs-on: ubuntu-latest
needs:
- build
permissions:
contents: write
if: startsWith(github.ref, 'refs/tags/')
steps:
- name: Download binary artifacts
uses: forgejo/download-artifact@v4
with:
pattern: conduwuit*
path: binaries
merge-multiple: true
- name: Create Release and Upload
uses: https://github.com/softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3
with:
draft: true
files: binaries/*
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Sync repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
fetch-depth: 0
+2 -2
View File
@@ -41,7 +41,7 @@ jobs:
DOCKER_MIRROR_TOKEN: ${{ secrets.DOCKER_MIRROR_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
@@ -55,7 +55,7 @@ jobs:
# repositories: continuwuity
- name: Install regsync
uses: https://github.com/regclient/actions/regsync-installer@14f9d37db17b5dc41fefd1ffdd1af4b9e2490560 # main
uses: https://github.com/regclient/actions/regsync-installer@4b4db1dcc7dad75ad67a788a380f75a20cc8a040 # main
- name: Check what images need mirroring
run: |
+3 -3
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
@@ -48,7 +48,7 @@ jobs:
rust: ${{ steps.filter.outputs.rust }}
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
@@ -70,7 +70,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
+5 -5
View File
@@ -46,7 +46,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
- name: Prepare Docker build environment
@@ -100,7 +100,7 @@ jobs:
needs: build-release
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
- name: Create multi-platform manifest
@@ -133,7 +133,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
- name: Prepare max-perf Docker build environment
@@ -187,7 +187,7 @@ jobs:
needs: build-maxperf
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
- name: Create max-perf manifest
@@ -216,7 +216,7 @@ jobs:
path: binaries
merge-multiple: true
- name: Create Release and Upload
uses: https://github.com/softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3
uses: https://github.com/softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3
with:
draft: true
files: binaries/*
+2 -2
View File
@@ -43,11 +43,11 @@ jobs:
name: Renovate
runs-on: ubuntu-latest
container:
image: ghcr.io/renovatebot/renovate:43.222.1@sha256:b9af3f59f3f4d92b2c41e9f4ca3ffe92400503f20158d0bd67d07a3fdbe781d2
image: ghcr.io/renovatebot/renovate:43.234.0@sha256:bff111bfe347c559c615b658b28721eba5b7bb32a7b7901ea321336767209fe1
options: --tmpfs /tmp:exec
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
show-progress: false
+3 -3
View File
@@ -14,7 +14,7 @@ jobs:
update-flake-hashes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: true
token: ${{ secrets.FORGEJO_TOKEN }}
@@ -27,7 +27,7 @@ jobs:
- name: Get new toolchain hash
run: |
# Set the current sha256 to an empty hash to make `nix build` calculate a new one
awk '/fromToolchainFile *\{/{found=1; print; next} found && /sha256 =/{sub(/sha256 = .*/, "sha256 = lib.fakeSha256;"); found=0} 1' nix/rust.nix > temp.nix
awk '/fromToolchainName *\{/{found=1; print; next} found && /sha256 =/{sub(/sha256 = .*/, "sha256 = lib.fakeSha256;"); found=0} 1' nix/rust.nix > temp.nix
mv temp.nix nix/rust.nix
# Build continuwuity and filter for the new hash
@@ -39,7 +39,7 @@ jobs:
sed -i "s|lib.fakeSha256|\"$new_hash\"|" nix/rust.nix
echo "New hash:"
awk -F'"' '/fromToolchainFile/{found=1; next} found && /sha256 =/{print $2; found=0}' nix/rust.nix
awk -F'"' '/fromToolchainName/{found=1; next} found && /sha256 =/{print $2; found=0}' nix/rust.nix
echo "Expected new hash:"
cat new_toolchain_hash.txt
Generated
+47 -15
View File
@@ -560,9 +560,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
[[package]]
name = "bytesize"
@@ -889,7 +889,7 @@ dependencies = [
"http-body-util",
"hyper",
"ipaddress",
"itertools 0.14.0",
"itertools 0.15.0",
"lettre",
"log",
"rand 0.10.1",
@@ -942,7 +942,7 @@ dependencies = [
"http-body-util",
"hyper-util",
"ipaddress",
"itertools 0.14.0",
"itertools 0.15.0",
"lettre",
"libc",
"libloading 0.9.0",
@@ -1004,7 +1004,7 @@ name = "conduwuit_macros"
version = "26.6.0-alpha.1"
dependencies = [
"cargo_toml",
"itertools 0.14.0",
"itertools 0.15.0",
"proc-macro2",
"quote",
"syn",
@@ -1044,7 +1044,7 @@ dependencies = [
"serde_json",
"tokio",
"tower",
"tower-http",
"tower-http 0.7.0",
"tracing",
]
@@ -1070,7 +1070,7 @@ dependencies = [
"http",
"image",
"ipaddress",
"itertools 0.14.0",
"itertools 0.15.0",
"lettre",
"log",
"loole",
@@ -1116,7 +1116,7 @@ dependencies = [
"ruma",
"serde",
"thiserror",
"tower-http",
"tower-http 0.7.0",
"tower-sec-fetch",
"tracing",
"validator",
@@ -2641,6 +2641,15 @@ dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.18"
@@ -3945,9 +3954,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.45"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
dependencies = [
"proc-macro2",
]
@@ -4112,7 +4121,7 @@ dependencies = [
"tokio",
"tokio-rustls",
"tower",
"tower-http",
"tower-http 0.6.11",
"tower-service",
"url",
"wasm-bindgen",
@@ -4157,7 +4166,7 @@ dependencies = [
"tokio-rustls",
"tokio-util",
"tower",
"tower-http",
"tower-http 0.6.11",
"tower-service",
"url",
"wasm-bindgen",
@@ -5144,9 +5153,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.117"
version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
dependencies = [
"proc-macro2",
"quote",
@@ -5627,10 +5636,33 @@ dependencies = [
"tower",
"tower-layer",
"tower-service",
"tracing",
"url",
]
[[package]]
name = "tower-http"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233"
dependencies = [
"async-compression",
"bitflags",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-body-util",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
+2 -2
View File
@@ -124,7 +124,7 @@ default-features = false
features = ["util"]
[workspace.dependencies.tower-http]
version = "0.6.8"
version = "0.7.0"
default-features = false
features = [
"add-extension",
@@ -316,7 +316,7 @@ default-features = false
# Used to make working with iterators easier, was already a transitive depdendency
[workspace.dependencies.itertools]
version = "0.14.0"
version = "0.15.0"
# to parse user-friendly time durations in admin commands
#TODO: overlaps chrono?
+1
View File
@@ -23,6 +23,7 @@ ### Responsible Disclosure
1. **Contact members of the team directly** over E2EE private message.
- [@jade:ellis.link](https://matrix.to/#/@jade:ellis.link)
- [@nex:nexy7574.co.uk](https://matrix.to/#/@nex:nexy7574.co.uk)
- [@ginger:gingershaped.computer](https://matrix.to/#/@ginger:gingershaped.computer)
2. **Email the security team** at [security@continuwuity.org](mailto:security@continuwuity.org). This is not E2EE, so don't include sensitive details.
3. **Do not disclose the vulnerability publicly** until it has been addressed
4. **Provide detailed information** about the vulnerability, including:
+1
View File
@@ -0,0 +1 @@
Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you are on NixOS. Contributed by @Henry-Hiles (QuadRadical).
+1
View File
@@ -0,0 +1 @@
Added support for MSC4380 invite blocking, which has become part of the Matrix specification in v1.18. Contributed by @nex.
+1 -1
View File
@@ -50,7 +50,7 @@ EOF
# Developer tool versions
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
ENV BINSTALL_VERSION=1.20.0
ENV BINSTALL_VERSION=1.20.1
# renovate: datasource=github-releases depName=psastras/sbom-rs
ENV CARGO_SBOM_VERSION=0.9.1
# renovate: datasource=crate depName=lddtree
+1 -1
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.20.0
ENV BINSTALL_VERSION=1.20.1
# renovate: datasource=github-releases depName=psastras/sbom-rs
ENV CARGO_SBOM_VERSION=0.9.1
# renovate: datasource=crate depName=lddtree
+8 -2
View File
@@ -47,9 +47,15 @@ #### Performance-optimised builds
### Nix
Theres a Nix package defined in our flake, available for Linux and MacOS. Add continuwuity as an input to your flake, and use `inputs.continuwuity.packages.${system}.default` to get a working Continuwuity package.
If you wish to generate a static binary, you can do so using Nix: `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity#packageName`, where `packageName` is one of:
If you simply wish to generate a binary using Nix, you can run `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity` to generate a binary in `result/bin/conduwuit`.
- `default-static-x86_64`
- `default-static-aarch64`
- `max-perf-static-x86_64`
- `max-perf-haswell-static-x86_64`
- `max-perf-static-aarch64`
`max-perf` takes longer to build, but has more runtime optimizations. Haswell builds are optimized for modern CPUs.
### Compiling
+8 -1
View File
@@ -47,9 +47,16 @@ ### Available options
- `extraEnvironment`: Extra environment variables to pass to the Continuwuity server
- `package`: The Continuwuity package to use, defaults to `pkgs.matrix-continuwuity`
- You may want to override this to be from our flake, for faster updates and unstable versions:
```nix
package = inputs.continuwuity.packages.${pkgs.stdenv.hostPlatform.system}.default;
package = inputs.continuwuity.packages.${pkgs.stdenv.hostPlatform.system}.packageName;
```
Where `packageName` is one of:
- `default`
- `max-perf`: Takes longer to build, but has more runtime optimizations
- `max-perf-haswell`: Optimized for modern CPUs, don't use if your CPU is not Haswell or later.
- `admin.enable`: Whether to add the `conduwuit` binary to `PATH` for administration (enabled by default)
- `settings`: The Continuwuity configuration
@@ -6,10 +6,10 @@
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
},
{
"id": 13,
"id": 14,
"mention_room": true,
"date": "2026-05-08",
"message": "[v0.5.9](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.9) has been released, fixing a few low-severity federation-related vulnerabilities. It is recommended you read the changelog and update as soon as possible. There are no new features or other changes in this release, only related bugfixes. Deployments tracking the main branch should also update to the latest commit."
"date": "2026-06-20",
"message": "[v0.5.10](https://forgejo.ellis.link/continuwuation/continuwuity/releases/tag/v0.5.10) has been released. It is a security release, so we suggest you update as soon as possible. Don't forget to also join [our announcements room](https://matrix.to/#/!jIdNjSM5X-V5JVx2h2kAhUZIIQ08GyzPL55NFZAH1vM/%24K1ISNKIqfNiZzsNVCaTt2E7ZtNeP6Dsy6sbz9l3rO0A?via=ellis.link&via=gingershaped.computer&via=matrix.org)."
}
]
}
+1 -1
View File
@@ -10,7 +10,7 @@ ## Continuwuity issues
### Slow joins to rooms
Some slowness is to be expected if you're the first person on your homserver to join a room (which will
Some slowness is to be expected if you're the first person on your homeserver to join a room (which will
always be the case for single-user homeservers). In this situation, your homeserver has to verify the signatures of
all of the state events sent by other servers before your join. To make this process as fast as possible, make sure you have
multiple fast, trusted servers listed in `trusted_servers` in your configuration, and ensure
-14
View File
@@ -1,14 +0,0 @@
{ inputs, ... }:
{
perSystem =
{
pkgs,
self',
...
}:
{
_module.args.craneLib = (inputs.crane.mkLib pkgs).overrideToolchain (
pkgs: self'.packages.stable-toolchain
);
};
}
-1
View File
@@ -1,7 +1,6 @@
{
imports = [
./rust.nix
./crane.nix
./packages
./devshell.nix
./fmt.nix
+29 -28
View File
@@ -1,7 +1,6 @@
{
{ inputs, ... }: {
perSystem =
{
craneLib,
self',
lib,
pkgs,
@@ -9,34 +8,36 @@
}:
{
# basic nix shell containing all things necessary to build continuwuity in all flavors manually (on x86_64-linux)
devShells.default = craneLib.devShell {
packages = [
self'.packages.rocksdb
pkgs.nodejs
pkgs.pkg-config
]
++ lib.optionals pkgs.stdenv.isLinux [
pkgs.liburing
pkgs.rust-jemalloc-sys-unprefixed
];
env = {
LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.llvmPackages.libclang.lib ];
LD_LIBRARY_PATH = lib.makeLibraryPath (
[
pkgs.stdenv.cc.cc.lib
devShells.default =
(inputs.crane.mkLib pkgs).overrideToolchain (pkgs: self'.packages.stable-toolchain).devShell
{
packages = [
self'.packages.rocksdb
pkgs.nodejs
pkgs.pkg-config
]
++ lib.optionals pkgs.stdenv.isLinux [
pkgs.liburing
pkgs.jemalloc
]
);
}
// lib.optionalAttrs pkgs.stdenv.isLinux {
PKG_CONFIG_PATH = lib.makeSearchPath "lib/pkgconfig" [
pkgs.liburing.dev
];
};
};
pkgs.rust-jemalloc-sys-unprefixed
];
env = {
LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.llvmPackages.libclang.lib ];
LD_LIBRARY_PATH = lib.makeLibraryPath (
[
pkgs.stdenv.cc.cc.lib
]
++ lib.optionals pkgs.stdenv.isLinux [
pkgs.liburing
pkgs.jemalloc
]
);
}
// lib.optionalAttrs pkgs.stdenv.isLinux {
PKG_CONFIG_PATH = lib.makeSearchPath "lib/pkgconfig" [
pkgs.liburing.dev
];
};
};
};
}
+13 -5
View File
@@ -2,14 +2,14 @@
lib,
self,
stdenv,
liburing,
rocksdb,
craneLib,
pkg-config,
liburing,
rustPlatform,
cargoExtraArgs ? "",
rustflags ? "",
target_cpu ? null,
rocksdb,
profile ? "release",
}:
let
@@ -28,18 +28,26 @@ let
};
attrs = {
__structuredAttrs = true;
strictDeps = true;
inherit src;
nativeBuildInputs = [
pkg-config
rustPlatform.bindgenHook
];
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ liburing ];
env = {
ROCKSDB_INCLUDE_DIR = "${rocksdb}/include";
ROCKSDB_LIB_DIR = "${rocksdb}/lib";
CARGO_PROFILE = profile;
RUSTFLAGS = rustflags;
}
// (lib.optionalAttrs (rocksdb != null) {
ROCKSDB_INCLUDE_DIR = "${rocksdb}/include";
ROCKSDB_LIB_DIR = "${rocksdb}/lib";
})
// (lib.optionalAttrs (target_cpu != null) {
TARGET_CPU = target_cpu;
});
@@ -51,7 +59,7 @@ craneLib.buildPackage (
cargoArtifacts = craneLib.buildDepsOnly attrs;
# Needed to make continuwuity link to rocksdb
postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
postFixup = lib.optionalString (stdenv.hostPlatform.isLinux && rocksdb != null) ''
old_rpath="$(patchelf --print-rpath $out/bin/conduwuit)"
extra_rpath="${
lib.makeLibraryPath [
+74 -21
View File
@@ -1,4 +1,5 @@
{
inputs,
self,
...
}:
@@ -6,32 +7,84 @@
perSystem =
{
self',
lib,
pkgs,
inputs',
system,
craneLib,
mkToolchain,
...
}:
{
packages = {
rocksdb = pkgs.callPackage ./rocksdb.nix { };
default = pkgs.callPackage ./continuwuity.nix {
inherit self craneLib;
inherit (self'.packages) rocksdb;
# extra features via `cargoExtraArgs`
cargoExtraArgs = "-F http3";
# extra RUSTFLAGS via `rustflags`
# the stuff below is required for http3
rustflags = "--cfg reqwest_unstable";
};
# users may also override this with other cargo profiles to build for other feature sets
# for features configuration see `default` package which enables http3 by default
packages =
let
mkPackages =
pkgs:
let
fnx = inputs'.fenix.packages;
# example: different compilation profile and different target_cpu
max-perf-haswell = self'.packages.default.override {
# compiles explicitly for haswell arch cpus
target_cpu = "haswell";
# compiles slower but with more thorough optimizations
profile = "release-max-perf";
};
};
isStatic = pkgs.stdenv.hostPlatform.isMusl;
craneLib = (inputs.crane.mkLib pkgs).overrideToolchain (
_:
if isStatic then
fnx.combine [
self'.packages.stable-toolchain
(mkToolchain fnx.targets.${pkgs.stdenv.hostPlatform.config}).rust-std
]
else
self'.packages.stable-toolchain
);
default = pkgs.callPackage ./continuwuity.nix {
inherit self craneLib;
liburing = (if isStatic then pkgs.pkgsStatic else pkgs).liburing;
rocksdb = if isStatic then null else self'.packages.rocksdb;
# extra features via `cargoExtraArgs`
cargoExtraArgs = "-F http3";
# extra RUSTFLAGS via `rustflags`
# the stuff below is required for http3
rustflags = "--cfg reqwest_unstable";
};
# users may also override this with other cargo profiles to build for other feature sets
# for features configuration see `default` package which enables http3 by default
max-perf = default.override {
# compiles slower but with more thorough optimizations
profile = "release-max-perf";
};
max-perf-haswell = max-perf.override {
# compiles explicitly for haswell arch cpus
target_cpu = "haswell";
};
in
{
inherit default max-perf max-perf-haswell;
};
in
{
rocksdb = pkgs.callPackage ./rocksdb.nix { };
}
// (mkPackages pkgs)
// (lib.mapAttrs' (name: value: lib.nameValuePair "${name}-static-x86_64" value) (
mkPackages (
import inputs.nixpkgs {
localSystem = system;
crossSystem = "x86_64-unknown-linux-musl";
}
)
))
// (lib.mapAttrs' (name: value: lib.nameValuePair "${name}-static-aarch64" value) (
mkPackages (
import inputs.nixpkgs {
localSystem = system;
crossSystem = "aarch64-unknown-linux-musl";
}
)
));
};
}
+13 -9
View File
@@ -2,22 +2,26 @@
{
perSystem =
{
system,
lib,
inputs',
pkgs,
...
}:
let
mkToolchain =
target:
target.fromToolchainName {
name = (lib.importTOML "${inputs.self}/rust-toolchain.toml").toolchain.channel;
sha256 = "sha256-mvUGEOHYJpn3ikC5hckneuGixaC+yGrkMM/liDIDgoU=";
};
in
{
_module.args = { inherit mkToolchain; };
packages =
let
fnx = inputs.fenix.packages.${system};
stable-toolchain = fnx.fromToolchainFile {
file = inputs.self + "/rust-toolchain.toml";
# See also `rust-toolchain.toml`
sha256 = "sha256-mvUGEOHYJpn3ikC5hckneuGixaC+yGrkMM/liDIDgoU=";
};
fnx = inputs'.fenix.packages;
stable-toolchain = (mkToolchain fnx).toolchain;
in
{
inherit stable-toolchain;
+4
View File
@@ -87,6 +87,10 @@ pub(crate) async fn handle_login(
return Err!(Request(InvalidParam("User ID does not belong to this homeserver")));
}
if services.users.is_deactivated(&user_id).await? {
return Err!(Request(UserDeactivated("This account has been deactivated.")));
}
if services.users.is_locked(&user_id).await? {
return Err!(Request(UserLocked("This account has been locked.")));
}
+6
View File
@@ -162,6 +162,9 @@ async fn verify<B: AsRef<[u8]> + Sync>(
query: AuthQueryParams,
route: TypeId,
) -> Result<Self::Identity> {
if output.is_empty() {
return Err!(Request(Unauthorized("Missing access token.")));
}
if let Ok((sender_user, sender_device)) = services.users.find_from_token(&output).await {
// Locked users can only use /logout and /logout/all
if services
@@ -259,6 +262,9 @@ async fn verify<B: AsRef<[u8]> + Sync>(
_query: AuthQueryParams,
_route: TypeId,
) -> Result<Self::Identity> {
if output.is_empty() {
return Err!(Request(Unauthorized("Missing access token.")));
}
let Ok(appservice_info) = services.appservice.find_from_token(&output).await else {
return Err!(Request(Unauthorized("Invalid appservice token.")));
};
+7
View File
@@ -676,6 +676,13 @@ async fn handle_edu_direct_to_device(
messages
.into_iter()
.stream()
.broad_filter_map(|(target_user_id, map)| async move {
services
.users
.is_active_local(&target_user_id)
.await
.then_some((target_user_id, map))
})
.for_each_concurrent(automatic_width(), |(target_user_id, map)| {
handle_edu_direct_to_device_user(services, target_user_id, sender, &ev_type, map)
})
+1
View File
@@ -44,5 +44,6 @@ pub fn unstable_features() -> BTreeMap<String, bool> {
("uk.timedout.msc4323".to_owned(), true), /* agnostic suspend (https://github.com/matrix-org/matrix-spec-proposals/pull/4323) */
("org.matrix.msc4155".to_owned(), true), /* invite filtering (https://github.com/matrix-org/matrix-spec-proposals/pull/4155) */
("computer.gingershaped.msc4466".to_owned(), true), /* profile change propagation (https://github.com/matrix-org/matrix-spec-proposals/pull/4466) */
("org.matrix.msc4380.stable".to_owned(), true),
])
}
+96 -5
View File
@@ -1,8 +1,13 @@
//! Types for invite filtering ([MSC4155]).
//! Types for invite filtering ([MSC4155]) and
//! invite blocking ([invite-blocking]).
//!
//! MSC4155: https://github.com/matrix-org/matrix-spec-proposals/pull/4155
//! invite-blocking: https://spec.matrix.org/v1.18/client-server-api/#invite-permission
use ruma::{ServerName, UserId, exports::ruma_macros::EventContent};
use ruma::{
ServerName, UserId, events::invite_permission_config::InvitePermissionAction,
exports::ruma_macros::EventContent,
};
use serde::{Deserialize, Serialize};
use wildmatch::WildMatch;
@@ -25,6 +30,21 @@ pub struct InvitePermissionConfigEventContent {
#[serde(default = "ruma::serde::default_true")]
pub enabled: bool,
/// The default action chosen by the user that the homeserver should perform
/// automatically when receiving an invitation for this account.
///
/// A missing, invalid or unsupported value means that the user wants to
/// receive invites as normal. Other parts of the specification might still
/// have effects on invites, like [ignoring users].
///
/// [ignoring users]: https://spec.matrix.org/v1.18/client-server-api/#ignoring-users
#[serde(
default,
deserialize_with = "ruma::serde::default_on_error",
skip_serializing_if = "Option::is_none"
)]
pub default_action: Option<InvitePermissionAction>,
/// A list of globs matching users which are allowed to send an invite.
/// Entries in this list supersede entries in the ignored and blocked lists.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
@@ -77,6 +97,7 @@ pub fn new(
) -> Self {
Self {
enabled,
default_action: None,
allowed_users,
ignored_users,
blocked_users,
@@ -86,12 +107,21 @@ pub fn new(
}
}
/// Returns true if the default action is configured and set to block.
fn are_all_blocked(&self) -> bool {
self.default_action
.clone()
.is_some_and(|action| action == InvitePermissionAction::Block)
}
/// Test the filters against a user id. This function will check both the
/// user rules _and_ the server rules.
#[must_use]
#[allow(clippy::if_same_then_else)]
pub fn user_filter_level(&self, user: &UserId) -> FilterLevel {
if !self.enabled {
if self.are_all_blocked() {
FilterLevel::Block
} else if !self.enabled {
FilterLevel::Allow
} else if Self::matches(&self.allowed_users, user.as_str()) {
FilterLevel::Allow
@@ -107,7 +137,9 @@ pub fn user_filter_level(&self, user: &UserId) -> FilterLevel {
/// Test the filters against a server name. Port numbers are ignored.
#[must_use]
pub fn server_filter_level(&self, server: &ServerName) -> FilterLevel {
if !self.enabled {
if self.are_all_blocked() {
FilterLevel::Block
} else if !self.enabled {
FilterLevel::Allow
} else {
let server = server.host();
@@ -132,7 +164,12 @@ fn matches(a: &[String], s: &str) -> bool {
#[cfg(test)]
mod tests {
use ruma::{ServerName, UserId, events::GlobalAccountDataEvent};
use assign::assign;
use ruma::{
ServerName, UserId,
events::{GlobalAccountDataEvent, invite_permission_config::InvitePermissionAction},
user_id,
};
use serde_json::{from_value as from_json_value, json};
use crate::invite_permission_config::{FilterLevel, InvitePermissionConfigEventContent};
@@ -268,4 +305,58 @@ fn only_goodguys_and_ignore_reallybadguys() {
FilterLevel::Ignore
);
}
#[test]
fn v118_blocking_enabled_blocks_all() {
let event = assign!(
InvitePermissionConfigEventContent::default(),
{ default_action: Some(InvitePermissionAction::Block) }
);
let fixtures = [
user_id!("@alice:goodguys.org"),
user_id!("@alice:goodguys.org:8080"),
user_id!("@bob:bar.com"),
user_id!("@bob:Bar.com"),
user_id!("@kevin:reallybadguys.org"),
];
assert!(
fixtures
.iter()
.all(|f| event.user_filter_level(f) == FilterLevel::Block)
);
}
#[test]
fn v118_blocking_enabled_is_uninfluenced_by_msc4155() {
let toggled = InvitePermissionConfigEventContent {
enabled: false,
default_action: Some(InvitePermissionAction::Block),
..Default::default()
};
let only_goodguys = InvitePermissionConfigEventContent {
enabled: true,
default_action: Some(InvitePermissionAction::Block),
allowed_servers: vec!["goodguys.org".to_owned()],
ignored_servers: vec!["reallybadguys.org".to_owned()],
blocked_servers: vec!["*".to_owned()],
..Default::default()
};
let fixtures = [
user_id!("@alice:goodguys.org"),
user_id!("@alice:goodguys.org:8080"),
user_id!("@bob:bar.com"),
user_id!("@bob:Bar.com"),
user_id!("@kevin:reallybadguys.org"),
];
assert!(
fixtures
.iter()
.all(|f| toggled.user_filter_level(f) == FilterLevel::Block)
);
assert!(
fixtures
.iter()
.all(|f| only_goodguys.user_filter_level(f) == FilterLevel::Block)
);
}
}
+1 -1
View File
@@ -423,7 +423,7 @@ pub fn url_preview_allowed(&self, url: &Url) -> bool {
url_preview_domain_explicit_denylist (check 1/3)",
&root_domain
);
return true;
return false;
}
if allowlist_domain_explicit.contains(&root_domain.to_owned()) {
+22 -7
View File
@@ -164,13 +164,27 @@ pub async fn invite_filter_level(
if self.user_is_ignored(sender_user, recipient_user).await {
FilterLevel::Ignore
} else {
self.services
.account_data
.get_global(recipient_user, GlobalAccountDataEventType::InvitePermissionConfig)
.await
.map_or(FilterLevel::Allow, |config: InvitePermissionConfigEvent| {
config.content.user_filter_level(sender_user)
})
let (stable, unstable) = tokio::join!(
self.services
.account_data
.get_global::<InvitePermissionConfigEvent>(
recipient_user,
GlobalAccountDataEventType::InvitePermissionConfig
),
self.services
.account_data
.get_global::<InvitePermissionConfigEvent>(
recipient_user,
"org.matrix.msc4155.invite_permission_config".into()
) // TODO: MSC4155 probably needs upstreaming to ruma at some point
);
if stable.is_err() && unstable.is_err() {
return FilterLevel::Allow;
}
stable
.unwrap_or_else(|_| unstable.unwrap())
.content
.user_filter_level(sender_user)
}
}
@@ -338,6 +352,7 @@ pub async fn count(&self) -> usize { self.db.userid_password.count().await }
/// Find out which user an access token belongs to.
pub async fn find_from_token(&self, token: &str) -> Result<(OwnedUserId, OwnedDeviceId)> {
assert!(!token.is_empty(), "Empty access token");
self.db.token_userdeviceid.get(token).await.deserialized()
}