Matrix ist ein neues Kommunikationssystem, allerdings nicht mit dem Anspruch, das nächste coole, hippe Teil zu werden, sondern Matrix setzt von Anfang an auf Integration und will Brücken zu anderen Systemen bauen.

Die Kommunikation im Internet hat sich leider zu einer zerklüfteten Inselwelt entwickelt, in der jede Gruppe mit ihrem eigenen System arbeitet und inkompatibel zur Außenwelt ist. Da der Umzug von einem Netzwerk in ein anderes umständlich ist und viele Netzwerke ihre speziellen Vorteile haben, will Matrix die Nutzer eben dort nicht wegholen, sondern dort erreichen. Jeder darf das System nutzen, das ihm gefällt – egal ob XMPP, IRC, Whatsapp, Telegram, Hangouts, Facebook oder SMS – und Matrix kommuniziert mit ihnen. Ein Ansatz, der mir wahnsinnig gut gefällt!

Wer sich Matrix erst einmal nur ansehen will, kann den Webclient Element benutzen und einen öffentlichen Raum wie #matrix:matrix.org oder #linux:matrix.org besuchen. Wem es dann gefällt, der kann sich einen eigenen Zugang einrichten, am besten auf einem der alternativen Server aus dem Hello-Matrix-Verzeichnis, damit im Netzwerk nicht ein riesiger Klumpen bei matrix.org entsteht.

An Matrix ist aber auch das gute, dass sich jeder leicht seinen eigenen Server einrichten kann, so dass alle Daten in der eigenen Hand liegen. Eine Anleitung dafür befindet sich unter anderem in Kuketz' Blog, in der Dokumentation von Matrix-Synapse und hier auf dieser Seite.

Gründe für Matrix

Früher habe ich für fast alle Kurzkommunikation mit anderen Menschen Whatsapp und Jabber/XMPP genutzt, aber mit beiden Systemen hatte ich Probleme, für die ich keine Lösung gefunden habe. Wichtig ist für mich, dass ich unterwegs am Handy, daheim am Laptop oder manchmal auch spontan an einem anderen Rechner (z. B. am Arbeitsplatz) Mitteilungen lesen oder schreiben kann.

Mit Matrix habe ich eine Lösung gefunden, die meinen Wünschen am besten gerecht wird. Mit dem Server Synapse konnte ich relativ schnell und einfach einen eigenen Home-Server einrichten, der mich unabhängig vom Wohlwollen anderer macht. Zur Nutzung von Matrix gibt es über F-Driod die App Element fürs Handy und am Laptop nutze ich Element als Webclient, was mir den Vorteil bietet, dass ich von überall darauf zugreifen kann.

Für die Teilnahme an Matrix ist auch keine Telefonnummer und keine E-Mailadresse notwendig. Man kann solche Merkmale mit seinem Konto verknüpfen und in einem Verzeichnis eintragen, aber man muss es nicht tun.

Bisher (April 2019) ist die Verschlüsselung von Matrix noch in Entwicklung, aber ich benutze sie ohne gravierende Probleme – einfach in den Raumeinstellungen aktivieren. Für Matrix findet jede Kommunikation in einem Raum statt, in dem man sich selbst und beliebig viele andere Personen befinden können; man kann auch allein in einem Raum bleiben und auf diese Weise Notizen zwischen Geräten austauschen oder unterschiedliche Räume mit der gleichen Person zu verschiedenen Themen betreiben.

Über Matrix lassen sich Bilder, Videos und Dateien versenden und diese werden über den Home-Server (nicht über einen zusätzlichen Upload-Server) ausgetauscht, so dass Inhalte vom Handy auch im Verlauf am Laptop und umgekehrt zu sehen sind. Durch diese Synchronisation über den Home-Server werden auch gelesenen Nachrichten vom Handy am Laptop nicht wieder vorlegt.

In Räumen kann man eine URL-Vorschau aktivieren, so dass im Verlauf eine Info zur Webseite eingeblendet wird. Diese wird vom Home-Server generiert, wodurch der Webseite nicht die IP-Adresse des Clients verraten wird. Die Vorschau wird für alle URLs in einer Nachricht angezeigt und wenn sie stört, kann man sie ausblenden.

Für Textnachrichten unterstützt Matrix die Formatierung mit Markdown, was in Gesprächen über Programmausgaben oder Dateieinträge richtig von Vorteil ist, bis dahin dass an der Box für Blockcode ein Knopf zum Kopieren hängt. Weiterhin gibt es eine Unterstützung für die Eingabe von Emojis und es lassen sich Sticker versenden.

Eine Nachricht kann man auch im Nachhinein löschen (bearbeiten ist geplant) und mit der notwendigen Berechtigung sogar die Nachrichten anderer, um größere Runden entsprechend zu moderieren. Für öffentliche Räume kann der Verlauf über die Webseite view.matrix eingesehen werden. Weiterhin kann man mit Element über Räume auch Telefonate und Videokonferenzen führen oder den Bildschirm übertragen.

Das Konzept des Home-Servers

Man kann sich auch mehrere Profile erstellen oder unterschiedliche Server nutzen, um ggf. Arbeit und privates zu trennen.

Weitere Informationsquellen

Den Home-Server einrichten

Synapse unter Debian einrichten

Wer Debian-Buster einsetzt, kann sich über Backports nur eine veraltete Version von Synapse installieren. Auch in Bullseye wird Synapse nicht direkt enthalten sein, weil so häufig neue Versionen erscheinen, die nicht zum Zweijahreszyklus von Debian passen.

Gegenwärtig (Juni 2021) in der Freeze-Phase für Bullseye wird die Version in Backports auch nicht mehr aktualisiert, weshalb man Fasttrack einsetzen muss:

% echo 'deb http://ftp.de.debian.org/debian/ buster-backports main' |sudo tee -a /etc/apt/sources.list
% sudo apt update
% sudo apt install -t buster-backports fasttrack-archive-keyring

% echo 'deb http://fasttrack.debian.net/debian/ buster-fasttrack main' |sudo tee -a /etc/apt/sources.list
% sudo apt update
% sudo apt install -t buster-backports matrix-synapse/buster-fasttrack

Für ältere Versionen bietet das Matrix-Projekt ein Repository an. Damit ist die Installation und die Aktualisierung gewohnt einfach.

% curl https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg |sudo dd of=/etc/apt/trusted.gpg.d/matrix-org.gpg
% echo "deb https://packages.matrix.org/debian/ stretch main" |sudo tee -a /etc/apt/sources.list
% sudo apt update && sudo apt install matrix-synapse-py3

Die Einstellungen für Synapse sind in der Datei /etc/matrix-synapse/homeserver.yaml. Hier sind nur die relevanten Anpassungen gezeigt, aber besser ist es, sich die vollständige Datei anzusehen.

public_baseurl: https://alea.gnuu.de/
admin_contact: 'mailto:admin@example.org'

database:
  name: psycopg2
  args:
    dbname: matrix
    user: matrix-synapse
    host: /run/postgresql
    application_name: synapse

url_preview_enabled: true
url_preview_ip_range_blacklist:
  - '127.0.0.0/8'
  - '10.0.0.0/8'
  - '172.16.0.0/12'
  - '192.168.0.0/16'
  - 'fe80::/10'

enable_metrics: false
macaroon_secret_key: "Geheimen Schlüssel mit `pwgen -s 64 1` erzeugen"
expire_access_token: true

Bei Matrix geschieht der Abruf der URL-Vorschau vom Server, was gegenüber Whatsapp den Vorteil hat, dass die Adresse des Nutzers nicht durch Versenden von Links erspäht werden kann – die Serveradresse ist durch die Federation eh bekannt. Allerdings sollten lokale Adresse vom Abruf ausgeschlossen werden, damit interne Webseiten nicht unberechtigt ausgespäht werden können.

Einrichten der Datenbank

Als Datenbanksystem kann man zwar sqlite nutzen, aber wenn nichts gegen den Einsatz von Postgres spricht, sollte man von Beginn an dieses verwenden. Damit hierbei die passwortlose Anmeldung funktioniert, muss der Datenbanknutzer genauso wie der Systembenutzer des Synapse-Prozesses (systemctl show -pUser matrix-synapse.service) heißen. Die Datenbank und der Benutzer müssen vor dem ersten Start mit folgendem Befehl erstellt werden:

% sudo -u postgres sh -c 'createuser matrix-synapse
  && createdb -O matrix-synapse -l C -E UTF-8 -T template0 matrix'

Bei der Dienstverwaltung muss noch eingestellt werden, dass der Start von Synapse erst nach Postgres erfolgt:

% sudo systemctl edit matrix-synapse.service
[Unit]
After=network-online.target postgresql.service

Neben den Parametern für connect können in der homeserver.yaml für database noch Parameter für das Connection-Pooling angegeben werden.

Postgres Tuning

Speicherbegrenzung von Synapse

Da Synapse sehr zum Speichergebrauch neigt, ist es ratsam diesem durch den Kernel eine Grenze zu setzen, damit das Gesamtsystem nicht beeinträchtigt wird. Eine Anpassung des Wertes SYNAPSE_CACHE_FACTOR hat bei mir langfristig keine Wirkung gezeigt, da dieser Wert nur bei der Initialisierung der Caches genutzt wird und keine Begrenzung darstellt. Ebenso konnte ich langfristig mit jemalloc keine spürbare Verbesserung erreichen.

% sudo systemctl edit matrix-synapse.service
[Service]
MemoryMax=80%

Sicherheitsbeschränkung mit AppArmor

Da keine Software fehlerfrei ist, bietet der Linux-Kernel die Möglichkeit, mit AppArmor die Zugriffsreche von Prozessen stärker einzugrenzen. Mithilfe eines Profils legt man fest, welche Zugriffe gestattet sind, und alles was darüber hinaus geht, wird unterbunden. Dieses Profil speichert man unter /etc/apparmor.d/matrix-synapse ab und aktiviert es mit apparmor_parser -r /etc/apparmor.d/matrix-synapse. Damit das Profil für den Prozess verwendet wird, muss die Information in der Systemd-Unit angegeben werden:

% sudo systemctl edit matrix-synapse.service
[Service]
AppArmorProfile=matrix-synapse

Im Journal sieht man gegebenenfalls Verstöße gegen die Regeln: journalctl -t audit. Sollte es zu Problemen kommen, kann man das Profil auch in den Testmodus schalten, womit die Verstöße protokolliert, aber nicht unterbunden werden. Hierfür ändert man in der Profildatei die Definition wie folgt ab und lädt das Profil mit dem obigen Befehl neu (ein Neustart von Synapse ist nicht erforderlich):

profile matrix-synapse flags=(complain) {

Protokollierung mit Journal einrichten

In der Konfiguration des Dienstes kann man auch noch den Namen angeben, der von journal verwendet werden soll, damit journalctl -t synapse (statt python) funktioniert:

[Service]
SyslogIdentifier=synapse

In Synapse selbst kann man auch noch die Protokollierung an journal anpassen, indem man das Paket python3-systemd installiert und in /etc/matrix-synapse/log.yaml folgende Anpassungen vornimmt:

@@ -4,6 +4,8 @@
 formatters:
   precise:
    format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s- %(message)s'
+  journal_fmt:
+   format: '%(name)s: [%(request)s] %(message)s'

 filters:
   context:
@@ -16,12 +18,17 @@
     formatter: precise
     filename: /var/log/matrix-synapse/homeserver.log
     maxBytes: 104857600
-    backupCount: 10
+    backupCount: 6
     filters: [context]
   console:
     class: logging.StreamHandler
     formatter: precise
     level: WARN
+  journal:
+    class: systemd.journal.JournalHandler
+    formatter: journal_fmt
+    filters: [context]
+    SYSLOG_IDENTIFIER: synapse

 loggers:
     synapse:
@@ -32,4 +39,4 @@

 root:
     level: INFO
-    handlers: [file, console]
+    handlers: [file, journal]

Nginx einrichten

In der Anfangszeit vor 2019 wurde Synapse direkt ins Internet gestellt. Bis auf sehr begrenzte Anwendungsfälle, wo eine Transportverschlüsselung nicht benötigt wird, ist es jedoch sinnvoller, einen Reverse-Proxy zu verwenden, der sich um TLS kümmert und gegebenenfalls noch weitere Maßnahmen genutzt werden kann. Die Einrichtung ist recht leicht, da nur alle Zugriffe

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    root /srv/www/default;

    ssl_certificate /etc/letsencrypt/live/HOST/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/HOST/privkey.pem;

    add_header Strict-Transport-Security "max-age=15552000; includeSubdomains; preload";

    location /_matrix/ {
        access_log off;
        proxy_pass http://[::1]:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /.well-known/matrix/server {
        access_log off;
        add_header Access-Control-Allow-Origin *;
        add_header Content-type application/json;
        return 200 '{"m.server": "alea.gnuu.de:443"}';
    }

    location /.well-known/matrix/ {
        access_log off;
        proxy_pass http://[::1]:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Funktionstest

Wenn alles durch ist, den Dienst (neu-)starten und dann sollte er auf dem Port 8008 lauschen.

% sudo systemctl restart matrix-synapse.service
% sudo ss -tlp |grep 8008
LISTEN     0      0        ::1:8008        :::*         users:(("python",pid=24088,fd=10))

Ob der Server für Clients erreichbar ist, kann man per netcat oder telnet prüfen (auch fürs System-Monitoring hilfreich):

% netcat localhost 8008 <<<$'GET /_matrix/client/versions HTTP/1.0\r\n\r'
HTTP/1.0 200 OK
Content-Length: 54
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Server: Synapse/0.29.0
Cache-Control: no-cache, no-store, must-revalidate
Date: Sun, 20 May 2018 15:16:36 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Content-Type: application/json

{"versions": ["r0.0.1", "r0.1.0", "r0.2.0", "r0.3.0"]}

Im Log /var/log/matrix-synapse/homeserver.log sollte dann etwas in dieser Art stehen:

2018-05-20 17:12:18,831 - synapse.access.http.8008 - 95 - INFO - GET-65532- - - 8008 - Received request: GET /_matrix/client/versions
2018-05-20 17:12:18,832 - synapse.access.http.8008 - 129 - INFO - GET-65532- - - 8008 - {None} Processed request: 1ms (0ms, 0ms) (0ms/0ms/0) 54B 200 "GET /_matrix/client/versions HTTP/1.0" "None"

Ob der Server für andere Server erreichbar ist, also ob die Federation funktioniert, kann man über die Adresse https://matrix.org/federationtester/api/report?server_name=… mit dem entsprechenden Servernamen prüfen. In der Ausgabe sollte irgendwo "AllChecksOK": true erscheinen und am Ende sollte "ConnectionErrors": {} leer sein. Alternativ dazu gibt es noch den Fed-tester.

Worker einrichten

Worker sind noch eine recht junge Entwicklung (Stand: Mai 2019) von Synapse, aber ihr Einsatz lohnt sich. Ziel der Entwicklung ist es, Teile aus dem Hauptprozess herauszulösen und in eigenständige Prozesse zu gliedern. Auf diese Weise kann man …

Element einrichten

Element ist ein Webclient für Matrix, der vom Matrix-Team entwickelt wird. Man kann ihn direkt von app.element.io aus nutzen oder man richtet sich eine eigene Instanz ein. Es gibt zwar ein Debian-Paket, aber dieses hängt vom Paket gconf ab und zieht auf einem Server einen Rattenschwanz an Paketen hinterher. Deshalb verwende ich das allgemeine Paket und entpacke es in /srv/www/m.jo-so.de.

In dem Verzeichnis liegt die Datei config.sample.json, welche nach config.json kopiert werden muss. Darin sollte bei default_hs_url die Adresse des eigenen Matrix-Servers eingetragen werden. Ich habe bei mir die Anmeldung von Gästen deaktiviert "disable_guests": true, bei den Raum-Servern meinen eigenen ergänzt und bei piwik den Schlüssel url durch X-url ersetzt, damit auch sicher kein Piwik angesprochen wird.

Matrix nutzt zwei verschiedene Kommunikationswege: 8008 für Clients und 8448 für andere Server, so wie es auch bei XMPP der Fall ist. Da Matrix eine REST-Schnittstelle verwendet, kann man den Verkehr zum eigentlichen Matrix-Dienst durch einen Nginx leiten, so dass der Matrix-Dienst nicht als root laufen muss und man die Möglichkeiten Nginx' nutzen kann: SSL-Zertifikate, HTTP/2.0, Einschränken der IP-Adressbereiche, HTTP-Authentifizierung und die Vermischung mit anderen Inhalten, denn Matrix nutzt nur das Verzeichnis /_matrix.

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    root /srv/www/default;

    location /_matrix/ {
        access_log off;
        proxy_pass http://[::1]:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    location /.well-known/matrix/server {
            access_log off;
            add_header Access-Control-Allow-Origin *;
            return 200 '{"m.server": "alea.gnuu.de:443"}';
    }

    location /.well-known/matrix/ {
        access_log off;
        proxy_pass http://[::1]:8008;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    location /m/ {
        access_log off;
        alias /srv/www/m.jo-so.de/;
    }
}

% sudo systemctl reload nginx.service

Als einfachere Funktionsprüfung kann man im Browser die Adresse /_matrix/client/versions seines Servers aufrufen und sollte eine Ausgabe ähnlich wie bei https://matrix.org/_matrix/client/versions erhalten.

Ein kleines Skript für die regelmäßige Aktualisierung von Element habe ich in der Anleitung zu jq beschrieben.

Neuen Benutzer anlegen

Man kann es allen Nutzern erlauben, ein neues Konto über die Weboberfläche anzulegen, in dem man in der Serverkonfiguration homeserver.yaml die Option enable_registration: true setzt. Falls man jedoch nur einen geschlossenen Nutzerkreis haben will, kann man in der Serverkonfiguration bei registration_shared_secret: "<SECRET KEY>" eine geheime Zeichenkette (generiert mit pwgen -s 64 1) eintragen und dann mit dem Kommandozeilenprogramm register_new_matrix_user neue Benutzer anlegen:

% register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008
New user localpart [root]: user
Password:
Confirm password:
Make admin [no]:
Sending registration request...
Success.

Das Zurücksetzen des Passworts gibt es die händische Bearbeitung der Datenbank und eine API-Funktion, die man mit curl aufrufen kann.

TURN für Video- und Audioverbindungen einrichten

Für Video- und Audioverbindungen ist neben dem Matrix-Server noch ein TURN-Server notwendig, der zwischen Geräten vermittelt, die sich nicht direkt erreichen können; z. B. durch NAT. Direkt von Debian gibt es das Paket coturn.

Nach der Installation (apt install coturn) muss die Konfigurationsdatei /etc/turnserver.conf wie folgt angepasst werden (Entnommen aus der Doku von synapse):

lt-cred-mech
use-auth-secret
static-auth-secret=Geheimen Schlüssel mit `pwgen -s 64 1` erzeugen
realm=jo-so.de
no-tcp-relay
cert=/etc/letsencrypt/live/host/fullchain.pem
pkey=/etc/letsencrypt/live/host/privkey.pem
no-multicast-peers
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
pidfile="/dev/null"
secure-stun
mobility
no-tlsv1

Den geheimen Schlüssel und die TURN-Verbindungen muss man noch in der homeserver.yaml eintragen und den Synapse-Server neustarten.

turn_uris:
  - "turn:alea.gnuu.de:3478?transport=udp"
  - "turn:alea.gnuu.de:3478?transport=tcp"

turn_shared_secret=Geheimer Schlüssel

Die Konfiguration für Systemd wird bei der Installation automatisch generiert, weshalb ich sie durch folgende ersetzt (systemctl edit --full coturn.service) habe. Damit läuft der Prozess auch nicht mehr als Benutzer root.

# https://github.com/coturn/coturn/blob/master/rpm/turnserver.service.fc

[Unit]
Description=coturn
Documentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)
After=network.target

[Service]
User=turnserver
Group=turnserver
SupplementaryGroups=ssl-cert
PIDFile=/run/turnserver.pid
ExecStart=/usr/bin/turnserver -c /etc/turnserver.conf --log-file stdout
Restart=on-abort

LimitNOFILE=999999
LimitNPROC=60000
LimitRTPRIO=infinity
LimitRTTIME=7000000
CPUSchedulingPolicy=other
UMask=0007
NoNewPrivileges=yes

[Install]
WantedBy=multi-user.target

AppArmor /etc/apparmor.d/usr.bin.turnserver

include <tunables/global>

profile /usr/bin/turnserver {
    include <abstractions/base>
    include <abstractions/ssl_certs>
    include <abstractions/ssl_keys>

    /etc/turnserver.conf r,
    owner /var/lib/turn/turndb rwk,
}

Sicherheitshinweis: Trotz der Einstellungen für Verschlüsselung des TURN-Servers konnte ich mit Wireshark noch die Inhalte der Verbindung einsehen. Ich habe nichts gefunden, wie ich die TURN-Verbindung weiter absichern kann.

Source: laptop (Port: 59697)
Destination: alea.gnuu.de (Port: 3478)
Protocol: STUN
Info: Allocate Request UDP lifetime: 3600 user: 1527072691:@test:alea.gnuu.de realm: alea.gnuu.de with nonce

Source: laptop (Port: 59697)
Destination: alea.gnuu.de (Port: 3478)
Protocol: STUN
Info: CreatePermission Request XOR-PEER-ADDRESS: 192.168.178.21:48261 user: 1527072691:@test:alea.gnuu.de realm: alea.gnuu.de with nonce

Im Wireshark konnte ich aber auch beobachten, dass meine beiden Testgeräte direkt per IPv6 kommuniziert haben, ohne den Weg über den TURN-Server.

Wechsel der Datenbank zu Postgres

Ich habe ursprünglich mit sqlite begonnen und irgendwann die Datenbank auf Postgres umgestellt. Hier die Befehle zum Einrichten des Benutzers und der Datenbank. Dabei ist darauf zu achten, dass der Benutzername identisch mit dem Systembenutzer seien muss, unter dem auch der Dienst läuft, sonst funktioniert die passwortlose Anmeldung per Socket nicht; systemctl show -pUser matrix-synapse.service.

% sudo apt install python-psycopg2
% sudo -u postgres sh -c 'createuser matrix-synapse
  && createdb -O matrix-synapse -l C.UTF-8 -T template0 matrix'

In der Konfiguration homeserver.yaml müssen noch die Einstellungen wie folgt geändert werden:

# Database configuration
database:
  # The database engine name
  name: psycopg2
  # Arguments to pass to the engine
  args:
    database: matrix
    user: matrix-synapse
    host: /run/postgresql
    application_name: matrix-synapse

Zusätzlich zu den Parametern für connect kann man noch Parameter für das Connection-Pooling angeben. Leider ist zu dem von Synapse genutzten Connection-Pool zu sagen, dass es ungenutzte (idle) Verbindungen nicht automatisch schließt. Eine Lösung hierfür habe ich noch nicht gefunden.

Bei Systemd sollte man dann noch angeben, dass der Server erst nach Postgres gestartet wird:

% sudo systemctl edit matrix-synapse.service
[Unit]
After=network-online.target postgresql.service

Für die Datenmigration von sqlite zu Postgres gibt es das Programm synapse_port_db. Dieses kann auch mehrfach ausgeführt werden, falls man den Dienst weiterlaufen lässt und eine Kopie der sqlite-Datenbank verwendet hat oder es zu Fehlern kam. Ich habe aber einfach für die gesamte Zeit den Dienst bei mir abgeschaltet.

% cd /tmp && sudo -u matrix-synapse synapse_port_db -v --curses \
  --sqlite-database /var/lib/matrix-synapse/homeserver.db \
  --postgres-config /etc/matrix-synapse/homeserver.yaml

Wenn es zu einem Fehler kommt und in der Datei port-synapse.log etwas von Failed to insert: room_depth steht, dann zuerst einmal nachsehen, ob der Fehler 3214 bereits gelöst ist oder ggf. den ALTER TABLE-Befehl von dort ausführen und die Migration noch einmal starten.

Wartungsarbeiten

Auf der Webseite von Matrix werden diverse Anleitungen zur Wartung von Synapse und Moderation von Matrix angeboten.

Datensicherung

Wichtig für eine Wiederherstellung einer Matrix-Installation sind

Um das Backup zu verkleinern kann man die Verzeischnisse /var/lib/matrix-synapse/media/(remote_|url_cache)*/* auslassen. Deren Inhalt lässt sich im Nachhinein über andere Server wiederherstellen.

Bei der Wiederherstellung des Systems muss man mit dem Zugangsschlüssel (Access-Token) eines Admin-Benutzers den Cache zurücksetzen, damit Synapse die Dateien, die vom Backup ausgeschlossen waren, neu beschafft. Den Zugangsschlüssel findet man in Element unter Einstellungen, Hilfe, Fortgeschritten und nutzt diesen für purge_remote_media mit aktuellem Zeitstempel:

curl -H "Authorization: Bearer <access_token>" -d '' "http://localhost:8008/_synapse/admin/v1/purge_media_cache?before_ts=$(date +%s000)"

(
  echo 'DELETE FROM remote_media_cache WHERE filesystem_id NOT IN ('; \
  find /var/lib/matrix-synapse/media/remote_content -type f -printf '%P\n' \
  |sed "s,^[^/]*/,',; s,/,,g; s/\$/',/; \$s/,\$//" |tail; \
  echo ');'; \
  echo 'DELETE FROM remote_media_cache_thumbnails WHERE media_id NOT IN (SELECT media_id FROM remote_media_cache);'
) > /tmp/cleanup_rmc.sql

Ungenutzte Räume entfernen

Wenn Nutzer einen Raum verlassen, der über mehrere Server verteilt liegt, bleiben auf dem eigenen Server die alten Nachrichten zurück. Da diese nicht mehr genutzt werden, ist es sinnvoll, diese zu entfernen:

mx_token=<Token eines Admins>
for room in $(curl -s --header "Authorization: Bearer $mx_token" \
  'http://localhost:8008/_synapse/admin/v1/rooms?limit=800' \
  |jq -r '[ .rooms[] | select(.joined_local_members == 0) ] |sort_by(.state_events) | .[].room_id')
