Matrix selbst ist keine Software. Es handelt sich hierbei um ein quelloffenes, Ende-zu-Ende verschlüsseltes Protokoll für Chat- und Echtzeitkommunikation. Als offener Standard stellt es sicher, dass verschiedene Softwareimplementierungen wie "Element" (Client) oder "Synapse" (Server) zueinander kompatibel bleiben. Das Prinzip von Matrix ist dabei simpel: Der Anwender betreibt seinen Matrix-Server passend zu einer Internetdomäne wie "". Darauf erstellt er seine eigenen Benutzer, deren Namen dem Schema "@name:domain.com" folgen.
Bis hier hin wäre alles sehr einfach und nur ein weiterer geschlossener Chatdienst. Doch Matrix erlaubt, den Server im Internet zu publizieren (Federation). Das ermöglicht, dass sich Nutzer verschiedener Matrix-Server miteinander verbinden. Vereinfacht gesagt folgt Matrix damit dem Vorbild des SMTP-Mailservers. Der verteilt lokale Nachrichten innerhalb des geschlossenen Netzwerks und leitet externe Nachrichten zu den jeweiligen SMTP-Servern der anderen Domänen. Wie bei Maildiensten mischen sich hierbei selbstgehostete Lösungen samt eigener Server mit Cloudangeboten wie "". Allerdings bleibt Matrix-Usern der Spam erspart, mit dem Mailnutzer tagtäglich leben müssen. Denn anders als SMTP stellt das Matrix-Protokoll nicht ungefragt alle Nachrichten zu. Möchte ein Nutzer einer fremden Domain Kontakt via Chat aufnehmen, muss der Empfänger dem zustimmen.
Wer einen eigenen Matrix-Server einrichtet, steht dann natürlich vor dem Problem, dass viele seiner bestehenden Kontakte trotzdem auf WhatsApp, Facebook Messenger oder Telegram bleiben. Alternativ arbeiten sie mit geschlossenen Systemen wie Discord oder Slack. Dafür offeriert Matrix eine ganze Serie von Bridges. Die klinken sich für den jeweiligen User in die fremden Dienste ein und leiten Nachrichten zu Matrix weiter. Mit der korrekten Konfiguration muss ein Anwender dann nur noch einen einzigen Matrix-Chatclient verwenden, über den er sowohl mit anderen Matrix-Nutzern als auch allen anderen Chatplattformen über den einen Matrix-Server kommunizieren kann.
Nachfolgend zeigen wir, wie Sie einen eigenen Matrix-Server mit der Open-Source-Software "Synapse" aufsetzen, dazu passende Clients nutzen und eine Bridge für WhatsApp aufsetzen. Natürlich lässt sich Synapse in einer virtuellen Maschine mit Debian- oder Fedora-Linux betreiben. Wir setzen den Server containerisiert mit Podman (alternativ: Docker) auf, das funktioniert dann weitgehend unabhängig vom eigentlichen Server-OS.
Vorbereitungen
Bevor es an das eigentliche Setup des in Python geschriebenen Synapse-Servers für Matrix geht, müssen Sie ein paar Vorbereitungen treffen. Der Matrix-Service im Container verwendet das HTTP-Protokoll auf Port 8008 oder HTTPS auf Port 8448. Sie könnten nun Port 8448 freigeben, den Matrix-Traffic dorthin leiten und dem Synapse-Server selbst ein gültiges Zertifikat beispielsweise via Let's Encrypt geben. Das ist aber mehr Aufwand als nötig. In unserem Beispiel läuft der Synapse-Dienst auf einem Mietserver (Hetzner) mit einer einzigen IP-Adresse. Den Server nutzt auch eine ganze Reihe anderer Dienste. Den ankommenden Traffic verteilt daher ein Nginx-Reverse-Proxy an die verschiedenen Service-Container basierend auf dem Namen der Dienste. Pakete für "" gehen an einen anderen Container als Anfragen an "dienst5.domain.com". Zudem übernimmt der Nginx-Server die SSL-Terminierung für alle Dienste und verwaltet das Let's-Encrypt-Zertifikat der Domain. Zwischen Proxy und den eigentlichen Diensten genügt dann HTTP.
Für Synapse nutzen wir im Beispiel den DNS-Namen "" und den regulären HTTPS-Port 443. Je nachdem, wie Sie ihr Docker/Podman-Setup betreiben, leitet Nginx den Traffic auf eine interne Bridge-IP-Adresse oder gemappten Port weiter. Bei unserem Beispiel handelt es sich um eine "gewachsene" Infrastruktur, die nach und nach Dienste von traditionellen VMs in Container migriert. Daher laufen diese Container auf demselben Bridged Network wie die VMs und jeder Container verfügt über eine eigene interne IP-Adresse. Ein Grund dafür ist auch die Sicherheit. Der Zugang zu Diensten auf einem internen Netzwerk lässt sich besser über die Firewall kontrollieren und überwachen, als wenn Container sich direkt auf das extern zugängliche Interface per Port-Mapping binden.
Unsere Reverse-Proxy-Konfiguration für den Synapse-Server ("/etc/nginx/conf.d/ matrix.conf ") sieht daher in etwa so aus:
server { listen 443 ssl http2;
server_name ; ssl_certificate /etc/ letsencrypt/live/ domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/ live/; # managed by Certbot
[...] (SSL- und LOG-Parameter)
location ~ ^(/_matrix|/
_synapse/client) { client_max_body_size 100M; proxy_pass ; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host;
}
Damit gelangt nun sämtlicher HTTPS-Verkehr für "" an Port 8008 des Containers auf der internen Bridge-IP 192.168.122.26. Wenn Sie Container ohne lokale Bridge betreiben, lautet der Eintrag "proxy_pass http://127. 0.0.1: 8008;".
Nach Außen hin heißt Ihr Synapse-Server "", aber der eigentliche Dienst soll Namen wie "@user1:domain.com", und nicht "@user1:matrix.domain.com" verwenden. Sie müssen also im weiteren Verlauf ihren Synapse-Server mit der Konfiguration "domain.com" betreiben und gleichzeitig fremden Servern mitteilen, dass die Chatnachrichten für "domain.com" an den Server "https://matrix.domain.com:443" geleitet werden sollen. Für die Discovery nutzt das Matrix-Protokoll zwei Optionen. Ein Server, der den Kontakt zu einer anderen Domäne herstellen will, versucht den Zielserver zuerst über eine DNS-Abfrage ausfindig zu machen. Hier folgt Synapse dem Beispiel von SNMP, das den Mailserver einer Domäne über den DNS-Eintrag "MX" publiziert. Matrix fragt nach einem SRV-Eintrag namens "_matrix._tcp", also in unserem Beispiel nach "_matrix._tcp.domain.com". Die Antwort muss dann entsprechend "matrix.domain.com" und Port 443 lauten.
Allerdings können nicht alle Domain-Inhaber problemlos DNS-Einträge anlegen oder ändern. Schlägt also die DNS-Query nach dem SRV-Eintrag fehl, probiert das Matrix-Protokoll einen anderen Weg: Es startet eine Rest-API-Anfrage via HTTPS an den Domänennamen mit der URL "/.well-known/matrix/server"– in unserem Fall also an "". Darauf erwartet Matrix eine HTTP-200-Antwort im JSON-Format. Diese Antwort übergibt in unserem Beispiel ebenfalls der Nginx-Reverse-Proxy. Die Konfiguration hierfür steht in der Regel in der Basiskonfiguration des Nginx-Servers "/etc/nginx/nginx.conf ":
server { listen 443 ssl http2; server_name ; root /usr/share/nginx/html/blank;
[…] (SSL-Konfiguration)
location /.well-known/matrix/server { default_type application/json; return 200 '{"m.server": ""}';
}
}
Synapse konfigurieren
Um den Synapse-Server konfigurieren zu können, brauchen Sie erst einmal eine Konfigurationsdatei. Die erstellt das Tool beim ersten Start freundlicherweise selber. Legen Sie ein Verzeichnis auf dem Containerhost an, in dem Synapse seine Daten speichert. In unserem Setup ist das "/var/ pods/synapse". Dann starten Sie den Container wie folgt:
podman run -it --rm \ --name synapse \ --volume /var/pods/ synapse:/data:Z \ -e SYNAPSE_SERVER_NAME=
\ -e SYNAPSE_REPORT_STATS=yes \ docker.io/matrixdotorg/ synapse:latest generate
Sollten Sie Docker statt Podman verwenden, müssen Sie das Kommando als root via docker run ausführen. Das "Z" am Ende der Volume-Angabe brauchen Sie auf Systemen mit aktivem SELinux. Der Schalter "SYNAPSE_REPORT_STATS" erlaubt Synapse, anonyme Betriebsstatistiken an die Entwickler zu senden. Wenn Sie das nicht wünschen, geben Sie hier "no" an.
Am Ende des Kommandos erhalten Sie eine Datei namens "homeserver.yaml" sowie eine "log.config" und einen Signing-Key im Verzeichnis "/var/pods/synapse". In der YAML-Datei finden Sie die Basiskonfiguration des Diensts, der Datenbank und auch ein "registration_shared_secret". Das sollten Sie an einem sicheren Ort abspeichern – es wird zur Registrierung neuer Nutzer benötigt, sollte aber nach dem initialen Setup aus der "homeserver.yaml" verschwinden.
Als Datenbank nutzt Synapse in der Basiskonfiguration SQLite. Das genügt für kleine Testinstallationen. Setzen Sie einen Synapse-Server für dutzende Nutzer und Chaträume auf, sollten Sie auf jeden Fall statt SQLite einen PostgreSQL-Server verwenden. Die Synapse-Dokumentation beschreibt ausführlich, wie Sie eine PostgreSQL-Datenbank einrichten, das muss aber nicht zwingend sofort mit der ersten Testinstallation passieren. Die Dokumentation beschreibt ebenfalls, wie Sie eine bestehende SQLite-Datenbank nachträglich zu PostgreSQL übertragen und den Synapse-Server passend umstellen. In unserem Testsetup bleiben wir bei SQLite.
Mit der passenden Konfiguration können Sie nun ihren Synapse-Container starten. Je nach Netzwerkkonfiguration betreiben Sie ihn auf der Host-IP mit dem Parameter "-p 8008:8008", um den HTTP-Port auf verfügbar zu machen. Unser Setup nutzt Synapse auf der Bridge via -- net virt_net --ip 192.168.122.26 --mac-address 53:54:C0:A8:7A:1A und damit mit seiner eigenen IP-Adresse. Erstellen Sie anschließend eine "service"-Definition für den Synapse-Server, sodass Systemd den Pod beim Systemstart ausführen kann.
Benutzer anlegen
Neue Benutzer registrieren Sie auf der Kommandozeile des Hosts im laufenden Synapse-Container:
podman exec -it synapse register_new_matrix_user -c /data/homeserver.yaml <username>
Geben Sie ein Passwort an und statten Sie den initialen Nutzer mit Admin-Rechten aus. In einem größeren Setup werden Sie natürlich nicht alle Nutzer manuell per CLI generieren. Für Synapse gibt es verschiedene Authentisierungs-Plug-ins, sodass Sie Single Sign-on mit verschiedenen ID-Providern verwenden können. Alternativ fügen Sie in der "homeserver.yaml" die Ziele "enable_registration = true" ein. Das ist aber mit Vorsicht zu genießen, denn damit darf sich jeder Nutzer mit Zugang zum Server einen Account erstellen. Diese Funktion sollten Sie nur im lokalen Netzwerk aktivieren, solange der Server noch nicht über das Internet zu erreichen ist.
Matrix trennt den Client vom Server. Daher verfügt der Synapse-Server selbst auch über keine Web-UI. Die Administration erfolgt über die CLI, die Rest-API oder externe Tools mit Zugang zur Admin-Rest-API. Um den Dienst zu nutzen, gibt es eine ganze Reihe verschiedener Clients. Der wohl populärste ist "Element". Den können Nutzer als Webdienst im Browser unter "" nutzen oder von dieser Seite Client-Apps für Windows, Linux oder macOS herunterladen. In den App-Stores von Apple und Google gibt es Element zudem kostenfrei für iOS und Android.
Im Element-Client geben Sie statt "" die URL Ihres Matrix-Servers, im Beispiel also "https://matrix. domain. com ein. Melden Sie sich mit dem initialen Benutzer und dem vergebenen Passwort an. Gleich am Anfang wird Element Sie auffordern, ein "Secure Backup" einzurichten und einen Security-Key für die Ende-zu-Ende-Verschlüsselung zu erstellen. Generieren Sie diesen Schlüssel und speichern ihn an einem sicheren Ort. Sie können danach neue Clients nur noch mit ihrem Konto verbinden, wenn Sie entweder diesen Schlüssel angeben oder eine Zweifaktor-Authentifizierung über einen bereits registrierten Client nutzen. An dieser Stelle empfiehlt es sich, einen mobilen Client auf Ihrem Handy mit dem Konto zu verknüpfen. Weitere Clients können Sie dann via QR-Code freischalten, den Elements auf dem Handy scannt und verifiziert.
User Interface für Admins
Neben Elements als Messaging-Client-App gibt es auch ein paar Admin-UI-Projekte. Diese funktionieren aber nur mit Einschränkungen. Die oben aufgeführte Reverse-Proxy-Konfiguration gibt nur die Messaging-API ("/_matrix" und "/_synapse/client") zum Internet hin frei, nicht aber die Admin-API ("/_synapse/admin"), und das sollte auch so bleiben. In unserem Beispiel könnten Sie jedoch eine Admin-Web-UI direkt auf dem Hosting-Server in einem weiteren Container starten:
podman run \ --net virt_net \ --ip \ --mac-address 52:54:C0:A8:7A:1b \ docker.io/awesometechnologies/synapse-admin
Direkt auf dem Hosting-Server rufen Sie die URL "http:// " im Browser auf. Im folgenden Verbindungsdialog geben Sie den Admin-User an und als Matrix-URL passend zum Beispiel "http://192.168.122.26:8008", da Sie hierfür die interne Netzwerkverbindung zwischen den Containern nutzen und nicht über den Proxy gehen. Verfügt Ihr Hosting-Server über keine GUI, können Sie den Applikationsport der Web-UI 192.168.122.27:80 auf gewohnte Weise via SSH zu Ihrem Client tunneln und dann den Browser dort verwenden.
Federation prüfen
An diesem Punkt läuft Ihr Synapse-Server und die lokal erstellten Nutzer können darüber kommunizieren. Jetzt ist es an der Zeit, die Verbindung zu anderen Matrix-Domänen zu testen. Prüfen Sie zunächst, ob die Federation-Einstellungen Ihres Servers korrekt konfiguriert sind. Gehen Sie dazu einfach auf die Webseite: "" und geben Sie Ihren Domainnamen ein. Der Federation-Tester prüft beide Discovery-Methoden via DNS und Well-Known-Rest-API. Zudem verifiziert der Service ihre HTTPS-Zertifikate. Erscheint hier alles in grün, können andere Matrix-Nutzer Ihren Server erreichen und Ihre Nutzer dürfen im Gegenzug die Kommunikation mit anderen Domänen starten.
Matrix verwaltet alle Chats in "Räumen". Private Chats sind für Matrix nichts anderes als Gruppen mit nur zwei Mitgliedern.
Die Kommunikation auf dem lokalen Server sowie mit anderen Matrix-Installationen erfolgt mit Ende-zu-Ende-Verschlüsselung. Die Nachrichten selbst sichert das Synapse-Setup verschlüsselt in der angegebenen Datenbank.
Brücken bauen
Ein Matrix-Setup mit Synapse als Server und Element als universellem Client genügt für die sichere interne Kommunikation und Chats mit anderen Matrix-Nutzern. Allerdings chattet der Großteil der Nutzer auf anderen Plattformen, allen voran WhatsApp. Eine der großen Stärken von Matrix sind die Bridges. Mit diesen Plug-ins stellt Synapse über Bots Verbindungen zu anderen Diensten wie WhatsApp, Google Chat, Slack, Discord oder Telegram her. Mit einem umfassenden Synapse-Setup brauchen die Anwender also nur noch einen einzigen Matrix-Client, über den sie alle Chats, egal mit welcher Plattform, erledigen. Das Bridge-Setup ist für viele Plug-ins recht ähnlich. Wir stellen hier stellvertretend die wohl wichtigste Bridge vor: WhatsApp.
Die Bridge läuft als eigenständige Applikation und kann theoretisch auch auf einem ganz anderen Rechner als Synapse arbeiten. In unserem Setup läuft "Mautrix Whatsapp" als eigener Container mit einer eigenen IP-Adresse () auf demselben System wie Synapse. Das Plug-in braucht ein eigenes Verzeichnis und eine eigene Datenbank. Wie bei Synapse gilt auch hier: Für Testinstallationen genügt SQLite, größere Setups sollten PostgreSQL verwenden. Legen Sie das Verzeichnis "/var/pods/mautrix_whatsapp" an und starten Sie den Plug-in-Container einmalig:
podman run --rm \ --name mautrix_whatsapp \ --volume /var/pods/mautrix_whatsapp:/data:Z \ whatsapp:latest
Die Bridge stellt beim ersten Start fest, dass es keine Konfigurationsdatei gibt. Der Container legt daher im angegebenen Verzeichnis eine "config.yaml" mit Standard-Settings an und stoppt. Passen Sie die Datei für Ihre Installation an. Die wesentlichen Einträge für unser Setup sehen dabei so aus:
homeserver: address: domain: domain.com appservice: address: http://192.168.122.31:29318 hostname: 0.0.0.0 port: 29318 database: type: sqlite3 uri: whatsapp.db
Zudem müssen Sie die Einstellung "Permission" passend zu Ihrer Domäne konfigurieren, sodass nur die Nutzer Ihrer Domain die Bridge aktiv verwenden dürfen.
permissions: "*": relay "": user "@admin:domain.com": admin
Den Synapse-Server spricht das Plug-in direkt über die interne Adresse an und stellt im Gegenzug den eigenen Dienst auf der internen IP-Adresse des Containers zur Verfügung. Abweichend zur Dokumentation des Plug-ins enthält die Datenbank-URL bei SQLite nur den Dateinamen der Datenbank ohne Pfad und ohne "sqlite://" am Anfang. Beim nächsten Start des Containers geben Sie die IP-Informationen mit an: --net virt_net --ip 192.168.122.31 --mac-address 52:54:C0:A8:7A:1f. Auch hier gilt: Wenn Sie Ihre Container ohne Bridge-Network betreiben, stellen Sie alle Adressen auf und geben statt der Netzwerkinformationen nur den Port "-p 29318: 29318" mit an.
Beim zweiten Aufruf erstellt das Plug-in die Datenbank und prüft die Verbindung zum Synapse-Server. Passt das Setup, generiert "mautrix-whatsapp" eine "registration.yaml" und stoppt den Container. Diese Registration enthält vereinfacht gesagt die Zugangsdaten des Plug-ins zum Synapse-Server. Erstellen Sie eine Kopie der "registration.yaml"-Datei im Verzeichnis des Synapse-Servers, am besten gleich mit dem Plug-in-Namen, also:
cp /var/pods/mautrix_whatsapp/registration.yaml /var/pods/synapse/registration_whatsapp.yaml