Préparation

Par ce salop de Croco et corrigé par ce salop de fl0w5

Nous allons commencer à créer une stack docker à laquelle nous rajouterons nos bridges par la suite. Il nous faudra donc créer:

  • Un network interne pour communiquer avec les futurs bridges et la database
  • Un volume pour stocker les données de façon permanente
  • Une base de données PostgreSQL pour plus de performances que sqlite.
  • Un service synapse

Installation

Tout d'abord, nous allons devoir générer les fichiers de configuration de synapse. Pour cela nous allons créer une stack docker avec la base de données postgresql afin de la configurer aussi. Il est évidemment possible d'utiliser une base de données externe à docker pour que cela fonctionne. Seulement Postgresql et sqlite sont supportés mais sqlite n'est pas adapté pour de la production.

version: "2.3"

networks:
  matrix:
    external: false

  volumes:
    matrix:
      driver: local
    postgreql:
      driver: local

  services:
    synapse:
      image: matrixdotorg/synapse
      container_name: matrix
      restart: always
      command: generate
      networks:
        - matrix
      ports:
        - 127.0.0.1:8008:8008
      volumes:
        - matrix:/data
      environment:
        - TZ=Europe/Paris
        - SYNAPSE_SERVER_NAME=<domain>
        - SYNAPSE_REPORT_STATS=no

  postgres:
    image: postgres:alpine
    restart: always
    container_name: postgres
    networks:
      - matrix
    volumes:
      - postgres:/var/lib/postgresql/data
      - <path to init.db>:/docker-entrypoint-initdb.d/init.sql
    environment:
      - TZ=Europe/Paris
      - PGTZ=Europe/Paris
      - POSTGRES_INITDB_ARGS="--auth=scram-sha-256"
      - POSTGRES_HOST_AUTH_METHOD=scram-sha-256
      - POSTGRES_PASSWORD=<synapse_password>
      - POSTGRES_USER=synapse

Le service Synapse est plutôt basique. Cependant, nous avons rajouter la commande command: generate afin de préciser que nous voulons générer la configuration par défaut avec les arguments SYNAPSE_SERVER_NAME=<domain> et SYNAPSE_REPORT_STATS=no.

Le service postgresql va créer l'utilisateur synapse ayant pour mot de passe <synapse_password>. Il faudra aussi créer un fichier init.db qui permettra de créer les bases de données nécessaires et les utilisateurs pour les différents bridges. Il faut donc prévoir en avance quels bridges seront créés. Il sera tout de même toujours possible de créer ces base de données et ces utilisateurs avec la commande psql par la suite. Le contenu du fichier init.db est le suivant (avec la creation d'un utilisateur mautrixfacebook et de sa db pour le bridge facebook par exemple):

CREATE DATABASE synapse
 ENCODING 'UTF8'
 LC_COLLATE='C'
 LC_CTYPE='C'
 template=template0
OWNER synapse;

CREATE USER mautrixfacebook WITH ENCRYPTED PASSWORD '<mautrixfb-password>';
CREATE DATABASE mautrixfacebook
 ENCODING 'UTF8'
 LC_COLLATE='C'
 LC_CTYPE='C'
 template=template0
OWNER mautrixfacebook;

Service synapse

Une fois que tout est préparé, nous pouvons déployer la stack sur portainer:

Aller dans les logs du containers matrix et attendre que le message suivant s'affiche:

Config file '/data/homeserver.yaml' already exists. Generating any missing config files.

Comment aller dans les logs:

Une fois que ce message est affiché, éteindre la stack.

Une fois la stack éteinte, aller sur le serveur avec une connexion SSH par exemple. Ouvrir le fichier de configuration du serveur synapse qui se trouve dans le volume monté:

vim /var/lib/docker/volumes/matrix_matrix/_data/homeserver.yaml

Ce fichier est très bien documenté et très complet. Cependant, des valeurs sont à vérifier:

  • server_name: "<matrix url desired>"
  • enable_registration: false

Aussi, il faut configurer la connexion à la base de données. Pour cela, commenter les lignes pour sqlite3 et ajouter postgresql:

database:
#  name: sqlite3
#  args:
#    database: /data/homeserver.db

 name: psycopg2
 txn_limit: 10000
 args:
   user: synapse
   password: <synapse_pasword>
   database: synapse
   host: postgres
   port: 5432
   cp_min: 5
   cp_max: 10

Service postgreql

Ici, nous allons autoriser ces saloperies de connexions venant de 'l'exterieur' représentées par les autres conteneurs.

vim /var/lib/docker/volumes/matrix_postgres/_data/pg_hba.conf

