Installing Synape (Matrix Server) on Gentoo Linux

Matrix is a federated, generaral purpose communication system and might very well be the future of digital communication. The reference homeserver implementation is Synapse, implemented in Python. This article describes the installation and configuration of Synapse on Gentoo Linux.

Installation

Make sure to install the necessary requirements from https://matrix-org.github.io/synapse/latest/setup/installation.html#installing-from-source. Most of the installation process has been taken over from this guide.

Install synapse server under /opt/synapse:

useradd -d /opt/synapse -s /bin/bash matrix
chown matrix:matrix /opt/synapse
mkdir /opt/synapse
mkdir /opt/synapse/ssl
cd /opt/synapse
su matrix
virtualenv -p python3 ~/synapse/env
source env/bin/activate
pip install -U pip
pip install -U setuptools
pip install matrix-synapse

Generate configuration file template and server keys (run while still in virtualenv):

python -m synapse.app.homeserver \
    --server-name my.domain.name \
    --config-path homeserver.yaml \
    --generate-config \
    --report-stats=[yes|no]

Replace my.domain.name with the domain name that will form the last part of the matrix IDs on this server.

Configuration

Open the resulting configuration file homeserver.yaml in a text editor and modify to your needs. Keys that might be necessary to modify include

  • public_baseurl
  • listeners
  • admin_contact
  • tls_certificate_path
  • tls_private_key_path
  • database
  • email

but others might also be relevant.

I have listeners for ports 8448 and 8008 active. Port 8448 uses TLS encryption and is mainly used for server federation, but is also left open for client connections. Port 8008 uses unencrypted HTTP, therefore this listener bind to the local interface (127.0.0.1 and ::1) only. As clients connect mainly over port 443 by default, HTTPS on the virutal domain used for client login will be forwarded by Apache's mod_proxy to localhost port 8008. The relevant Apache configuration looks like this:

ServerName matrix.0xaa55.org
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
AllowEncodedSlashes NoDecode
ProxyPreserveHost On 
ProxyRequests Off
ProxyPass /_matrix http://localhost:8008/_matrix nocanon
ProxyPassReverse /_matrix https://locahost:8008/_matrix
ProxyPass /_synapse/client http://localhost:8008/_synapse/client nocanon
ProxyPassReverse /_synapse/client http://locahost:8008/_synapse/client

For more details, see https://matrix-org.github.io/synapse/develop/reverse_proxy.html.

Certificates

If this is the only domain being served form the server running synapse (or at least the only one using certificates), feel free to use synapse's build-in ACME mechanisms to obtain certificates from Let's Encrypt. In my case, a couple of hostnames already existed that received certificates from Let's Encrypt using certbot with Apache plugin. Therefore, the certificate for the synapse server domain (matrix.0xaa55.org) has been added to the certificates obtained by certbot. Therefore, the acme section of the homserver configuration has been left out.

After obtaining the certificate and key for the matrix server domain name, the certificate and key files are copied to /opt/synapse/ssl/ (the configuration options tls_certificate_path and tls_private_key_path point there) and chown'ed to user matrix. Since the server will be run by user matrix (more on that later), but the certificates will be renewed within the context of a different user, a certificate deployment hook is needed to make the renewed certificate and key readable for user matrix. To accomplish this, certbot's renew command is run (via crontab) with the --deploy-hook option. This option takes as argument the location of a script run after deploying a new certificate. This script looks like this:

#!/bin/bash
case "${RENEWED_LINEAGE}" in 
        "/etc/letsencrypt/live/my.domain.name")
                /etc/init.d/synapse stop
                cp /etc/letsencrypt/live/my.domain.name/fullchain.pem /opt/synapse/ssl/my.domain.name.tls.crt
                cp /etc/letsencrypt/live/my.domain.name/privkey.pem /opt/synapse/ssl/my.domain.name.tls.key
                chown matrix:matrix /opt/synapse/ssl/my.domain.name.tls.*
                /etc/init.d/synapse start
                ;; 
esac

Replace matrix.domain.name with the domain name of your matrix server.

Server Name vs. Hostname

As with probably lots of other matrix servers, the server name of my matrix server does not match the hostname the matrix server if being hosted on. In matrix terminology, the server name is the last part of the matrix user ID, e.g. for a matrix server with user IDs @user:my.domain.name hosted on matrix.domain.name, the server name is_my.domain.name and the domain name is matrix.domain.name. To enable other matrix servers to find the correct matrix server for user @user:my.domain.name, a feature called delegation is used. This requires the web server to serve a JSON file under https://my.domain.name/.well-known/matrix/server with the following content:

{
	"m.server": "matrix.domain.name"
}

At this point, it's advisable to check if the configration has been set up correctly to enable federation with oter servers using matrix.org's federation tester.

openrc Scripts

Since synapse is missing from Gentoo's portage, there are no openrc scripts provided to control the synapse daemon. I use the following openrc script in /etc/init.d/synapse:

#!/sbin/openrc-run

depend() {
        need net 
}

cd /opt/synapse
source /opt/synapse/env/bin/activate

start() {
        ebegin "Starting synapse"
        start-stop-daemon --start --user matrix --exec synctl start
        eend $? 
}

stop() {
        ebegin "Stopping synapse"
        synctl stop
        eend $? 
}

Additional components

The following additional component extend Synapse's functionality: