Skip to content

One way to setup a Matrix Synapse server, with Coturn, PostgreSQL, HAProxy and SSL certificates

Notifications You must be signed in to change notification settings

Miouyouyou/matrix-coturn-docker-setup

Repository files navigation

About

This repository contains files to "quickly" setup a Matrix Synapse server.

Note that more complex setups can be done using Ansible

DNS configuration

  • Prepare two domain names for your Matrix (Synapse) server and TURN (CoTURN) server.

Your matrix server will offer Chat services, and the TURN server will allow you to use Webconferences through your Chat with ease.

_matrix._tcp IN SRV  10 5 8448 matrix.example.com
_turn._udp   IN SRV  0 0 3478 turn.example.com.
_turn._tcp   IN SRV  0 0 3478 turn.example.com.
_turns._tcp  IN SRV  0 0 5349 turn.example.com.
_turn._udp   IN SRV  0 0 3478 turn.example.com.
_turn._tcp   IN SRV  0 0 3478 turn.example.com.
_turns._tcp  IN SRV  0 0 5349 turn.example.com.

Setup the whole thing with the provided tools

Note : All the tools should be run from the main folder.
Meaning that every tool should be called using ./tools/tool_name.sh syntax from a shell.

First configuration

In the following examples, you should replace matrix.yourdomain.com and turn.yourdomain.com, by the domain names that will be used to reach your Matrix Synapse server and your CoTURN server, respectively.

Example :

  • If your Matrix domain name is : matrix.hamsters.dev
  • If your TURN domain name is : turn.hamsters.dev

Then :

  • Replace references to matrix.yourdomain.com by matrix.hamsters.dev
  • Replace references to turn.yourdomain.com by turn.hamsters.dev

SSL

If you already have SSL certificates, put in them in the ssl/matrix.yourdomain.com and ssl/turn.yourdomain.com and be sure to follow this convention :

  • fullchain.pem is a certificate containing the whole chain of trust.
  • key.pem is the private key associated with your certificate.

Let's encrypt

If you don't have SSL certificates, you can generate them using tools/letsencrypt-generate.sh.

Same certificate for Matrix and TURN domains
./tools/letsencrypt-generate.sh matrix.yourdomain.com turn.yourdomain.com

OR

One certificate for each domain
./tools/letsencrypt-generate.sh matrix.yourdomain.com
./tools/letsencrypt-generate.sh turn.yourdomain.com

Docker, the various services and preconfigure Riot-web

./tools/docker-prepare.sh matrix.yourdomain.com turn.yourdomain.com

You can setup environment variables to control the generation of some configuration parameters :

  • POSTGRESQL_PASSWORD controls the password for PostgreSQL
  • TURN_USERNAME controls the username used for TURN
  • TURN_PASSWORD controls the password used for TURN
    Example :
    POSTGRESQL_PASSWORD=W1llBr34kEasily TURN_USERNAME=John TURN_PASSWORD=Piano ./tools/docker-prepare.sh matrix.yourdomain.com turn.yourdomain.com
    You can also only setup the desired variables :
    TURN_USERNAME=John ./tools/docker-prepare.sh matrix.yourdomain.com turn.yourdomain.com
    In such case, the others parameters will be automatically generated.

Install Riot-Web

./tools/riot-install.sh

Start the whole thing

docker-compose up -d

Add the missing TURN user

This is the only script that is installed in the main folder.

This script is generated by tools/docker-prepare.sh

./turn_add_missing_user.sh

Afterwards

Add users to your chat

./tools/synapse_add_user.sh Username Password

View the logs

You can then use docker-compose logs to get the logs of every units at once, or :

  • docker-compose logs --last=50 -f matrix to follow Synapse logs
  • docker-compose logs --last=5 -f coturn to follow COTURN logs
  • docker-compose logs -f postgresql to follow PostgreSQL logs
  • See files in nginx/logs for NGINX logs

HAProxy logs can be read using : journalctl -t haproxy

