Install a Matrix Server with Synapse on Arch Linux

Matrix is a new(ish) open source communications protocol. Modern features like encryption, voip, etc. are a part of it which makes it very interesting. A popular client is Riot, another open source protocol that reminds me a lot about the popular but closed discord platform.

This article explains the installation of a self hosted matrix server with LDAP support on top of Arch Linux. As a database backend I chose an existing PostgreSQL server. Of course the database backend is up to you. Change the installation procedure as needed.

LDAP support is provided by the Synapse LDAP Auth provider package.

Arch Linux provides a ready to use matrix-synapse package. This is skipped in favor of a manual installation however as the LDAP extension is currently out of date.

Preparing Arch Linux

The following line installs the required compilers, python 3 and various python extensions.

pacman -S base-devel python python-pip python-setuptools python-virtualenv postgresql-libs 

Next, create a service user. At this point I assume that the installation will live in /opt/synapse.

useradd -r -U -d /opt/synapse -s /bin/nologin synapse

Prepating PostgreSQL Database

Login to your PostgeSQL server to create a new database and a new user for it:

CREATE USER synapse WITH ENCRYPTED PASSWORD 'your_super_secret_password';
CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse;
GRANT ALL PRIVILEGES ON DATABASE synapse TO synapse;

If you’re using a remote host remember to set an entry in your pg_hba.conf file.

Installing synapse

Creating the destination directory and switching to the synapse user.

mkdir -p /opt/synapse
chown -R synapse:synapse /opt/synapse
sudo -u synapse /bin/bash

Continue as synapse user!

Preapre the Python Virtual Environment to hold the required packages for synapse including all it’s Python dependencies.

python3 -m venv /opt/synapse/env
source /opt/synapse/env/bin/activate
pip install --upgrade pip
pip install --upgrade setuptools

Continue with the installation of synapse and additional packages.

pip install matrix-synapse psycopg2-binary matrix-synapse-ldap3

Next, generate the initial config.

IMPORTANT: Change the domain name to the domain you would like to use.

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

Three new files, a ky, a logging config and the main server conifg homeserver.yaml should have been created. Edit homeserver.yaml as needed. Take some time to read through the various config options to see if they’re for you.

Set your bind_addresses array to contain your server’s IP otherwise it will only be accessible through localhost. Ecxample:

...
bind_addresses: ['::1', '127.0.0.1', '133.144.155.166']
...

In the database section remove the sqlite config and replace it with something like this:

database:
    name: psycopg2
    args:
        user: synapse
        password: PASSWORD_GOES_HERE
        database: synapse
        host: localhost
        cp_min: 5
        cp_max: 10

An example LDAP configuration has been created as well. Change as needed:

password_providers:
 - module: "ldap_auth_provider.LdapAuthProvider"
   config:
   enabled: true
       uri: "ldap://ldap.example.com:389"
       start_tls: true
       base: "ou=users,dc=example,dc=com"
       attributes:
           uid: "cn"
           mail: "mail"
           name: "givenName"
       #bind_dn:
       #bind_password:
       #filter: "(objectClass=posixAccount)"

Check the matrix-synapse-ldap3 repository for additional documentation.

This should be it. Run synctl start. After the command ran, check if port 8008 (or whatever port you set) shows up when you run ss -tulpn.

Troubleshooting

LDAP user DN start ist uid instead of cn

If you use something else then cn as the first property of a user’s dn, change the uid attribute in the LDAP configuration.

Only admin users can create communities

Setting an admin user is done setting the admin flag of an entry in the database’s user entry to 1. Example:

UPDATE users SET admin=1 WHERE name=’@roman:romangeber.com’

Not very elegant but it works.

Integration manager cannot be reached

I solved this issue by enabling tls on my matrix backend. Encryption was already enabled though the reverse proxy, however the internal communication was established through plain old http.

Set up a TLS listener (preferrably on port 8448) and integrate a cert and a key file.

More on that topic can be found in this github issue

URL previews don’t work

Set url_preview_enabled to true and enable the mandatory url_preview_ip_range_blacklist.

Further reading