Thoughts on Matrix Conduit


What for?

A few years ago I was looking for a messaging app that:

  1. Can be self-hosted (on an RPi)
  2. Can be maintained by "setting and forgetting"
  3. Offers audio/video calls
  4. Has a friendly front-end for family and friends

These four requirements ruled out apps such as Signal, Session, and Threema. I had wanted to try out Matrix Synapse but hadn't gotten around to it. When I stumbled upon Matrix Conduit (or just Conduit, the names surrounding the Matrix protocol are confusing because you have different server implementations AND front-ends, but my friends and family just call it Element :) it seemed like a straight forward messaging solution with audio/video call support.

A few problems came up, namely when using a TURN server for audio/video calls which I didn't set up and naively assumed that because calls worked on my local network that they would totally work outside the NAT. A year in, I also migrated the server to a different machine and that logged everyone out of their accounts which isn't great because most of the users hadn't backed up their private keys and so couldn't view old messages.

Setting up

Using the official Docker image works nicely, especially if having to migrate between machines. You can keep the database files in a neighbouring directory to the Docker compose file. Besides Docker, setting up a reverse proxy is strongly recommended, with Caddy being my pick. To get audio/video calls to work a TURN server is needed. I used coturn but between its and the Conduit config files, it took a while for me to get calls working. However, as long as you have open ports for your web server/reverse proxy (80 and 443 for TLS, both TCP) as well as TURN (3478 UDP) on your NAT and any firewall, you should be good to go.

Below are very stripped down configs for coturn, Matrix Conduit, and Caddy that enable all my required functionality. Note that many example configs online have more options specified which can be good, but trying out just this and seeing if it works reduces the amount of fiddling needed to troubleshoot if it doesn't. Assuming you have a domain and can set DNS records, you can share the domain between the coturn and Conduit server since they use different ports. As long as there is an A record that points to the NAT's public IP, any domain or subdomain can be used for the coturn server. You don't have to specify the url in the coturn config.

coturn config
listening-ip=0.0.0.0

user=turnUsername:turnPassword # CHANGE THIS
Matrix Conduit config
[global]
server_name = "mydomain.com" # CHANGE THIS

database_backend = "rocksdb"
database_path = "/var/lib/matrix-conduit/"
port = 6167

max_request_size = 100_000_000 # Max media upload size (~100MB)

allow_registration = true # Set to false after known users have registered

[global.media]
backend = "filesystem"
path = "/srv/matrix-media"

[global.media.directory_structure]
depth = 2
length = 2

[global.turn]
uris = ["turn:mydomain.com"]
username = "turnUsername" # CHANGE THESE (match with coturn config)
password = "turnPassword"
Caddyfile
# Match with server_name in conduit config
mydomain.com {
        reverse_proxy /_matrix/* 127.0.0.1:6167 # Match with port in conduit config
}