github matrix-construct/tuwunel v1.9.3
Release v1.9.3

5 hours ago

Tuwunel 1.9.3

September 25, 2026

New Features & Enhancements

  • Remote profiles can be refreshed on demand, graciously contributed by @x86pup (64e1226, b1157d8). !admin users refresh-profile <user> fetches a remote user's profile from their own server and drops every cached field that server no longer serves, such as a status the user has since cleared; local clients see the removal on their next sync. !admin users set-profile-key can now also clear one cached field of a remote user, and the value returns on the next ordinary lookup if their server still serves it. Neither command runs automatically, and both accept only remote users this server already knows. See docs/moderation.md.

Bug Fixes

  • Sliding Sync works again for users with old-format join records. In 1.9.2, a user holding a join record written by Conduit, conduwuit, another Conduit-lineage fork, or Tuwunel before 1.4.3.1, and not rewritten since, got a 500 on every Sliding Sync request, logged as u64 buffer underflow, and Element X sat in a restart loop. Legacy /sync failed the same way for clients that request profile_fields in their filter. Such a record now reads as the earliest join position. The condition is per record, not per database: a join event processed by Tuwunel 1.4.3.1 or later rewrites the record, and a display name or avatar change sends one into every joined room, so a user who had changed their profile on such a release was spared while a neighbor with a stable profile on the same database was not. Upgrading is the whole fix; nothing migrates and nobody needs to rejoin. @drrossum reported the restart loop in (#598), @Reaster0 confirmed it on a database migrated from a Conduit-lineage fork, and @scvalex hit it while testing the nixpkgs backport of 1.9.2; the fix is courtesy of @x86pup. Sincere apologies to everyone whose Element X could not get past a sync.

  • OIDC sessions carried over from a Conduit-lineage fork survive the upgrade again. The 1.9.2 migration that preserved imported token expiries stamped each such session with its long-past origin expiry, so its first request drew a soft logout (M_UNKNOWN_TOKEN) and deleted its token. With no OIDC provider here, the default, the client could neither refresh nor sign out cleanly; the reporter's Element X sat in a 401 loop for forty minutes before a password sign-in. Adoption now waits until this server runs its own OIDC provider (well_known.client plus an identity_provider or oidc_native_auth); until then those sessions keep their origin lifetime, and enabling a provider signs them out once, cleanly. On a server without a provider, a database that already ran 1.9.2 is repaired on its first 1.9.3 start for every migrated session not used since, and each restored device is logged. A session used under 1.9.2 was deleted at that request; neither this release nor a rollback to 1.9.1 brings it back. Do not roll back to 1.9.2 after that first 1.9.3 start: 1.9.2 would stamp the restored sessions again and delete each at its next request, and the repair does not run a second time, so those sessions are lost. 1.9.1 and earlier are safe to return to. Thanks to @Reaster0, who reported (#602) with a proxy-log timeline and a code-level diagnosis and proposed the repair for databases 1.9.2 had already stamped; shipped by @x86pup. Sincere apologies to everyone 1.9.2 signed out.

  • The Synapse-compatible admin join, POST /_synapse/admin/v1/join/{room_id_or_alias}, no longer answers 403 "cannot join a room that is not public" for a private room. When this server is in the room and its join rule would refuse the user uninvited, the requesting admin now invites them first, matching Synapse; a restricted room gets the invite only when the user is outside its allowed rooms. The admin must be joined there with power to invite, and the !admin users force-join console commands are unchanged. Thank you @arnolicious for reporting (#603); credit to @x86pup for the fix.

  • Debian and RPM upgrades skip the recursive ownership walk over a database directory already owned by tuwunel:tuwunel, unless a legacy database was just adopted. The server keeps running until the package restarts it, so a file RocksDB removed mid-walk could fail the chown; on Debian that aborted package configuration, while the RPM script ignored the failure. Tip of the hat to @x86pup (afc1116).

Don't miss a new tuwunel release

NewReleases is sending notifications on new releases.