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 Riot 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 oder der Liste bei Matrix-Stats, 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 Riot fürs Handy und am Laptop nutze ich Riot 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 Riot ü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.

Den Home-Server einrichten

Synapse unter Debian einrichten

Wer Debian-Buster einsetzt, kann sich direkt Synapse installieren: apt install matrix-synapse. 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.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.

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;
    }

    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;
    }
}

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 …

Riot einrichten

Riot ist ein Webclient für Matrix, der vom Matrix-Team entwickelt wird. Man kann ihn direkt von riot.im 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/riot.

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 /riot/ {
        access_log off;
        alias /srv/www/riot-web/;
    }
}

% 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 Riot 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 ist hier beschrieben.

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
# Matrix uses only TURN
no-stun
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.

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

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.

In der Datenbank gibt es die sehr große Tabelle state_groups_state (siehe \dt+ in psql), welche ich von der Sicherung bei mir ausschließen musste. Ob eine Wiederherstellung ohne diese Tabelle möglich ist, kann ich jedoch nicht sagen!

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

curl -d '' "https://example.org/_matrix/client/r0/admin/purge_media_cache?before_ts=$(date +%s000)&access_token=<access_token>"

state_groups_state aufräumen

https://github.com/matrix-org/rust-synapse-compress-state/ https://github.com/matrix-org/rust-synapse-compress-state/issues/2#issuecomment-444039031

sudo systemd-run --nice=4 --uid=matrix-synapse --collect =cleanup-matrix-db

event_forward_extremities aufräumen

https://github.com/matrix-org/synapse/issues/1760#issuecomment-379183539

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

Alte Anhänge löschen

curl -v -d '' "https://m.jo-so.de/_matrix/client/r0/admin/purge_media_cache?before_ts=$(date -d-1month +%s000)&access_token=<access_token>"

Räume aus der Datenbank kratzen

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

Clients für Matrix

Riot

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. 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 * 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.

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=systemd-networkd.service network.target

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

[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 Riot 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 Riot, 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