do
    echo -n "Purging $room: "
    time curl -s -o /dev/null --header "Authorization: Bearer $mx_token" \
      -X POST -H "Content-Type: application/json" -d "{ \"room_id\": \"$room\" }" \
      'http://localhost:8008/_synapse/admin/v1/purge_room'
done

state_groups_state aufräumen

In der Tabelle state_groups_state legt Synapse irgendwelche Daten ab (weiß jemand welche? Stift oben rechts nutzen), die zum Teil redundant sind. Daher kann man diese Tabelle mit dem Programm rust-synapse-compress-state aufräumen und somit den Speicherverbrauch eindämmen.

Wer Rust installiert hat, kompiliert das Programm besser selbst aus den Quellen, denn Releases passieren eher selten:

cargo install --git https://github.com/matrix-org/rust-synapse-compress-state synapse_compress_state

Danach liegt das Programm im Verzeichnis ~/.cargo/bin/synapse-compress-state. Beim Aufruf erstellt es aber nur eine SQL-Dateien, die die eigentlichen Änderungen beschreiben. Man muss also nach jedem Durchlauf des Programms noch das entstandene SQL-Skript ausführen. Daher habe ich mir das Hilfsprogramm synapse-clear-state erstellt, um auch alle anderen Schritte dafür durchzuführen. Dieses Hilfsprogramm rufe ich mithilfe von Systemd auf, damit es im Hintergrund läuft (bei mir dauert es über 2 Stunden) und ich die Meldungen im Nachhinein prüfen kann

% sudo systemd-run --nice=4 -pCPUSchedulingPolicy=batch \
  -pIOSchedulingClass=idle --uid=matrix-synapse --collect \
  --unit=synapse-clear-state ~/bin/synapse-clear-state
% journalctl -Stoday -u synapse-clear-state

Das Programm hat nämlich die Macke und erzeugt ein größeres Ergebnis als der Ausgangszustand. Da auch die Prüfung auf die Korrektheit des neuen Zustands teilweise sehr lange dauert, kann man mit der Option -m bei synapse-compress-state die Mindestanzahl an Tabellenzeilen angeben, für die der neue Zustand genommen wird. Abgesehen von dieser Macke liefert das Programm aber teilweise eine Reduktion auf 10 % (sic!) bei einigen Räumen.

Synapse muss während der Ausführung nicht angehalten werden, sodass es egal ist, wie lange das Programm läuft oder ob man es zwischendurch abbricht. Ich rufe es bei mir unregelmäßig alle paar Wochen auf.

device_inbox aufräumen

Die Schema-Definition der Datenbank von Synapse ist piep. Daher werden Einträge in der Tabelle device_inbox nicht gelöscht, wenn die dazugehörigen Geräte gelöscht werden. Mit folgendem SQL-Befehl kann man dies händisch erledigen:

DELETE
-- SELECT COUNT(*)
FROM device_inbox
WHERE device_id IN (SELECT device_id FROM devices WHERE hidden = true)
  OR device_id NOT IN (SELECT device_id FROM devices);

event_forward_extremities aufräumen

Wenn ein Server offline ist, kommen die Daten im Nachhinein nicht immer in der korrekten Reihenfolge an. Dadurch kann es passieren, dass Synapse in der Tabelle event_forward_extremities ungünstige Einträge erzeugt, die dazu führen, dass Synapse sehr viel Arbeitsspeicher verbraucht und der Dienst teilweise unbenutzbar wird. Daher sollte man regelmäßig prüfen, ob diese ungünstigen Einträge entstanden sind und bei mehr als fünf diese entfernen. Ein paar wenige stören nicht und man kann sie belassen, weil sonst Synapse abgeschaltet werden muss (was potentiell zu neuen fehlerhaften Einträgen führt).

Ich beobachte diese fehlerhaften Einträge auch noch mit Synapse 1.34, aber ich prüfe auch nur etwa einmal im Monat darauf. Zum Entfernen verwende ich ein angepasstes Skript , das ich anhand des Beitrags im Bugtracker erstellt habe:

sudo -u matrix-synapse LC_ALL=C.UTF-8 psql -f matrix-clean-extremities.sql matrix

Alte Anhänge löschen

Die beiden Verzeichnisse mit remote in /var/lib/matrix-synapse/media können mit der Zeit verdammt groß werden. Sie enthalten Bilder, Video und Dateien, die Nutzer auf anderen Servern in Räume geschickt haben. Nach einem gewissen Zeitraum sind die Dateien aber nicht mehr von Bedeutung und können gelöscht werden. Sollte doch einmal ein Nutzer auf dem lokalen Server so weit zurück scrollen oder springen, werden die Datei von anderen Servern wieder geholt, da mindestens der Ursprungsserver diese als lokale Daten betrachten und sie nicht löschen sollte.

Aber sicher ist dies nicht und bisher habe ich auch noch keine Möglichkeit gefunden, Chats zu exportieren. Wer also den nötigen Festplattenplatz hat, sollte die Dateien lieber liegenlassen, denn das Löschen betrifft alle Räume, inklusive privater, verschlüsselter Chats mit Urlaubsbildern und Dokumenten.

Purge Remote Media API

curl -H "Authorization: Bearer <access_token>" -d '' \
  "http://localhost:8008/_synapse/admin/v1/purge_media_cache?before_ts=$(date -d-6months +%s)000"

Alte Nachrichten löschen

Räume, in denen viel geschrieben wird, wachsen dementsprechend schnell an. Wer auf seinem Server Platz schaffen will oder wer alte Nachrichten aufgrund der Datensparsamkeit beseitigen möchte, kann dies für einzelne Räume durchführen.

Jedoch gilt wie oben bei den alten Anhängen: Sollte ein Nutzer die alten Nachrichten wieder anfragen, werden diese von den Nachbarservern beschafft, sofern sie dort noch verfügbar sind. Für private Unterhaltungen könnten das einige Nutzer nicht so lustig auffassen, wenn sie auf die Konzertpläne vom letzten Jahr oder die Glückwünsche vom letzten runden Geburtstag nicht mehr zugreifen können. Daher: Wer den Platz hat, sollte die Nachrichten besser aufheben.

curl -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{ "delete_local_events": false, "purge_up_to_ts": '$(date -d-6months +%s)000' }' \
  "http://localhost:8008/_synapse/admin/v1/purge_history/$room_id"

Purge History

Räume aus der Datenbank kratzen

Ich habe bei mir einen kaputten Zustand des Synapse-Servers erreicht, sodass ich dem Raum #matrix:matrix.org nicht mehr beitreten konnte, ihn aber auch nicht aus Element entfernen konnte. Es gibt im git das Programm nuke-room-from-db, mit dem man die Datenbank bereinigen kann.

Unerwünschte Räume entfernen

