Tech, web, programming, home automation, networking, and geeky blog.

13 Jun 2020

Setting up Synapse Matrix homeserver on a Raspberry Pi in Docker with Caddy and Cloudflare

Matrix is a decentralized open source communication tool. This can be self hosted using Synapse. This can easily be setup on Docker with the official Synapse image but this is not ARM compatible for Raspberry Pi, luckily black0 has made a multi-architecture Synapse image availale. The documentation from the Synapse repo can be followed, just using the black0/synapse image rather than the matrixdotorg/synapse image.

docker run -it --rm \
    --mount type=volume,src=synapse-data,dst=/data \
    -e SYNAPSE_SERVER_NAME=my.matrix.host \
    black0/synapse:latest generate

The above command runs the Synapse docker image to generate relevant settings file. Ensure my.matrix.host is replaced with your hostname, and note, this cannot be changed later. The files will be created in /var/lib/docker/volumes/synapse-data/_data on your Raspberry Pi.

The container can then be run with:

docker run -d --name synapse \
    --mount type=volume,src=synapse-data,dst=/data \
    -p 8008:8008 \

Navigating to the IP of your Raspberry Pi with port 8008 will allow you to see the default Matrix page, and running docker logs synapse will show the logs to check all is running ok.

To allow registration you will need to edit the homeserver.yaml file to set enable_registration: true then restart the docker container with docker restart synapse.

In Cloudflare point your hostname you’re using for Matrix to the public IP for your Raspberry Pi, for better security route the (sub-)domain via Cloudflare and set the router to only forward port 443 from Cloudflare IPs. Then in your Caddyfile add a section for your Matrix hostname:

matrix.example.co.uk {
  header /.well-known/matrix/server {
    Content-Type application/json
  respond /.well-known/matrix/server 200 {
    body "{ \"m.server\": \"matrix.example.co.uk:443\" }"
  tls [email protected] {
    dns cloudflare {env.CLOUDFLARE_API_TOKEN}

Here the hostname is defined, the “.well-known” definition is then setup. This is used to assist with Matrix federation. Matrix generally uses port 8448 to assist with federation, however as we want to run though Cloudflare we need to use a standart port, 443. We also want all traffic to go via Cloudflare and not direct to the public IP, so setting the documented SRV DNS record won’t work either. Via the Caddyfile the header for the .well-known path is set to a json content type, Caddy is then set to respond with a 200 response and a json string. This is a key/value of m.server, then host and port, note the escaping of quotes within the json string. Finally all other requests are proxied to the IP and port of the docker container running Synapse and tls is setup with Cloudflare.

comments powered by Disqus