HAProxy logs are actually routed to /dev/log which is read by SystemD journalctl on most Linux systems.
If you're not using SystemD, you'll have to know where /dev/log is routed (/var/log/messages ?).

Shut it down

  • From this repo, run :
docker-compose down

Afterwards

Renew the certificates afterwards

If you generated the Let's Encrypt SSL certificates using the method described in this document, here's how you can renew your certificates.

Execute the following commands while docker-compose is up :

docker run -v $PWD/letsencrypt:/etc/letsencrypt -v $PWD/static/:/var/lib/letsencrypt certbot/certbot:latest renew
cp -rL letsencrypt/live/* ssl/
cd ssl/matrix.yourdomain.com
cat fullchain.pem privkey.pem > complete.pem
cd -
docker-compose kill -s SIGHUP haproxy # Tell HAProxy to reread its config and the SSL certificates

Configurations

HAProxy (Load balancer - Reverse proxy)

Used to manage SSL certificates directly and filter out bad traffic, before redirecting it to either Synapse or NGINX

Configuration

  • haproxy/conf/haproxy.cfg

NGINX

Only used to serve Let's Encrypt ACME challenges and the .well-known/matrix/server file in this setup.

Configuration

  • nginx/conf/nginx.conf

COTURN

Used to help VOIP users setup their firewalls in order to communicate directly.

In this setup, COTURN uses the host network in order to avoid dealing with Docker "port-ranges" mapping.

Turns out that if you ask Docker to NAT ports between 49000 and 65535 to your container, Docker will setup one iptables rule PER PORT !
So if you want to map ports using the 'ports' directive, you'll have to wait patiently for Docker to setup roughly 16000 iptables rules !
Using the Docker host avoid this issue.

Configuration

  • coturn/conf/turnserver.conf

Database

  • coturn/conf/turndb

Template database

The original form of coturn/conf/turndb

  • coturn/conf/turndb_sample

Check if users were added correctly

sqlite3 coturn/data/turndb "select * from turnusers_lt"

PostgreSQL

Data

Execute docker volume inspect pgdata and check the folder pointed by "Mountpoint".

Synapse

Configuration

Main configuration files :

  • synapse/conf/homeserver.yaml
  • synapse/conf/homeserver.d/database.yaml
  • synapse/conf/homeserver.d/registration.yaml
  • synapse/conf/homeserver.d/voip.yaml

Sample configuration with comments :

  • synapse/conf/homeserver.yaml.sample

Keys generated by Synapse. I have no idea about how this is used.

  • synapse/conf/keys

Data (avatars, files, ...) of your server :

  • synapse/data

Riot-web

The Chat client used to connect to your Chat server.

You can still use https://riot.im client though.

Main configuration file :

  • static/config.json

Sample configuration file :

  • static/config.sample.json

Setup the whole thing manually

Now untested...

First configuration

Quite a long-ride for a "quick" setup...

SSL

If you don't have SSL certificates, generate free Let's Encrypt SSL certificates before hand.
To do that you can use the method described below.

Conventions used in this document

Folders

docker-compose.yml is currently configured to use ssl/matrix.yourdomain.com/... for SSL files related to your Matrix domain and ssl/turn.yourdomain.com/... for SSL files related to your TURN domain.
The Checklist follows this logic.

If you use the same SSL certificates for both TURN and Matrix domains, replace these references accordingly in docker-compose.yml.

Files
  • fullchain.pem is a certificate containing the whole chain of trust.
  • key.pem is the private key associated with your certificate.
  • complete.pem is the concatenation of fullchain.pem and key.pem

If you change any of these filenames, remember to change them in the various configuration files.

Generate SSL certificates with Let's Encrypt

Prepare ssl/ and start NGINX for ACME challenges

This is the only time we map NGINX directly to port 80. In the current setup, HAProxy is mapped to port 80 and handle HTTP connections.

docker-compose down # Shut down all services for the moment
mkdir -p ssl # Be sure that ssl/ exist
docker-compose run -p 80:80 -d nginx # Run only NGINX on port 80 for ACME challenges
Generate the certificates the first time

For Matrix

export SSL_DOMAIN=matrix.yourdomain.com
docker run -v $PWD/letsencrypt:/etc/letsencrypt -v $PWD/static/:/var/lib/letsencrypt certbot/certbot:latest certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt -d $SSL_DOMAIN
cp -rL letsencrypt/live/$SSL_DOMAIN ssl/

For TURN

export SSL_DOMAIN=turn.yourdomain.com
docker run -v $PWD/letsencrypt:/etc/letsencrypt -v $PWD/static/:/var/lib/letsencrypt certbot/certbot:latest certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt -d $SSL_DOMAIN
cp -rL letsencrypt/live/$SSL_DOMAIN ssl/
Shutdown NGINX
docker-compose down

If you have your own SSL certificates

If you generated SSL certificates yourself, using another method :

  • Create the folder ssl/matrix.mynewchat.com/
  • Copy SSL certificates for matrix.mynewchat.com to ssl/matrix.mynewchat.com/
  • Create the folder ssl/turn.mynewchat.com/
  • Copy SSL certificates for turn.mynewchat.com to ssl/turn.mynewchat.com

In both cases, generate complete.pem for HAProxy

cd ssl/matrix.yourdomain.com
cat fullchain.pem privkey.pem > complete.pem
cd -

If you don't do this now, when starting HAProxy through docker-compose, a folder ssl/matrix.yourdomain.com/complete.pem will be created automatically by Docker.
In such case, remove the ssl/matrix.yourdomain.com/complete.pem folder, then cat the files.

Postgres

  • Edit env/postgres.env and setup the credentials you would like to use for this server instance.

The PostgreSQL instance should NOT be accessible from the outside though, unless you understand what you're doing.

Final checklist (once you got the SSL certificates)

Let's say that :

  • your new domain name for your Matrix server is matrix.mynewchat.com

  • your new domain name for your TURN server is turn.mynewchat.com

  • Fork this repository

  • Clone it git clone https://github.com/YourUserName/matrix-coturn-docker-setup --depth 1

  • In static/.well-known/matrix/server change occurences of matrix.yourdomain.com to matrix.mynewchat.com

  • In static/config.json change occurences of matrix.yourdomain.com to matrix.mynewchat.com

  • In docker-compose.yml change occurences of matrix.yourdomain.com to matrix.mynewchat.com

  • In nginx/conf/nginx.conf change occurences of matrix.yourdomain.com to matrix.mynewchat.com

  • In haproxy/conf/haproxy.cfg change occurences of matrix.yourdomain.com to matrix.mynewchat.com

  • In docker-compose.yml change occurences of turn.yourdomain.com to turn.mynewchat.com

  • In coturn/conf/turnserver.conf change occurences of turn.yourdomain.com to turn.mynewchat.com

  • In docker-compose.yml edit the following properties, based on your preferences, by modifying the part after the '='. Avoid using quotes in the environment variables :

    • - SYNAPSE_REPORT_STATS=yes # Can be set to "no"
    • - SYNAPSE_VOIP_TURN_USERNAME=turn_username
    • - SYNAPSE_VOIP_TURN_PASSWORD=turn_password
  • Download a Riot-web release from their webpage https://github.com/vector-im/riot-web/releases

  • Extract the archive and move all the content from riot-vx.y.z to static/

Run it

  • From this repo, run :
docker-compose up -d

Add users

To your Synapse server

docker-compose exec synapse register_new_matrix_user -c /etc/synapse/homeserver.d/registration.yaml -u chat_user -p chat_password -a http://localhost:8008

To your TURN server

docker-compose exec coturn turnadmin -a -b "/srv/coturn/turndb" -u turn_username -p turn_password -r turn.yourdomain.com

TURN is used to help the users wanting to do direct VOIP configure their firewalls, and NAT setup.
This remove the complexity of VOIP communications, without requiring a middleman server (who could record the entire session).

If SYNAPSE_VOIP_TURN_USERNAME is not set to an empty string in the matrix configuration part, the user should be added ASAP, else CoTURN will reject the authentication request and fail VOIP setups.