Matrix ist so entworfen, dass der Administrator eines Servers nicht in den Inhalt eines Raumes eingreifen kann. Wenn in einem Raum Nachrichten und Anhänge ausgetauscht werden, die vom Administrator nicht erwünscht sind, kann der Administrator nur den kompletten Raum vom Server löschen. Konkret: Wenn in einem Raum niemand Spamer und störende Nutzer hinauswirft, kann der Serveradministrator nichts tun – er hat technisch keine Möglichkeiten, die Benutzer zu entfernen, weil der Raum über alle beteiligten Server verteilt liegt und er die Struktur mit händischen Eingriffen zerstören würde.

Der folgende Aufruf löscht den Raum mit der MX-ID $room_id und blockiert den erneuten Beitritt zu dem Raum. Die Teilnehmer des lokalen Servers werden alle vom Raum abgemeldet und in einen neuen Raum eingetragen, in dem der Nutzer @abuse:example.com Administrator ist und die Nutzer keine Schreibrechte haben. Als Information erscheint im neuen Raum die Nachricht message. Den alten Raum würde ich erst in einem zweiten Schritt durch die normale Funktion zum Aufräumen aus der Datenbank entfernen, damit der Aufruf nicht zu lange dauert.

curl -H "Authorization: Bearer <access_token>" \
  -X DELETE -d '{
    "new_room_user_id": "@abuse:example.com",
    "room_name": "Löschung des Raums …",
    "message": "Der Raum … wurde gelöscht, weil …",
    "block": true,
    "purge": false
  }' "http://localhost:8008/_synapse/admin/v1/rooms/$room_id"

Versiegelung von Räumen

Matrix bietet die Möglichkeit, in einem Raum einen Grabstein (engl. tombstone) zu platzieren und somit die Kommunikation über diesen Raum zu beenden. Diese Funktionalität wird bei der Aktualisierung der Raumversionen genutzt, indem in den alten Raum ein Grabstein gesetzt und ein neuer Raum (mit aktueller Version) eröffnet wird. Auf diesem Grabstein steht dann auch der Verweis auf den neuen Raum, wo das Leben weiter geht. 😉

Diese Versiegelungen für einen Raum kann man in Element mit /devtools und dort unter Explore room state mit Send custom state event erstellen. Der Event Type ist dann m.room.tombstone, State key bleibt leer und als Content gibt man folgendes an:

{
        "body": "This room has been replaced, blblabla",
        "replacement_room": "!newroom:example.org"
}

Oder man erstellt die entsprechende Nachricht über die Kommandozeile mit folgendem Aufruf. Dabei muss $mx_token von einem Admin des Raumes sein und $old_roomid bzw. $new_roomid die ID (mit !…:example.org) sein:

curl -s -X PUT -H "Authorization: Bearer $mx_token" \
  -H "Content-Type: application/json" \
  --data-binary "{\"replacement_room\":\"$new_roomid\"}" \
  "https://…/_matrix/client/r0/rooms/$old_roomid/state/m.room.tombstone"

Administration von Räumen

Zugangsbegrenzungen über die Raum-ACL

Man kann für jeden Raum einzeln auch konfigurieren, welche Domains darauf Zugriff haben sollen. Diese ACL kann man über spezielle Events verändern:

  1. in Element im Raum die Entwicklerwerkzeuge mit dem Befehl /devtools öffnen
  2. auf Send custom event klicken
  3. unten rechts auf den Knopf Event drücken
  4. bei Event Type m.room.server_acl eintragen, State Key leer lassen
  5. bei Event Content die Regeln (s. u.) einfügen
  6. Send klicken
  7. danach auf Back klicken
  8. über Explore Room State, m.room.server_acl die ACL kontrollieren
  9. im Chatverlauf erscheint die Meldung … set the server ACLs for this room.

    {
        "allow": [
            "*"
        ],
        "allow_ip_literals": false,
        "deny": [
            "matrix.kiwifarms.net",
            "*.kiwifarms.net"
        ]
    }
    

Clients für Matrix

Element

Hydrogen

Weitere Apps

Desktop-Programme

Kommunikation mit anderen Netzwerken

IRC

Von matrix.org werden offiziell Verbindungen in verschiedene IRC-Netze angeboten. Um zum Beispiel in den IRC-Channel #firefox bei moznet einzutreten, betritt man den Matrix-Raum #mozilla_#firefox:matrix.org. Genaueres gibt's in der Anleitung zum IRC-Appservice.

Nachdem man das erste Mal einen Chatraum für ein anderes Netzwerk betreten hat, wird man von dem Dienst für das Netzwerk in einen zusätzlichen Raum eingeladen; alternativ kann dem auch selbst einen Direktchat mit dem Appservice user starten. In diesem Raum kann man über spezielle Nachrichten den Dienst steuern: * mit !nick seinen Namen in dem fremden Netzwerk ändern, * mit !join weitere Räume betreten – ich betrete neue Räume fast nur mit diesem Befehl und lasse mich in den eigentlichen Matrix-Raum einladen * mit !help die allgemeine Hilfe abfragen

Wenn man Schwierigkeiten mit den Räumen hat, weil zum Beispiel der Nickname nicht stimmt oder Nachrichten nicht ankommen, kann man mit dem Befehl !quit auch komplett die Brücke verlassen und von vorn beginnen.

Nick-Name registrieren bei libera.chat

Einige Channels in IRC sind nur für registrierte Benutzer (+r) zugänglich. Daher ist es sinnvoll, sich in diesen Netzwerken einen Namen zu registrieren. Exemplarisch beschreibe ich hier den Weg für Libera Chat, aber mit anderen Netzwerken sollte es genauso ablaufen:

  1. mithilfe eines Webclients zum Netzwerk verbinden
  2. seinen gewünschten Namen auswählen: /nick jo-so
  3. ein Passwort mit dem Lieblingspasswortmanager generieren und die Registrierung starten: /msg NickServ REGISTER YourPassword youremail@example.com
  4. die E-Mail abrufen und den Befehl daraus im Webchat ausführen: /msg NickServ VERIFY REGISTER jo-so …; dies sollte mit einer Erfolgsmeldung bestätigt werden
  5. den Webchat schließen
  6. im Matrix-Raum mit dem Appservice user für liberachat IRC Bridge status den Nickname und das Passwort hinterlegen: !username jo-so und !storepass YourPassword
  7. danach !reconnect ausführen
  8. wenn die Verbindung wieder besteht, sollte nach !nick die Meldung »Currently connected to IRC networks: irc.libera.chat as jo-so« erfolgen

