Files
movim-rs/README.md
T
2026-11-07 15:29:40 +07:00

3.9 KiB

Movim (Rust edition)

A rewrite of the Movim XMPP web client backend in Rust, keeping Movim's frontend (CSS/JS/theme, in frontend/). The PHP daemon, widgets and templates were replaced by a single Rust server (tokio, axum, tokio-xmpp, sqlx with SQLite or PostgreSQL, minijinja). Scope: a Conversations-like chat client.

Features

1:1 chat, group chats (MUC, bookmarks, invitations, moderation, configuration), MAM history, carbons, receipts and chat markers, typing states, corrections, retractions, reactions, replies, link previews (OpenGraph cards, picture links shown inline), HTTP file upload, avatars and vCards, OMEMO (in-browser libsignal), 1:1 audio/video calls (Jingle + JMI), group audio/video calls in group chats (Muji, XEP-0272: a mesh of Jingle sessions), blocking, contact requests, search, account registration (XEP-0077), settings, Web Push, last seen (XEP-0319 idle), Client State Indication when no tab is open, and automatic XMPP reconnection (backoff up to 60s, rooms rejoined).

Run

cargo build --release
MOVIM_BIND=0.0.0.0:8080 MOVIM_DOMAIN=example.org ./target/release/movim

Put it behind a TLS reverse proxy (WebSocket on /ws/, same host).

Link previews are fetched by the server (only public addresses, every redirect checked) and cached for 30 days. Group calls are a mesh: every participant sends its streams to every other one, fine for a handful of people. They need a non-anonymous room (the default for group chats created by Movim).

Environment: MOVIM_BIND, MOVIM_ROOT, MOVIM_DATA_DIR, MOVIM_DATABASE_URL, MOVIM_DOMAIN, MOVIM_XMPP_WHITELIST, MOVIM_MAX_SESSIONS, MOVIM_DISABLE_REGISTRATION, MOVIM_LOCALE, MOVIM_SESSION_TIMEOUT_HOURS, MOVIM_MESSAGE_RETENTION_DAYS (delete cached messages older than this, e.g. the XMPP server's archive expiry), dev only: MOVIM_XMPP_PLAINTEXT=host:port, MOVIM_ALLOW_PRIVATE_URLS=1, MOVIM_DEBUG_XMPP=1.

Database

SQLite by default (data/movim.sqlite). For PostgreSQL, set MOVIM_DATABASE_URL=postgres://user:password@host/database; the tables are created at startup. To move an existing SQLite database, stop Movim, create an empty PostgreSQL database and run:

movim migrate-to-postgres postgres://user:password@host/database [--from sqlite:///path/movim.sqlite]

Without --from it copies the SQLite database Movim would use (MOVIM_DATABASE_URL or the one in MOVIM_DATA_DIR). Everything is copied in one transaction, ids included, and the command refuses a database that already has data. The SQLite file is left untouched.

Tests

cargo test runs the unit tests (MOVIM_TEST_POSTGRES_URL=postgres://… also runs them against PostgreSQL, in throwaway databases). tests/e2e/ holds end-to-end scripts that drive the server (and the real frontend in headless Chromium) against a local Prosody; see tests/e2e/README.md.

Frontend patches (vs upstream Movim)

  • widgets/Notif/notif.js: guard missing service worker registration.
  • widgets/ChatOmemo/chatomemo_storage.js: blind trust before verification (upstream trust check crashes: libsignal.util is undefined).
  • scripts/movim_jingles.js: the signaling of each call session runs through a promise queue (a content-add could arrive before the remote description was applied, early ICE candidates were dropped).
  • widgets/Config/config.js, widgets/Account/account.js: removed the blog configuration and gateways calls (not implemented here).
  • Widgets of the social features, the admin pages, AdHoc, SendTo, RoomsExplore and the sticker packs are not shipped. Their strings still in use moved to locales/extra.ini.

Not implemented

Movim social features (blogs, communities, stories), SFU conference calls (Movim's own extension; Muji group calls work), sticker packs/GIFs, ad-hoc commands, XEP-0198 stream resumption. Web Push has only been tested without a real HTTPS push service; Dictaphone/Snap/Draw go through the upload path but are untested.

License: AGPL-3.0 (same as Movim).