Skip to content

How to Quickly Set Up a Development Matrix Homeserver (with bonus Traefik routing)

tl;dr: use matrix-docker-ansible-deploy, you might be most interested in reading about the traefik aspect

What’s All This About?

I like Matrix for messaging / group chats. I like an open ecosystem, which gives people the choice of running their own services. Browsing the list of bridges listed on (a bridge connects another service — which might not itself be ‘open’ — to the Matrix universe) and one caught my eye: matrix-appservice-mumble. Mumble is a FOSS VOIP client/server which I’ve been using for gaming / chat voice comms with my friends for years, ever since we migrated off TeamSpeak. So the idea of having one talk to the other was worth exploring.

However, I’ve not tried out a bridge before, and as this one wasn’t part of the wonderful automated setup/maintenance playbook matrix-docker-ansible-deploy, I wanted to try it out on a non-live homeserver first. While my matrix server isn’t mission-critical in the sense that business would be severely affected by it going down; it is mission-important (definitely a real term!) in the sense that I would miss talking to a bunch of great people if mine went down.

How Do I Set A Development Homeserver Up With Minimal Fuss?

Just as a development environment lets you make potentially breaking changes without fear of affecting critical components, a ‘development’ homeserver lets you play with homeserver components such as bridges, bots and other ancillary services without affecting the homeserver you and other users might actually be using.

I used matrix-docker-ansible-deploy (MDAD for short) for quickly getting the dev homeserver set up. It’s an incredibly useful project, and it’s what I use for my ‘production’ homeserver too. I cannot recommend it highly enough.


  • a domain [strictly speaking this is optional, but it makes things much easier]
  • somewhere to host a homeserver, eg a VM
  • ten minutes or so to get these set up and run the ansible playbook

having a quick look at the MDAD prerequisites page too is a good idea. For the items above, I used a domain I have which isn’t yet being used for anything, and a QEMU VM on a proxmox host.*

* MDAD uses Docker, which can be used in a container, but it’s a bit more of a faff and that goes against the spirit of “get it set up quickly”

From there, I recommend following the first few parts of MDAD’s own setup guide:

  1. Set up DNS – I only added the required records and skipped the optional ones as I wasn’t using (eg Dimension)
  2. Get the playbook and then configure it – I already had the ansible playbook, and I added the dev server to my matrix_servers inventory; then the play can be run against a particular entry via eg: ansible-playbook -i inventory/hosts setup.yml --limit="matrix_servers[1]" --tags=setup-all
  3. You’re ready to go! Run the install

I was running this on a guest of a proxmox host on my own LAN, so the ports mentioned in MDAD’s prerequisites weren’t directly available- this caused certificate acquisition from LE to fail.

Setting Up a Homesever Behind Traefik

I already had web ports (80 & 443) forwarded to another Docker host, where web traffic is handled by traefik – which I’ve written about elsewhere. Forwarding the ports to the matrix homeserver host would break that, so I configured traefik to forward web traffic instead.

A file provider provides dynamic configuration for services you manually define, similar to what the Docker provider does for services running on Docker ‘automatically’.

My traefik.toml:

  filename = "/external.yml"
  watch = true

and then in external.toml we can define a provider which forwards to the matrix homeserver host. Importantly, if you forward HTTPS (eg an already existing websecure entrypoint), then traefik itself will attempt to handle encryption. We could have it do this, but having both traefik and the matrix homeserver handle TLS is couterproductive. Therefore we use a tcp router (ref), with a corresponding service entry which uses address instead of url. For example:

external.toml excerpt:

      service: matrix-service
      rule: HostSNI(``)
        passthrough: true
      service: element-service
      rule: HostSNI(``)
        passthrough: true

# ... lines elided ...

        - address:
        - address:

(hosts and IPs above are examples)

I also added some standard router/service entries for non-encrypted traffic, but I don’t think they’re needed; and a HTTP → HTTPS redirect might be more useful.

Re-running setup after traefik is in place let everything complete smoothly!†

It all works, and a new user can be added, bridges tried out, bots brought to life…

† Strangely, I re-ran MDAD setup prematurely, before I had fully sorted out traefik routing to the right host; and the LE cert registration somehow worked. I’m going to chalk that one up to luck!

Tell us what's on your mind