Theoretisch müsste auch alles von Matrix aus funktionieren, aber ich habe dies nicht getestet.

  1. mit dem Appservice user einen Direktchat starten
  2. !nick jo-so
  3. !cmd MSG NickServ REGISTER YourPassword youremail@example.com
  4. !cmd MSG NickServ VERIFY REGISTER jo-so …
  5. !username jo-so
  6. !storepass YourPassword

Weitere Dokumentationen:

Whatsapp

Whatsapp ist ein geschlossenes System und bietet keine saubere Schnittstelle, über die man an dem Netzwerk teilnehmen könnte. Für Matrix wurde jedoch über den Whatsapp-Webchat ein Weg in das Netzwerk gefunden. Über den Dienst mautrix-whatsapp werden die Kontakte von Whatsapp importiert und jeweils ein Raum erstellt. Alle Nachrichten in dem Matrix-Raum werden dann zu Whatsapp übertragen und umgekehrt.

Wer bereits den Whatsapp-Webchat nutzt, kennt dessen Schwäche und diese bleibt auch mit der Matrix-Kopplung: Das Handy mit der Whatsapp-App muss immer online sein. Allerdings kann man sich auch eine virtuelle Maschine mit Anbox einrichten und dort Whatsapp installieren.

In der Liste der unterstützen Funktionen kann man sehen, was alles bereits umgesetzt wurde und was noch geplant ist. Im Matrix-Raum des Projekts kann man sich auch immer Hilfe holen und Fragen stellen.

Installation von mautrix-whatsapp

Zum Erstellen des Programms benötigt man go; Installation mit apt install golang. Gemäß der offiziellen Anleitung holt und übersetzt man das Programm mit folgendem Befehl:

go get -u maunium.net/go/mautrix-whatsapp

Der Quelltext befindet sich danach in dem Verzeichnis ~/go/src/maunium.net/go/mautrix-whatsapp und das Ergebnis ist unter ~/go/bin/mautrix-whatsapp. Später kann man mit dem gleichen Befehl den Quelltext aktualisieren und neu übersetzen.

Ich lasse den Dienst auf dem selben Server wie Synapse laufen und habe mir dafür ein Verzeichnis /srv/matrix/whatsapp-bridge angelegt und das Programm dort abgelegt. In dem Verzeichnis habe ich die Unterverzeichnisse db und logs erstellt und entsprechende Eigentümer (Gruppe adm) und Rechte (g=rxs,o=) dafür gesetzt. Für das Hauptverzeichnis und die Dateien habe ich auch entsprechende Rechte gesetzt, um die Fehlergefahr etwas einzuschränken.

Im Quelltextverzeichnis liegt eine Datei example-config.yaml. In dieser muss man die Einstellungen anpassen:

Danach sollte man Datei example-config.yaml in das srv-Verzeichnis als config.yaml kopieren und dort ./mautrix-whatsapp -g aufrufen. Leider werden dabei alle Kommentare in der Datei zerstört, weshalb es besser ist, die abgeänderten Werte aus der config.yaml von as_token und hs_token in die example-config.yaml zu übertragen und am Ende diese Datei noch einmal in das srv-Verzeichnis kopieren.

In diesem Schritt wurde auch die Datei registration.yaml erstellt. Diese ist für den Home-Server wichtig, damit er den App-Service kennt. In der Serverkonfiguration /etc/matrix-synapse/homeserver.yaml muss diese Datei unter app_service_config_files eingetragen werden und danach Synapse neugestartet werden (systemctl restart matrix-synapse):

app_service_config_files:
    - /srv/matrix/whatsapp-bridge/registration.yaml

Für den Dienst habe ich noch eine Konfiguration für systemd erstellt (systemctl edit --force --full matrix-whatsapp.service) und dabei den vorhandenen Benutzer des Matrix-Servers wiederverwendet.

[Unit]
Description=Bridging service between Matrix and Whatsapp
Documentation=https://maunium.net/go/mautrix-whatsapp
After=network.target

[Service]
ExecStart=/srv/matrix/whatsapp-bridge/mautrix-whatsapp
WorkingDirectory=/srv/matrix/whatsapp-bridge
User=matrix-synapse
Group=daemon
Restart=on-failure

NoNewPrivileges=yes

[Install]
WantedBy=multi-user.target

Den Dienst muss man dann noch aktivieren und starten: systemctl enable --now matrix-whatsapp. Alle Logmeldungen sind damit auch im Journal enthalten.

Nutzung von mautrix-whatsapp

Grundsätzlich kann der Matrix-Whatsapp-Dienst mit mehreren Benutzern umgehen, jedoch sollte man sich bewusst sein, dass der Administrator des Dienstes auf die Zugangsschlüssel für Whatsapp und damit indirekt auf die Handy-Kontakte Zugriff hat. Als Administrator wiederum kann man in der Konfiguration im Abschnitt bridge.permissions einstellen, wer den Dienst nutzen darf.

Für die Nutzung muss man als erstes einen Chat mit dem entsprechenden Dienst beginnen; bei mir @whatsappbot:alea.gnuu.de. Über diesen Raum kann man den Whatsapp-Dienst steuern: Mit der Nachricht help bekommt man die Hilfe angezeigt.

Mit der Nachricht login wird ein QR-Code angezeigt, den man mit dem Handy über die App (Menü: Whatsapp Web) einscannen muss. Nach erfolgreicher Kopplung wird in der App der Eintrag Mautrix-WhatsApp bridge aufgeführt und der Dienst lädt einen in die Räume mit den Whatsapp-Kontakten ein – das ist etwas nervig, weil man gegebenenfalls über hundert Einladungen einzeln bestätigen muss.

Danach merkt man nicht mehr den Unterschied, ob man mit einem Matrix-Partner oder einem Whatsapp-Partner schreibt.

mxmpp

% git clone 'https://github.com/anewusername/mxpp.git'
% cd mxpp
% git clone 'https://github.com/matrix-org/matrix-python-sdk.git'
% ln -s matrix-python-sdk/matrix_client .
% git clone 'https://github.com/yaml/pyyaml'
% ln -s pyyaml/lib3/yaml .
% sudo agi python3-sleekxmpp

https://gitlab.com/ecartman/sleekxmpp-omemo-plugin

Skype-Bridge

https://github.com/matrix-hacks/matrix-puppet-skype

https://github.com/matrix-hacks/matrix-puppet-facebook

matterbridge

https://github.com/42wim/matterbridge

XMPP-Bridge mit Prosody

https://gitlab.com/uhoreg/matrix-appservice-prosody

Dienste innerhalb von Matrix

t2bot.io

t2bot bietet mehrere öffentliche Bots und Bridges an, so dass man die Dienste nicht selbst einrichten und pflegen muss.

Ein Bot für Umfragen

Manchmal möchte man in Gruppen eine Umfrage durchführen. Dies lässt sich leicht mit dem poll-bot erreichen.

