Matrix and Element: How Secure Is It, and How to Get Started
Most chat apps are a single company's service. Slack, Discord, WhatsApp and Telegram all work the same way: one company runs the servers, owns the account system, and decides what gets encrypted, what gets kept, and what happens to your history when the product changes direction.
Matrix works differently. It's an open protocol for chat, more like email than like an app. Anyone can run a server (a homeserver), those servers talk to each other (federation), and you can pick whatever client you like. Element is the best-known Matrix client. It's built by Element Creations Ltd, the company founded by the people who created Matrix and still the biggest contributor to it.
This post covers three things: how Matrix works, how secure it actually is (including the parts people tend to skip), and how to get started, either as a user on an existing server or by running your own.
If you want the broader list of security software I use, see Linux Security Tools. For storing the recovery key this post will tell you to create, see Managing SSH Keys, Passwords, and Dev Secrets on Linux.
TL;DR
- Matrix is a protocol, Element is a client. Your account lives on a homeserver (
@you:example.org), and you can talk to people on any other homeserver. - Private chats and DMs are end-to-end encrypted by default. The crypto (Olm and Megolm, implemented in the Rust library vodozemac) is well studied and has been audited, and it has had real bugs that were found and fixed in public.
- Metadata is the weak spot. Your homeserver, and every server that takes part in a room, can see who is in the room, who talked when, and room details like names and topics. Message content is encrypted. A lot of the rest isn't.
- Set up your recovery key and verify every device. Most "Unable to decrypt" problems come from skipping this. Element is also moving to only share keys with verified devices (MSC4153), so unverified sessions will stop being able to read new encrypted messages.
- Use Element X on your phone (the new, faster app) and Element Desktop or Element Web on your computer.
- Signal still leaks less metadata. Matrix wins on ownership: no phone number required, self-hosting, federation, large communities, and bridges to other networks.
- Self-hosting is very doable. Synapse is the full-featured reference server. Continuwuity and Tuwunel are lightweight Rust servers that run happily on a small VPS.
Part 1: How Matrix works
The pieces
| Piece | What it is |
|---|---|
| Homeserver | The server your account lives on, e.g. matrix.org or one you run yourself. It stores your account, your rooms, and your history. |
| User ID | @name:server, like an email address. @alice:matrix.org and @alice:example.com are different people. |
| Room | Every conversation is a room, including one-to-one DMs. Rooms have IDs (!abc123:server) and optional human-friendly aliases (#linux:example.com). |
| Space | A group of rooms, roughly a Discord "server" or a Slack workspace. |
| Federation | When users from different homeservers join a room, each of those servers keeps a full copy of that room and syncs with the others. No single server owns the room. |
| Client | The app you use: Element, Element X, FluffyChat, Cinny, Nheko, iamb, and many more. Any client works with any homeserver. |
| Bridge | A bot-like service that connects a Matrix room to another network (Signal, WhatsApp, Telegram, IRC, Slack, Discord) so messages pass both ways. |
Federation is both the selling point and the source of most of the trade-offs. Nobody can shut down "Matrix," and you can leave a server without losing the network. But a room's data is copied onto every server that has a member in it, so your privacy depends partly on servers you don't run.
Matrix 2.0
In late 2024 the Matrix project announced "Matrix 2.0", a set of changes aimed at making Matrix feel like a modern app instead of a hobby project:
- Sliding sync (simplified sliding sync): clients load only the rooms you're looking at, so apps open instantly even on large accounts. This is a big part of why Element X feels so much faster than the classic Element apps.
- Next-generation auth (OIDC): login and account management move to the Matrix Authentication Service (MAS), which uses the OpenID Connect standard. matrix.org switched its login over to MAS on 7 April 2025. In practice this means login happens on a web page run by your server, and that page can support things like single sign-on and passkeys.
- Native group VoIP (MatrixRTC / Element Call): encrypted group voice and video calls built into the protocol, using a LiveKit media server on the back end.
- Invisible crypto: making encryption "just work" by requiring devices to be verified and cleaning up the confusing warnings. More on that below.
Part 2: Security, the honest version
End-to-end encryption
Matrix uses two related protocols:
- Olm sets up an encrypted channel between two devices. It's an implementation of the Double Ratchet algorithm, the same design Signal uses.
- Megolm encrypts messages in a room. Each device that sends to a room creates a Megolm session and shares its key with every other device in the room over Olm. Megolm is cheaper for large groups, but it gives up some of the per-message forward secrecy that the Double Ratchet provides.
Both are implemented in vodozemac, a Rust library that replaced the old C/C++ libolm (now deprecated). Element X, and Element Web/Desktop through the Matrix Rust SDK crypto module, all use it.
What is encrypted when E2EE is on:
- Message text, images, files, voice messages
- Reactions and edits in newer clients, which send them as encrypted events too
- Encrypted group calls in Element Call
E2EE is on by default for DMs and private rooms in Element. Public rooms are usually left unencrypted on purpose. If anyone can join, encryption doesn't protect much, and it makes searching and reading history harder. You can turn encryption on for a room, but you can't turn it off again.
Devices, cross-signing, and the recovery key
This is the part that trips people up, so it's worth understanding.
Every app or browser you log in from is a separate device (Element also calls it a session) with its own keys. Room keys are shared device to device, so a brand new device starts out unable to read old encrypted messages until it gets those keys from somewhere.
There are two places it can get them:
- Key backup. Your room keys are stored on your homeserver, encrypted with a key only you hold. That key is unlocked with your recovery key (Element used to call it a "Security Key" or "Security Phrase"). The server stores the backup but can't read it.
- Another one of your devices, through verification.
Cross-signing ties your devices together. When you verify a new device, either by scanning a QR code or by comparing a set of emoji with an already-trusted device, or by entering your recovery key, that device gets signed with your identity, so everyone else's apps know it really is you and not a device the server quietly added.
That last point is the real security property. In Matrix, your homeserver controls your device list. A malicious or compromised server could add a fake device to your account to try to receive room keys. Cross-signing is what lets other users' clients tell your real devices apart from one the server invented.
"Unable to decrypt" messages almost always mean one of these:
- The device was never verified, so it never got the keys
- Key backup was never set up, so the keys were lost when you logged out of your last device
- The sender's device didn't have your new device yet when it sent the message
MSC4153: excluding insecure devices
For years Matrix clients warned you about unverified devices but still sent them keys. That was confusing ("red shield" warnings everywhere) and it was also weak security, since an unverified device could still read messages.
The spec has changed. MSC4153 (accepted in 2025) says clients should not send encrypted messages to devices that aren't cross-signed by their owner. In practice:
- If your device isn't verified, other people's messages to you won't be readable on that device.
- Devices that the server added without your signature stop getting keys, which closes the fake-device attack described above.
- Element has been prompting everyone to verify their devices ahead of the change. It's also hard on bots and bridges, because their devices need to be cross-signed as well.
Element first planned to switch this on by default in April 2026, then moved the date to October 2026 to give organisations and bridge/bot developers more time. Element Web also lets you turn it on early under Labs → Exclude insecure devices. Check the current release notes for your client to see where it stands. Either way, the advice is the same: verify every device you use now.
What is NOT encrypted: metadata
This is the most important limitation to understand. E2EE in Matrix protects what you said. Much of who, when, and where is still visible to your homeserver, and to every other homeserver that has members in the room:
- Room membership: who is in the room, and when they joined or left
- Who sent each event, and when (sender ID and timestamp)
- Room state: room name, topic, avatar, and power levels (who's a moderator) are not end-to-end encrypted
- Your account details: your IP addresses, which devices you have, when you're online, plus your email or phone number if you added one
- Read receipts and typing notifications, which are visible to the servers involved
- Your contact graph: which rooms and DMs you're in, which adds up to who you talk to
And because of federation, if your DM partner is on another server, both servers have that metadata. In a big public room, every server with a member in it does.
The Matrix team has been upfront about this. Removing metadata is a long-term research goal (P2P Matrix and similar experiments), not something you get today. If you need to hide who you talk to from the people running the servers, Matrix isn't the right tool yet.
The track record
Matrix is open source and widely used by governments, the military, and organisations like Mozilla and KDE. That's attracted serious attention from researchers, which is a good thing. A quick history:
- 2016: NCC Group audited the original Olm/Megolm implementation and found issues that were fixed.
- 2022: Researchers published "Practically-exploitable Cryptographic Vulnerabilities in Matrix" (the "Nebuchadnezzar" paper), which described attacks that relied on a malicious homeserver, including tricking clients into trusting attacker-controlled devices. These were fixed in the main clients, and they're part of why Matrix is now tightening device verification.
- 2022–2024: vodozemac was audited by Least Authority, and Olm/Megolm got a formal security analysis. Old
libolmwas deprecated in favour of vodozemac. - 2025: Two high-severity protocol bugs in state resolution (the algorithm servers use to agree on a room's state) were disclosed (CVE-2025-49090 and one other). They could let a malicious server cause "state resets" in rooms. The fix was a new room version 12 in Matrix spec 1.16 (August 2025), which means existing rooms need to be upgraded to get the fix. Synapse now creates new rooms as version 12 by default.
- February 2026: An independent cryptographer published a list of alleged weaknesses in vodozemac, the main one being that it didn't reject all-zero X25519 Diffie-Hellman outputs. Matrix's response agreed the check was missing but argued that, because device keys are signed, none of the issues were practically exploitable. It promised the check in a future release as defence in depth. The two sides still disagree about how serious the issues are. It's worth reading both.
My take: being open means problems get found and argued about in public, and they get fixed. That's a better position than a closed app where you have to take the vendor's word for it. Just keep your clients updated, and if you run rooms, upgrade old ones when your client offers.
Matrix vs Signal
People always ask this, so here's the short version:
| Signal | Matrix (Element) | |
|---|---|---|
| Message encryption | Signal Protocol, on everywhere | Olm/Megolm, on by default in DMs and private rooms |
| Metadata the server sees | Very little, by design (sealed sender, private contact discovery) | A lot: membership, timestamps, room state, contact graph |
| Account needs | A phone number (usernames hide it from other people) | Just a username, unless your server asks for an email |
| Who runs the server | Signal Foundation only | Anyone: matrix.org, a community, your company, you |
| Self-hosting | No | Yes |
| Large communities / public rooms | Groups up to 1,000 | Thousands of members, spaces, public rooms, moderation tools |
| Bridges to other networks | No | Yes (WhatsApp, Signal, Telegram, IRC, Slack, Discord…) |
| Ease of use | Very easy | Easier than it used to be. Device verification is still a learning curve |
Use Signal for private conversations between people where leaking as little metadata as possible matters most. Use Matrix when you want to own the infrastructure, don't want to tie your identity to a phone number, want community spaces (a Discord/Slack replacement), or need to bridge networks together. Plenty of people, me included, use both.
Part 3: Getting started as a user
Step 1: Pick a homeserver
Your homeserver is who you're trusting with your metadata, so pick it on purpose.
- matrix.org: run by the Matrix.org Foundation. It's the default in most clients and the easiest place to start, but it's large and busy, and its terms of service limit what it'll host.
- A community server: many free servers run by groups or individuals are listed at servers.joinmatrix.org. Look at who runs it, their privacy policy, and whether they've been around a while.
- Your own: see Part 4.
You can't move an account between servers yet (account portability is still being worked on), so if you think you'll eventually self-host, it's fine to start on matrix.org and make a new account later.
Step 2: Pick a client
Element X (phone) is the new mobile app, rewritten on the Matrix Rust SDK with sliding sync. It's much faster than the classic app and it's where Element is putting its effort. The old Element mobile app now shows a banner asking you to switch.
- iOS: App Store, "Element X"
- Android: Google Play or F-Droid (
io.element.android.x)
Element Desktop / Element Web (computer). Element X doesn't have a desktop version yet, so on a computer you use Element Desktop or app.element.io in a browser. Both work fine alongside Element X on your phone.
On Linux, the easiest install is Flatpak:
flatpak install flathub im.riot.Riot
flatpak run im.riot.Riot(im.riot.Riot is a leftover from when Element was called Riot. Note that the Flathub package is community maintained, not an official Element build.)
Or use Element's official apt repository on Debian/Ubuntu:
sudo apt install -y wget apt-transport-https
sudo wget -O /usr/share/keyrings/element-io-archive-keyring.gpg \
https://packages.element.io/debian/element-io-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/element-io-archive-keyring.gpg] https://packages.element.io/debian/ default main" \
| sudo tee /etc/apt/sources.list.d/element-io.list
sudo apt update
sudo apt install element-desktopOther clients worth knowing:
- FluffyChat: friendly cross-platform client (mobile, desktop, web), good for less technical friends and family
- Cinny: clean web client that looks a lot like Discord
- Nheko: native Qt desktop client, light on resources
- iamb: a Vim-style terminal client written in Rust. If you like CLI/TUI tools as much as I do, it's a fun way to live in Matrix from a terminal.
- gomuks: another terminal client, written in Go
Step 3: Set up your account properly (don't skip this)
- Create the account at your homeserver of choice. Use a strong, unique password from your password manager.
- Set up the recovery key as soon as Element offers it (Settings → Encryption, or Security & Privacy in older versions). Save it in your password manager. Without it, if you lose all your devices you lose your encrypted history.
- Verify every new device you log in on. Element X will ask you to verify with another device or with your recovery key when you sign in. Do it, every time.
- Review your sessions now and then (Settings → Sessions). Sign out anything you don't recognise or don't use, like old browsers or retired phones.
- Think about what's public. Your display name and avatar are visible to anyone who shares a room with you, and that information is copied to their servers.
- Optionally, verify the people you talk to most. Open their profile and verify them in person or over a call. After that, Element will warn you if their identity changes.
Step 4: Join rooms and spaces
- Use Explore rooms in Element to search your server's public room directory, or enter an alias like
#somecommunity:example.org. - To share a room or user with someone, use a matrix.to link (
https://matrix.to/#/#room:server). It works no matter which client the other person uses. - When you create a room, pick Private (invite only) with encryption on, unless you really want a public room.
Part 4: Running your own homeserver
Self-hosting is where Matrix really pays off: your account, your history, and your metadata live on hardware you control. Your server still federates with everyone else, so you aren't on an island.
Choosing a server
| Server | Language | Good for |
|---|---|---|
| Synapse | Python (with Rust parts) | The reference server, maintained by Element. Most complete and best supported (MAS, workers for scaling, Element Call). Needs more RAM, especially if you join big public rooms. |
| Continuwuity | Rust | A community-maintained fork of conduwuit (itself a fork of Conduit). Single binary, embedded database, very low resource use. Great for a personal or small-group server. |
| Tuwunel | Rust | Another actively maintained conduwuit fork aimed at small to medium servers. |
| Element Server Suite (ESS) Community | Helm chart | Element's packaged full stack (Synapse, MAS, Element Web, MatrixRTC) for Kubernetes/K3s. Worth a look if you already run Kubernetes. |
Dendrite (Go) is still around, but it's listed as beta and development has slowed down. The original conduwuit project is archived, so use one of its maintained forks.
The Rust servers have occasionally had compatibility problems with Synapse after upgrades (for example a 2026 Continuwuity release with an invite incompatibility that was fixed in a follow-up release), so read the release notes before upgrading.
What a minimal setup looks like
A domain and a small VPS or home server. Continuwuity runs fine on 1 GB of RAM for a few users.
A reverse proxy with TLS (Caddy, nginx, or Traefik) in front of the homeserver.
Delegation, so your user IDs can be
@you:example.comwhile the server runs atmatrix.example.com. Serve two small JSON files from your main domain:https://example.com/.well-known/matrix/server:json{ "m.server": "matrix.example.com:443" }https://example.com/.well-known/matrix/client:json{ "m.homeserver": { "base_url": "https://matrix.example.com" } }The homeserver itself. As a sketch, here's Continuwuity in Docker Compose. Check the current Continuwuity docs for the image name and config options before you use it. These things change between releases.
yamlservices: homeserver: image: forgejo.ellis.link/continuwuation/continuwuity:latest restart: unless-stopped ports: - "127.0.0.1:6167:6167" # only reachable by the reverse proxy volumes: - ./data:/var/lib/continuwuity environment: CONTINUWUITY_SERVER_NAME: example.com CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity CONTINUWUITY_ADDRESS: 0.0.0.0 CONTINUWUITY_PORT: 6167 CONTINUWUITY_ALLOW_REGISTRATION: "true" CONTINUWUITY_REGISTRATION_TOKEN: "change-me-to-a-long-random-string"Test federation with the Matrix Federation Tester once it's up.
Hardening your server
- Don't leave registration open. Open registration on a small server gets found by spammers fast. Use registration tokens or invite-only signups, or turn registration off after creating your accounts.
- Keep the server updated. Security fixes, like the 2025 state resolution fixes, only help if you install them.
- Back up the database and signing keys. If you lose the server's signing key, other servers won't trust it anymore. Keep backups encrypted and off the machine (see the backup section of my secrets post).
- Bind the homeserver to localhost and expose only the reverse proxy.
- Think before joining huge public rooms from a tiny server. They pull in a lot of state and can eat RAM and disk.
- Remember you're now the one holding the metadata for your users. Write a short privacy note for anyone you invite.
A quick checklist
For users:
- Recovery key created and stored in your password manager
- Every logged-in device verified (no "unverified session" warnings)
- Old sessions signed out
- Using Element X on mobile, an up-to-date Element Desktop/Web on the computer
- DMs and private rooms encrypted (the default, but check rooms you created long ago)
- You know what your homeserver can see, and you trust whoever runs it
For server admins:
- Registration closed or token-gated
- Homeserver behind a TLS reverse proxy, bound to localhost
- Federation tester passes
- Encrypted, off-machine backups of the database and signing keys
- Watching release notes and the Matrix security disclosures
Further reading
- Matrix specification: the protocol itself
- Matrix.org security disclosure policy and security blog posts
- "Exclude insecure devices" is coming: the MSC4153 announcement
- Analysis of reported issues in vodozemac: Matrix's response to the February 2026 report
- Practically-exploitable Cryptographic Vulnerabilities in Matrix: the 2022 research paper
- Privacy Guides: Real-Time Communication: an independent take on Signal, Matrix, and others
- Matrix homeserver list and client list
Matrix isn't magic. It encrypts your messages well and leaks more metadata than Signal. What it gives you that almost nothing else does is a chat network nobody can take away from you. Set up your recovery key, verify your devices, and choose your homeserver carefully, and it's a solid, private place to talk.

