Why host your own Matrix server
Classic team messaging tools — Slack, Teams, and even self-hosted alternatives — share a limit: you can only talk with members of the same server. Matrix reverses this. It is a FEDERATED protocol: your server talks to all other Matrix servers in the world, exactly like an email address reaches any other domain. Your users keep an identity tied to you (@alice:your-domain.com) while chatting with people hosted elsewhere. Add to this end-to-end encryption, per-room: even you, as server admin, cannot read a message in an encrypted room. That is what sets Matrix apart from simply self-hosted messaging — sovereignty rests not on trust in the host, but on cryptography.
What you gain with a self-hosted Matrix server
- Federation: your users reach those on any other Matrix server, without extra accounts.
- End-to-end encryption per room, independent of trust in the host.
- Identifiers tied to your domain name, becoming a lasting address.
- Self-hosted Element Web: the interface stays under your control, without depending on app.element.io.
- Official Element apps on mobile, desktop and web — all pointed at your server.
- History and files stored on your machine, with no imposed retention limit.
- Bridges to other networks (Telegram, Signal, IRC, XMPP…) are possible.
- No advertising collection or profiling: metadata stays within your perimeter.
Self-hosted Element vs. app.element.io: the concrete difference
Element Web is an open source web application — you can host it on your own domain instead of using app.element.io. This choice is often overlooked, but it matters. When your users open app.element.io, their browser loads JavaScript from Element HQ's servers: this does not affect message confidentiality (encryption stays local), but it creates an external dependency.
Hosting Element Web yourself — typically behind chat.your-domain.com — removes this dependency. You control the deployed version, you can customize config.json so the interface is pre-configured to your homeserver, and your users have a single URL to remember.
Important: Element Web reads config.<domain>.json BEFORE config.json. If your configuration is not served correctly, the interface displays perfectly — and connects your users to the public server instead of yours. Verify both files respond with your configuration before inviting users.
The point to understand BEFORE installing: the domain name
This is the peculiarity of Matrix, and the most costly source of error. The server_name of your server — your domain name — is not a display setting: it is written INTO the identity of every object the server produces. Every user identifier (@alice:your-domain.com), every room identifier, every signed event contains it. Changing it after the fact is not possible: you must start from a blank server and recreate accounts. Choose the definitive subdomain at installation time, and attach it when you install the application — not after. On ServOrbit, the installation deliberately refuses to start if no domain is attached: better an immediate, clear failure than a server you will have to redo once accounts are created.
Hardware requirements
The full stack — Synapse, PostgreSQL, Element Web and reverse proxy — consumes around 300 MB at rest, measured on a fresh installation. A VPS with 2 GB RAM and 2 vCPUs is therefore more than adequate for a team, an association or a family.
Consumption depends mostly on PUBLIC rooms you join: Synapse retains the history and state of every federated room, and joining a few large community rooms can grow the database by several gigabytes. For that use case, target 4 GB RAM and monitor disk space.
PostgreSQL is essential — Synapse accepts SQLite, but does not recommend it beyond a test server. Also plan for a valid TLS certificate: without HTTPS, federation and mobile apps refuse to connect.
Deploy Matrix with Docker, PostgreSQL and Element
Choose and point your domain
Decide on the definitive subdomain (for example
matrix.your-domain.com) and point it at your VPS with an A record. This name will become the server's identity. Add a second subdomain for Element Web if you want to host it separately (chat.your-domain.com). Both A records must be active before starting the container.Generate the configuration and signing key
The first start of the Synapse image generates
homeserver.yamland most importantly the server's SIGNING KEY, which authenticates its events to other servers. Back it up: losing it is equivalent to losing the server's identity on the federated network. Also keephomeserver.yamlin your backup system — it contains shared secrets between components.Switch the database to PostgreSQL
The image can only generate an SQLite configuration. Add a file in
conf.d/that redefines thedatabaseblock for PostgreSQL — Synapse reads multiple--config-pathand repeated keys override earlier ones. Create the database withCcollation: Synapse refuses to start on a database with different collation, and this choice cannot be changed after creation.Place a reverse proxy in front
Serve Element Web at the root of
chat.your-domain.comand the Matrix API under/_matrixand/_synapse/clientonmatrix.your-domain.com, behind a TLS certificate per domain. Properly relayUpgradeandConnectionheaders: Matrix maintains long connections (WebSocket), otherwise real-time does not work. Also increaseclient_max_body_sizeto at least 50 MB for file transfers.Publish the .well-known delegation
Expose
/.well-known/matrix/serverand/.well-known/matrix/clienton your root domain. This allows other servers and mobile apps to find your homeserver without manual configuration. Then verify on federationtester.matrix.org: unverified federation can silently block external invitations.Configure Element Web on YOUR server
Create a
config.jsonpointingdefault_server_configat your homeserver. Element also readsconfig.<domain>.jsonfirst: serve both via your reverse proxy. Test by opening the interface in a private tab — no cookie or session — and verify the login screen offers your domain by default, not matrix.org.Create the first admin account
Synapse creates no account on its own and registrations must remain closed. Create the admin account with
register_new_matrix_user, then log in athttps://chat.your-domain.com. On ServOrbit, thisadminaccount is created automatically on first start and its generated password is readable in your client area.
Administering Synapse after installation
Synapse exposes an administration API at /_synapse/admin/v1 — reserved for accounts marked admin. Via this API, you can deactivate an account, purge room history, force logout of all devices for a user, or consult federation statistics.
Synapse Admin (open source web interface, deployable as a separate container) uses this same API and offers a graphical view: user list, rooms, registered devices and database size per room. Useful for spotting a federated room that is growing the database by several gigabytes.
For updates, Synapse publishes its images on ghcr.io/element-hq/synapse. Check release notes before each major update: some database migrations are irreversible, and Synapse explicitly documents minimum required versions to move between branches.
History purge and disk space management
A federated server accumulates the history of all joined rooms — including large public rooms. Without regular purging, the PostgreSQL database can reach tens of gigabytes within months.
Synapse provides two levers. History purge via the admin API (POST /_synapse/admin/v1/purge_history) deletes events prior to a date in a given room — without affecting other rooms or messages you have not yet read. The synapse_auto_compressor command then compresses state_groups groups in PostgreSQL, which can halve database size on a server active for several months.
Also enable gc_thresholds in homeserver.yaml to control Synapse's Python garbage collector: on an active federated server, the default GC is rarely optimal for resident memory.
Bridges: connecting Matrix to Telegram, Signal and WhatsApp
One of Matrix's distinctive advantages is its ecosystem of bridges — services that link your homeserver to other networks. Matterbridge, Beeper or the Matrix project's official bridges relay messages between a Matrix room and a Telegram group, a Slack channel or a WhatsApp conversation.
Each bridge deploys as an additional service (an extra container in your compose.yml) and registers with Synapse via a registration.yaml file. The bridge receives a portion of the identifier namespace (@telegram_*:your-domain.com) and translates messages in both directions.
For Telegram, mautrix-telegram is the most maintained bridge. For Signal, mautrix-signal. Both bridges require an account on the target network — no reading without an account. WhatsApp and Meta Messenger go through mautrix-meta, which uses the unofficial API: its functioning depends on Meta's decisions and may be interrupted.
Matrix / Synapse vs. self-hosted messaging alternatives
Scroll the table
| Criterion | Matrix + Synapse | Mattermost | Rocket.Chat |
|---|---|---|---|
| Inter-server federation | Yes, native | No | No |
| End-to-end encryption | Yes, per room | Optional (beta) | No (plaintext in transit) |
| Bridges to other networks | Yes (Telegram, Signal, Slack…) | Partial (Slack) | Partial |
| RAM consumption (idle) | ~300 MB (full stack) | ~400 MB | ~500 MB |
| Self-hostable web client | Element Web (open source) | Yes (included) | Yes (included) |
| Mobile clients | Element iOS/Android | Native iOS/Android | Native iOS/Android |
Close registrations, and keep them closed
A Matrix server with open registrations is quickly discovered and used as a relay by third parties: spam accounts, unwanted rooms, and a database that grows without your doing anything. Keep enable_registration at false and create accounts manually, or use external authentication (SSO, OIDC). If you open registrations, require at minimum an email verification and enable registration_requires_token.
Official documentation
For advanced configuration — workers, bridges, authentication modules, history purge — refer to the official Synapse documentation. This guide covers deployment on VPS; the upstream docs remain the reference for fine-tuned settings and major version upgrades.