A la fin de ce fichier, ajouter la ligne:

host    all             all             all                     scram-sha-256

avant:

local   all             all                                     scram-sha-256

Ensuite, ouvrir le fichier postgresql.conf:

vim /var/lib/docker/volumes/matrix_postgres/_data/postgresql.conf

et dé-commenter la ligne listen_address:

listen_addresses = '0.0.0.0'

Lancement

Une fois tous ces changements faits, il est faut encore modifier la stack afin que le serveur synapse soit lancé et arrête d'essayer de regénerer les fichiers de configuration. Aussi, il est possible de supprimer le volume _init.sql _ qui n'est plus utile pour le conteneur postgres.

version: "2.3"

networks:
  matrix:
    external: false

  volumes:
    matrix:
      driver: local
    postgreql:
      driver: local

  services:
    synapse:
      image: matrixdotorg/synapse
      container_name: matrix
      restart: always
      networks:
        - matrix
      ports:
        - 127.0.0.1:8008:8008
      volumes:
        - matrix:/data
      environment:
        - TZ=Europe/Paris

  postgres:
    image: postgres:alpine
    restart: always
    container_name: postgres
    networks:
      - matrix
    volumes:
      - postgres:/var/lib/postgresql/data
    environment:
      - TZ=Europe/Paris
      - PGTZ=Europe/Paris
      - POSTGRES_INITDB_ARGS="--auth=scram-sha-256"
      - POSTGRES_HOST_AUTH_METHOD=scram-sha-256
      - POSTGRES_PASSWORD=<synapse_password>
      - POSTGRES_USER=synapse

Aussi, synapse possède un health check ce qui permet de vérifier que le conteneur tourne bien. Si au bout de 10 minutes, le conteneur n'affiche pas healthy, alors regarder les logs afin de trouver le problème.

Mise en ligne

Nginx

Il faudra un serveur proxy pour pouvoir atteindre le serveur synapse. En effet, la stack n'expose pour l'instant que le port 8008 sur localhost.

Pour cela, il y a le tutoriel Saloperie de NGINX.

Pour ma part, j'ai utilisé cette configuration:

server {
    listen 8080;
    listen [::]:8080;

    server_name <domain>;

    # enforce https
    return 301 https://$host:443$request_uri;
}

server {
    listen 443 ssl http2;
    listen 8448 ssl http2; # For federation purpose

    server_name <domain>;

    ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;

    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_ecdh_curve secp384r1;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;

    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;

    access_log            /var/log/nginx/matrix.access.log;


    client_max_body_size 128M;

    location ~* ^(\/_matrix|\/_synapse\/client) {
        proxy_set_header Host $host;
        proxy_set_header   X-Real-IP          $remote_addr;
        proxy_set_header   X-Forwarded-Proto  $scheme;
        proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;

        proxy_pass http://127.0.0.1:8008;
    }
}

Firewall

Afin que le serveur matrix soit accessible depuis l'exterieur, il faut que les règles de firewall laissent passer le port 8448 et 443 (optionnelement 80).

Le port 8448 sert à la fédération des serveurs et le port 443 est le port d'accès au serveur.

Par exemple, avec iptables, il faut utiliser ces règles:

iptables -I INPUT 1 -p tcp --dport 8448 -j ACCEPT -m comment --comment "Federation for matrix"
iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT -m comment --comment "WebServeur HTTPS"
#iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT -m comment --comment "WebServeur HTTP"

Serveur DNS

Afin de pouvoir bien fédérer le serveur matrix, il faut aussi ajouter un enregistrement DNS de type SRV:

_matrix._tcp.<domain> IN SRV 10 0 8448 <domain>

il est possible de vérifier que l'enregistrement fonctionne à l'aide de la commande:

nslookup -q=SRV _matrix._tcp.<domain>

Vérifier la fédération

Il est possible de vérifier que le serveur synapse est bien fédéré à l'aide du site federation tester.

Connexion à Matrix

Afin de se connecter à un serveur matrix, il faut utiliser un client. Le client le plus utilisé est element. Il existe un client web ou alors, selon la distribution utilisée ou l'OS utilisé, une application. Plus d'information ici.

Une fois l'application lancée, il faut modifier le homeserver de matrix.org vers votre domaine.

Ensuite, il suffit de créer un compte et ensuite de s'y connecter afin d'avoir accès au serveur matrix.

Attention

Suite à la création du compte utilisateur, il est suggéré de supprimer la possibilité de pouvoir créer un compte. Pour cela, il suffit d'éteindre la stack, modifier le fichier homeserver.yaml et changer la ligne éditée au début de ce tutoriel:

enable_registration: false