February 28, 2021

Dockerized Synapse (Matrix Home Server)

Yesterday I played a bit with Synapse, the reference implementation of a Matrix homeserver. Matrix is a federate chat protocol that features end-to-end encryption and does not require a phone number. As it is federated, everyone can run their own server but still talk to users registered to other servers. So, in my eyes, Matrix should be preferred over Signal or comparable applications.

The installation would actually be simple if the documentation were better. Unfortunately, you have to dig through various blogs, forum posts, and also the official documentation as the project is quite new and apparently configuration differs between older and recent versions quite much…

I figured out the following configuration to work - maybe it is helpful for someone:

Step 0: DNS

You need a domain. Let’s call it domain.tld. In your DNS settings, create a CNAME record called matrix.domain.tld. After installing Synapse, your Matrix IDs have the following format: @name:domain.tld (not @name:matrix.domain.tld).

Step 1: Persistent Configuration

Run the following command

docker run -it --rm \
    -v "/path/to/some/place/data:/data" \
    -e SYNAPSE_SERVER_NAME=domain.tld \
    matrixdotorg/synapse:latest generate

In /path/to/some/place you’ll find some configuration files, keying material, and a TinySQL database. For me, the configuration file was okay and didn’t need any changes.

Step 2: docker-compose

Create following docker-compose.yml file in /path/to/some/place:

version: '3'

  container_name: synapse
  image: matrixdotorg/synapse:latest
  restart: always
      - /path/to/some/place/data:/data
     - 8008:8008

As always, docker-compose up -d will run the beast.

Step 3: Create Users

docker exec -it synapse /bin/bash into the running container. Here you execute register_new_matrix_user -c /data/homeserver.yaml Follow the instructions on screen.

Step 4: Reverse Proxy and SSL

If you use nginx, a reverse proxy configuration might look like this:

server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    listen 8448 ssl http2 default_server;
    listen [::]:8448 ssl http2 default_server;

    server_name matrix.domain.tld;

    location ~* ^(\/_matrix|\/_synapse\/client) {
        proxy_pass http://localhost:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        client_max_body_size 50M;

    location /.well-known/matrix/client {
        return 200 '{"m.homeserver": {"base_url": "https://matrix.domain.tld"}}';
        default_type application/json;
        add_header Access-Control-Allow-Origin *;

    ssl_certificate /etc/letsencrypt/live/matrix.domain.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/matrix.domain.tld/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

Step 5: Testing

If everything worked according to plan, you should be able to do the following things:

  • Open https://federationtester.matrix.org and enter your domain. It should print out “success”. (Obviously.)
  • Open https://app.element.io/#/welcome or install Element on your local machine. Element is a Matrix client. Enter your homeserver’s URL and your ID, things should connect. If you know the ID of some other user, invite them and you should be able to chat.

© ho1ger 2015 - 2021