% git clone https://github.com/shawnanastasio/matrix-pollbot
% pip install matrix-bot-api

% register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008
New user localpart [root]: pollbot
Password:
Confirm password:
Make admin [no]:
Sending registration request...
Success.
% cd matrix-pollbot
% cp config.ini.example config.ini && emacs config.ini

% python3 pollbot.py

Den Bot kann man dann in den Raum einladen und mit !newpoll eine neue Umfrage starten (kleiner Tipp: Keine URLs verwenden, sonst wird immer wieder URL-Preview aktiv). Danach sendet man als Nachricht in den Raum die Frage und danach als einzelne Nachrichten die möglichen Antworten. Mit !startpoll schließt man dann die Erstellung ab. Jeder im Raum kann dann mit !info sich die Umfrage ansehen, mit !vote <number> darüber abstimmen und mit !endpoll wird die Umfrage beendet. Alle Befehle werden bei !pollhelp aufgelistet.

Gedanken zu Matrix

Wahl der Kennungen

Die Benutzernamen bei Matrix folgen dem Schema @user:domain, Raumnamen haben das Schema #raum:domain, für Gemeinschaften ist es +name:domain und interne IDs lauten !id:domain. Im Vergleich mit XMPP ist dies sehr gut, denn wenn irgendwo im WWW diese IDs auftauchen, gibt es genug Spammer die sie einfach als E-Mailadresse verwenden. Ich bekomme auch massenweise Spam für Message-IDs von Mailinglisten oder Usenet-Beiträgen, weil diese eben auch wie eine E-Mailadresse aufgebaut sind.

Anfangs fand ich die Form der Kennungen merkwürdig, aber mittlerweile begrüße ich die Abweichung vom bekannten Muster der E-Mails.

Referenzierung von Nachrichten

Da Nachrichten eine global eindeutige Kennung haben, lässt sich auch darauf verweisen; Beispiel. Da zum Beispiel der Webclient Element auch ohne Anmeldung auf öffentliche Räume zugreifen kann, lässt sich damit angenehm auf Diskussion im Matrix-Netzwerk verweisen; Beispiel. Zu finden sind die Links unter anderem bei Element, wenn man auf die drei Punkte rechts neben einer Nachricht klickt.

Technisches Design

Was mir bei Matrix von Anfang an gefallen hat, waren die Konzepte des Systems. Im Grunde ist Matrix sehr einfach: es gibt nur Benutzer, Räume und Nachrichten. Das hat zur Folge, dass ein direkter Chat mit einer Person für Matrix auch über einen Raum läuft. Genauso kann man Selbstgespräche in einem Raum mit nur einem Teilnehmer führen – ich nutze das, um Nachrichten zwischen Handy und Computer auszutauschen. Es wird also nicht zwischen Direktnachrichten und Gruppengesprächen unterschieden. Der Kern der Technologie ist schlicht und einfach gehalten, was immer ein großer Vorteil ist.

Matrix verwendet für Räume intern langen Kennungen und bietet für diese einen lesbaren Alias an. Somit kann ein Raum einerseits über mehrere Namen (z. B. mit und ohne Bindestrich) erreichbar sein und andererseits auch von einem zu einem anderen Server umziehen, weil sich einfach der Alias ändert.

Das Netzwerk ist auch ähnlich dem Usenet aufgebaut. Es gibt für einen Raum, eine Nachricht oder einen Benutzer eine Quelle (den Home-Server), die für die eindeutige Kennung sorgt, aber nicht als zentrale Instanz agiert. Jeder Server, der über einen seiner Benutzer an einem Raum beteiligt ist, pflegt die Nachrichten des Raums. Somit kann ein Knoten des Netzwerks ausfallen und alle anderen drumherum können weiterarbeiten. Im Gegensatz zum Usenet kooperieren die Server automatisch untereinander und es bedarf keiner händischen Pflege der Feeds.

Die Verknüpfung von Benutzerkennungen mit anderen Merkmalen wie Telefonnummer oder E-Mailadresse hat man in einen eigenen Dienst ausgelagert: identity servers. Dieses Verzeichnis kann also völlig getrennt von dem Kommunikationsnetzwerk aufgebaut und gepflegt werden, sprich man muss sich nicht dort registrieren, um Matrix nutzen zu können.

Bilder und Dateien sind mit Bestandteil des Protokolls, so dass es nicht wie bei XMPP die Probleme bei der Übertragung über einen zusätzlichen Server gibt und Bilder integrieren sich auch gut in Gruppengespräche. In der Nachricht steht zwar auch nur ein Verweis auf die Daten, aber der Abruf dieser läuft über die gleiche Schnittstelle.

"content": {
  "body": "IMG_20180330_120003.jpg",
  "info": {
    "mimetype": "image/jpeg",
    "thumbnail_info": {
      "mimetype": "image/jpeg",
      "h": 320,
      "w": 240,
      "size": 82143
    },
    "h": 1632,
    "thumbnail_url": "mxc://alea.gnuu.de/uCtPLuiKLlQPFwVmxfuCEovu",
    "w": 1224,
    "size": 908347,
    "orientation": 0
  },
  "msgtype": "m.image",
  "url": "mxc://alea.gnuu.de/IkyOoQUDtHlIhHBRBNGqDqJI"
},

Was ich auch wirklich gut finde, ist die Schnittstelle per Rest/JSON. JSON finde ich wesentlich handlicher als XML und Rest-Aufrufe kann man auch einfach von der Kommandozeile aus mit curl ausführen; eine kleine Einführung in die Matrix-Schnittstelle.

Ein kleines Beispiel für die Vorzüge von REST

Mit Synapse 0.29 gab es immer wieder Performance-Probleme mit großen Räumen wie #matrix:matrix.org. Da der Zugriff auf den Server über normale HTTP-Aufrufe erfolgt, kann man diese auch mit Nginx filtern und so Funktionen ausgleichen, die in der eigentlich Software nicht eingebaut sind; wie hier vorgeschlagen:

krombeI: I don't suppose it's possible to disable pagination for only certain rooms?

aidalgol: It is not possible via synapse. But I implemented it in nginx as follows (i know it't hacky but currently my only solution for accidential OOMing...)

location ~ /_matrix/client/r0/rooms/.*cURbafjkfsMDVwdRDQ.*matrix.org/messages {
    # set as text/plain to let this custom message be displayed (at least in js-sdk)
    default_type text/plain;
    return 429 "fetching history for #matrix:matrix.org leads to server OOM => it is currently disabled";
}

Programmierung von Matrix

Matrix-Implementation in Rust

https://www.ruma.io/ Matrix-Raum

dsn-Traveller-Bot

Go

Sonstiges

Datenbank von Synapse