Security & privacy

What's protected, what isn't, and where the sharp edges are. Written to be useful rather than reassuring.

The one that matters most

Messages are not end-to-end encrypted. They are stored as plain text in your database and on your Matrix homeserver. Anyone with administrator access to that machine can read every message ever sent.

For a self-hosted instance that's usually one person — you — which is the whole point of running it yourself. It's a categorically different situation from a company holding your messages on its servers.

But it is not the same as Signal, and it shouldn't be described as private in the way Signal is private. If you're running an instance for other people, they deserve to know this before they type anything into it. If someone else is running the instance you're on, they can read your messages.

End-to-end encryption via Olm/Megolm is the next major phase. It isn't built yet, and claiming otherwise would be the kind of thing this project exists to avoid.

What is protected

AreaHow
Passwords scrypt hashes. Never stored or logged in plaintext.
Sessions Signed JWT in an httpOnly, SameSite=Lax cookie. JavaScript on the page can't read it.
Brute force Login attempts rate-limited per IP and email — ten per fifteen minutes.
Matrix tokens Held server-side only. The browser never receives one.
Every read and write Membership and role checked server-side. The client's opinion about what it's allowed to do is never trusted.
File downloads Streamed through the app with membership checks, not from a public IPFS gateway. Content identifiers don't leak outside the channel.
Homeserver registration Gated behind a generated token, so your Matrix server isn't an open signup target.
Traffic in transit HTTPS whenever you use a public address. Between services, traffic stays on loopback or a private container network.

What listens where

Only two ports are reachable from outside the machine. Everything else is bound to loopback deliberately.

PortReachable fromWhat
3000your networkthe app
4001the internetIPFS peering
6167 / 8008loopback onlyMatrix homeserver
5001loopback onlyIPFS admin API
5432loopback onlyPostgreSQL
Why 5001 matters The IPFS API is an unauthenticated admin socket — anyone who can reach it controls the node completely. It was briefly published to the host in an earlier version of the compose file. It isn't now, and it shouldn't be in any deployment you build.

Federation is off by default

Your homeserver talks to no other Matrix server until you set MATRIX_ALLOW_FEDERATION=true. Turning it on is a real decision: it means other homeservers can reach yours, your users can join rooms elsewhere, and your server name becomes publicly meaningful.

Federation is genuinely valuable — it's much of why Matrix is worth building on. It just shouldn't happen by accident.

What you're responsible for

Self-hosting means the security boundary is yours. Concretely:

Reporting a vulnerability

Please don't open a public issue for a security bug. Email [email protected] with what you found and how to reproduce it. You'll get an acknowledgement, and credit in the changelog if you want it.

This is alpha software that has not been independently audited. It's written carefully and reviewed honestly, but those aren't the same thing as an audit, and it would be wrong to imply otherwise.