Matrix selbst hosten - Synapse, Element und warum das mehr als nur ein Messenger ist

Messenger gibt es viele. Matrix ist dabei eine Besonderheit, da es nicht direkt eine App meint, sondern ein offenes Protokoll für dezentrale Echtzeitkommunikation, auf dem verschiedene Clients und Server miteinander sprechen können.

Was ist Matrix?

Matrix ist ein offenes, föderiertes Kommunikationsprotokoll für Chat, Gruppenräume, Sprach- und Videokommunikation. Synapse ist dabei der klassische Matrix-Homeserver, also die Server-Software, die das eigenes Matrix-System betreibt.

Als Client wird sehr häufig Element genutzt, weil es auf Desktop und Mobilgeräten breit verfügbar ist und den größten Teil der üblichen Messenger-Funktionen abdeckt und sich wie andere bekannte Messenger anfühlt. Es gibt auch diverse andere Clients wie z.B. Cinny, was von der UI her näher an Discord ist.

Der größte Unterschied zu klassischen Messengern ist die Dezentralität. Man ist nicht an einen einzigen Anbieter gebunden, sondern kann mit anderen Matrix-Servern kommunizieren, ähnlich wie beispielsweise auch E-Mail über viele Anbieter hinweg funktioniert.

Dazu kommt die offene Architektur: Der Server ist selbst hostbar und man kann den Client frei wählen. Das macht Matrix auch nicht nur für die private Kommunikation interessant, auch in Unternehmen und co bietet sich die Nutzung an. Dort kann man beispielsweise auch die Förderation für rein interne Kommunikation deaktivieren.

Aber: Durch die Architektur und auch die Ende-zu-Ende-Verschlüsselung ist Matrix komplizierter in der Einrichtung, was schnell abschreckend wirkt.

Politischer Kontext

Ja, ein Thema was ich sonst nicht betrachte. Finde ich hier aber erwähnenswert.

Matrix passt ziemlich gut in die aktuelle Diskussion um digitale Souveränität, Datenschutz und unabhängige (Kommunikations-)Infrastruktur. Gerade in Europa und auch in Deutschland ist das Interesse an offenen Alternativen zu großen Plattformen seit Jahren hoch und auch diverse öffentliche Einrichtungen und Hochschulen nutzen Matrix als sicheren Messenger.

Installation

Ein alltagstaugliches Matrix-Setup besteht aus mehreren Komponenten:

  • Synapse als Homeserver (es gibt auch andere, aber Synapse ist der gängigste)
  • Element als Frontend im Browser
  • Synapse-Admin zur Benutzerverwaltung

Von der Domaingestaltung habe ich bei mir etwa folgendes Setup:

  • Synapse unter matrix.example.com
  • Element unter chat.example.com
  • Wobei example.com als Basis-URL für die Identitäten dient, das wird über eine .well-known an die Subdomain matrix.example.com delegiert

Die Delegation hat den großen Vorteil, dass die Hauptdomain als Matrix-Adresse genutzt werden kann, aber nicht von Synapse belegt wird. Über eine kleine “Hinweis-Datei” auf der Hauptdomain wissen Clients (und andere Homeserver) dann, dass diese sich zu matrix.example.com verbinden müssen.

In diesem Fall wird Synapse mit sqlite installiert. Für kleine Setups ist das vollkommen in Ordnung, ich selbst nutze Postgres als Datenbank.

Docker

Wie das meiste betreibe ich Matrix in Docker. Meine Compose (10.0.0.2 ist die interne IP dieses Servers):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
services:
  synapse:
    image: docker.io/matrixdotorg/synapse:latest
    restart: unless-stopped
    environment:
      - SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
    volumes:
      - ./data:/data
    ports:
      - 10.0.0.2:8008:8008
  element:
    image: vectorim/element-web:latest
    restart: unless-stopped
    volumes:
      - ./config/element-config.json:/app/config.json
    ports:
      - 10.0.0.2:8009:80
  synapse-admin:
    image: ghcr.io/etkecc/synapse-admin:latest
    restart: unless-stopped
    volumes:
      - ./config/synapse-admin-config.json:/app/config.json
    ports:
      - 10.0.0.2:8010:8080

Die grundlegende Konfiguration für Synapse lässt sich generieren:

1
docker compose run --rm -e SYNAPSE_SERVER_NAME=example.com synapse generate

Die relevanten Config-Files:

Element (config/element-config.json):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
    "default_server_config": {
        "m.homeserver": {
            "base_url": "https://matrix.example.com"
        }
    },
    "disable_custom_urls": true,
    "disable_guests": true,
    "brand": "Mein Chatserver"
}

Synapse-Admin (config/synapse-admin-config.json):

1
2
3
4
5
{
  "restrictBaseUrl": [
    "https://matrix.example.com"
  ]
}

Die eigentliche Config von Synapse (data/homeserver.yaml) habe ich minimal modifiziert:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Configuration file for Synapse.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
#
# For more information on how to configure Synapse, including a complete accounting of
# each option, go to docs/usage/configuration/config_documentation.md or
# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html
server_name: "example.com"
pid_file: /data/homeserver.pid
listeners:
  - port: 8008
    resources:
    - compress: false
      names:
      - client
      - federation
    tls: false
    type: http
    x_forwarded: true

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

log_config: "/data/example.com.log.config"
media_store_path: /data/media_store
registration_shared_secret: "[...]"
macaroon_secret_key: "[...]"
form_secret: "[...]"
signing_key_path: "/data/example.com.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"


# Modifikationen
public_baseurl : "https://matrix.example.com" # URL, über die Synapse von außen erreichbar ist
report_stats: false
enable_registration: false

Reverse-Proxy

Ich habe Caddy als Reverse-Proxy im Einsatz. Die relevante Konfiguration in der Caddyfile sieht bei mir so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
matrix.example.com {
    reverse_proxy 10.0.0.2:8008
}

chat.example.com {
    reverse_proxy 10.0.0.2:8009
}

synapse-admin.example.com {
    # siehe https://caddyserver.com/docs/caddyfile/directives/basic_auth
    basic_auth {
        # User hier
    }
    reverse_proxy 10.0.0.2:8010
}

Synapse-Admin habe ich hinter Basic-Auth versteckt. Das ist an sich meiner Meinung nach nicht notwendig, aber fühlt sich besser an.

Delegation einrichten

Bei der Hauptdomain example.com müssen einige Dateien angelegt werden.

.well-known/matrix/server:

1
2
3
{
    "m.server": "matrix.example.com:443"
}

.well-known/matrix/client:

1
2
3
4
5
{
    "m.homeserver": {
        "base_url": "https://matrix.example.com"
    }
}

Damit sollte nun Förderation auch funktionieren. Mit dem Federation Tester (federationtester.matrix.org) lässt sich das prüfen.

Initialen User erstellen

Mittels

1
docker compose exec -it synapse register_new_matrix_user http://localhost:8008 -c /data/homeserver.yaml

lässt sich nun der initiale Admin-User (und auch weitere User natürlich) anlegen.

Clients einrichten

An den Clients sollte ein Login auf example.com nun funktionieren. Durch die Delegation werden Clients zu matrix.example.com weitergeschickt.