<html> <p><a href=„https://matrix.org/“><em>Matrix</em></a> ist ein neues Kommunikationssystem, allerdings nicht mit dem Anspruch, das nächste coole, hippe Teil zu werden, sondern <em>Matrix</em> setzt von Anfang an auf Integration und will Brücken zu anderen Systemen bauen.</p><p>Die Kommunikation im Internet hat sich leider zu einer <a href=„https://xkcd.com/1810/“>zerklüfteten Inselwelt</a> 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 <em>Matrix</em> die Nutzer eben dort nicht wegholen, sondern dort erreichen. Jeder darf das System nutzen, das ihm gefällt – egal ob XMPP, <a href=„https://jo-so.de/2018-03/Matrix.html#irc“>IRC</a>, <a href=„https://jo-so.de/2018-03/Matrix.html#whatsapp“>Whatsapp</a>, Telegram, Hangouts, Facebook oder SMS – und <em>Matrix</em> kommuniziert mit ihnen. Ein Ansatz, der mir wahnsinnig gut gefällt!</p><p>Wer sich <em>Matrix</em> erst einmal nur ansehen will, kann den <a href=„https://app.element.io/“>Webclient Element</a> benutzen und einen öffentlichen Raum wie</p><h3 id=„funktionstest“>Funktionstest</h3><p>Wenn alles durch ist, den Dienst (neu-)starten und dann sollte er auf dem Port 8008 lauschen.</p><pre>% sudo systemctl restart matrix-synapse.service% sudo ss -tlp |grep 8008LISTEN 0 0 ::1:8008 :::* users:1)</pre><p>Ob der Server für Clients erreichbar ist, kann man per <em>netcat</em> oder <em>telnet</em> prüfen (auch fürs System-Monitoring hilfreich):</p><pre>% netcat localhost 8008 <<<$'GET /_matrix/client/versions HTTP/1.0\r\n\r'HTTP/1.0 200 OKContent-Length: 54Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, AuthorizationServer: Synapse/0.29.0Cache-Control: no-cache, no-store, must-revalidateDate: Sun, 20 May 2018 15:16:36 GMTAccess-Control-Allow-Origin: *Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONSContent-Type: application/json{„versions“: [„r0.0.1“, „r0.1.0“, „r0.2.0“, „r0.3.0“]}</pre><p>Im Log <em>/var/log/matrix-synapse/homeserver.log</em> sollte dann etwas in dieser Art stehen:</p><pre>2018-05-20 17:12:18,831 - synapse.access.http.8008 - 95 - INFO - GET-65532- - - 8008 - Received request: GET /_matrix/client/versions2018-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“</pre><p>Ob der Server für andere Server erreichbar ist, also ob die <em>Federation</em> 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 <a href=„https://neo.lain.haus/fed-tester/“>Fed-tester</a>.</p><h2 id=„workereinrichten“>Worker einrichten</h2><p>Worker sind noch eine recht junge Entwicklung (Stand: Mai 2019) von <em>Synapse</em>, 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 …</p><h2 id=„elementeinrichten“><em>Element</em> einrichten</h2><p><em>Element</em> ist ein Webclient für <em>Matrix</em>, der vom <em>Matrix</em>-Team entwickelt wird. Man kann ihn direkt von <a href=„https://app.element.io/“>app.element.io</a> aus nutzen oder man richtet sich eine eigene Instanz ein. Es gibt zwar ein <a href=„https://github.com/vector-im/riot-web#installation-steps-for-debian-stretch“>Debian-Paket</a>, aber dieses hängt vom Paket <em>gconf</em> ab und zieht auf einem Server einen Rattenschwanz an Paketen hinterher. Deshalb verwende ich das <a href=„https://github.com/vector-im/riot-web/releases“>allgemeine Paket</a> und entpacke es in <em>/srv/www/m.jo-so.de</em>.</p><p>In dem Verzeichnis liegt die Datei <em>config.sample.json</em>, welche nach <em>config.json</em> kopiert werden muss. Darin sollte bei
default_hs_url
die Adresse des eigenen <em>Matrix</em>-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 <em>piwik</em> den Schlüssel
url
durch
X-url
ersetzt, damit auch sicher kein <em>Piwik</em> angesprochen wird.</p><p><em>Matrix</em> nutzt zwei verschiedene Kommunikationswege: 8008 für Clients und 8448 für andere Server, so wie es auch bei XMPP der Fall ist. Da <em>Matrix</em> eine REST-Schnittstelle verwendet, kann man den Verkehr zum eigentlichen <em>Matrix</em>-Dienst durch einen <em>Nginx</em> leiten, so dass der <em>Matrix</em>-Dienst nicht als <em>root</em> laufen muss und man die Möglichkeiten <em>Nginx'</em> 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 <em>/_matrix</em>.</p><pre>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</pre><p>Als einfachere Funktionsprüfung kann man im Browser die Adresse
/_matrix/client/versions
seines Servers aufrufen und sollte eine Ausgabe ähnlich wie bei <a href=„https://matrix.org/_matrix/client/versions“>https://matrix.org/_matrix/client/versions</a> erhalten.</p><p>Ein kleines Skript für die regelmäßige Aktualisierung von <em>Element</em> habe ich in der <a href=„https://jo-so.de/2018-10/filtern-mit-jq.html“>Anleitung zu <em>jq</em></a> beschrieben.</p><h2 id=„neuenbenutzeranlegen“>Neuen Benutzer anlegen</h2><p>Man kann es allen Nutzern erlauben, ein neues Konto über die Weboberfläche anzulegen, in dem man in der Serverkonfiguration <em>homeserver.yaml</em> 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 <em>register_new_matrix_user</em> neue Benutzer anlegen:</p><pre>% register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8008New user localpart [root]: userPassword:Confirm password:Make admin [no]:Sending registration request…Success.</pre><p>Das Zurücksetzen des Passworts gibt es die <a href=„https://github.com/matrix-org/synapse/blob/master/README.rst#password-reset“>händische Bearbeitung der Datenbank</a> und eine <a href=„https://github.com/matrix-org/synapse/blob/master/docs/admin_api/user_admin_api.rst#reset-password“>API-Funktion</a>, die man mit <em>curl</em> aufrufen kann.</p><h2 id=„turnfrvideo-undaudioverbindungeneinrichten“><em>TURN</em> für Video- und Audioverbindungen einrichten</h2><p>Für Video- und Audioverbindungen ist neben dem <em>Matrix</em>-Server noch ein <em>TURN</em>-Server notwendig, der zwischen Geräten vermittelt, die sich nicht direkt erreichen können; z. B. durch <a href=„https://de.wikipedia.org/wiki/Netzwerkadress%C3%BCbersetzung“>NAT</a>. Direkt von <em>Debian</em> gibt es das Paket <em><a href=„https://packages.debian.org/stable/coturn“>coturn</a></em>.</p><p>Nach der Installation (
apt install coturn
) muss die Konfigurationsdatei <em>/etc/turnserver.conf</em> wie folgt angepasst werden (Entnommen aus der Doku von <a href=„https://github.com/matrix-org/synapse/blob/master/docs/turn-howto.rst“><em>synapse</em></a>):</p><pre>lt-cred-mechuse-auth-secretstatic-auth-secret=Geheimen Schlüssel mit `pwgen -s 64 1` erzeugenrealm=jo-so.deno-tcp-relaycert=/etc/letsencrypt/live/host/fullchain.pempkey=/etc/letsencrypt/live/host/privkey.pem# Matrix uses only TURNno-stunno-multicast-peersdenied-peer-ip=10.0.0.0-10.255.255.255denied-peer-ip=172.16.0.0-172.31.255.255denied-peer-ip=192.168.0.0-192.168.255.255pidfile=„/dev/null“secure-stunmobilityno-tlsv1</pre><p>Den geheimen Schlüssel und die <em>TURN</em>-Verbindungen muss man noch in der <em>homeserver.yaml</em> eintragen und den <em>Synapse</em>-Server neustarten.</p><pre>turn_uris: - „turn:alea.gnuu.de:3478?transport=udp“ - „turn:alea.gnuu.de:3478?transport=tcp“turn_shared_secret=Geheimer Schlüssel</pre><p>Die Konfiguration für <em>Systemd</em> 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 <em>root</em>.</p><pre># https://github.com/coturn/coturn/blob/master/rpm/turnserver.service.fc[Unit]Description=coturnDocumentation=man:coturn(1) man:turnadmin(1) man:turnserver(1)After=network.target[Service]User=turnserverGroup=turnserverSupplementaryGroups=ssl-certPIDFile=/run/turnserver.pidExecStart=/usr/bin/turnserver -c /etc/turnserver.conf –log-file stdoutRestart=on-abortLimitNOFILE=999999LimitNPROC=60000LimitRTPRIO=infinityLimitRTTIME=7000000CPUSchedulingPolicy=otherUMask=0007NoNewPrivileges=yes[Install]WantedBy=multi-user.target</pre><p>AppArmor <em>/etc/apparmor.d/usr.bin.turnserver</em></p><pre>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,}</pre><p><strong>Sicherheitshinweis:</strong> Trotz der Einstellungen für Verschlüsselung des <em>TURN</em>-Servers konnte ich mit <em>Wireshark</em> noch die Inhalte der Verbindung einsehen. Ich habe nichts gefunden, wie ich die <em>TURN</em>-Verbindung weiter absichern kann.</p><pre>Source: laptop (Port: 59697)Destination: alea.gnuu.de (Port: 3478)Protocol: STUNInfo: Allocate Request UDP lifetime: 3600 user: 1527072691:@test:alea.gnuu.de realm: alea.gnuu.de with nonceSource: laptop (Port: 59697)Destination: alea.gnuu.de (Port: 3478)Protocol: STUNInfo: CreatePermission Request XOR-PEER-ADDRESS: 192.168.178.21:48261 user: 1527072691:@test:alea.gnuu.de realm: alea.gnuu.de with nonce</pre><p>Im <em>Wireshark</em> konnte ich aber auch beobachten, dass meine beiden Testgeräte direkt per IPv6 kommuniziert haben, ohne den Weg über den <em>TURN</em>-Server.</p><p>Ich habe ursprünglich mit <em>sqlite</em> begonnen und irgendwann die <a href=„https://github.com/matrix-org/synapse/blob/master/docs/postgres.rst“>Datenbank auf <em>Postgres</em> umgestellt</a>. Hier die <a href=„https://jo-so.de/2017-07/postgres.html“>Befehle zum Einrichten des Benutzers und der Datenbank</a>. 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
.</p><pre>% sudo apt install python-psycopg2% sudo -u postgres sh -c 'createuser matrix-synapse && createdb -O matrix-synapse -l C.UTF-8 -T template0 matrix'</pre><p>In der Konfiguration <em>homeserver.yaml</em> müssen noch die Einstellungen wie folgt geändert werden:</p><pre># Database configurationdatabase: # 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</pre><p>Zusätzlich zu den <a href=„http://initd.org/psycopg/docs/module.html#psycopg2.connect“>Parametern für <em>connect</em></a> kann man noch <a href=„https://twistedmatrix.com/documents/8.0.0/api/twisted.enterprise.adbapi.ConnectionPool.html#__init__“>Parameter für das Connection-Pooling</a> angeben. Leider ist zu dem von Synapse genutzten <a href=„https://twistedmatrix.com/documents/current/api/twisted.enterprise.adbapi.ConnectionPool.html“>Connection-Pool</a> zu sagen, dass es ungenutzte (idle) Verbindungen nicht automatisch schließt. Eine Lösung hierfür habe ich noch nicht gefunden.</p><p>Bei <em>Systemd</em> sollte man dann noch angeben, dass der Server erst nach <em>Postgres</em> gestartet wird:</p><pre>% sudo systemctl edit matrix-synapse.service[Unit]After=network-online.target postgresql.service</pre><p>Für die Datenmigration von <em>sqlite</em> zu <em>Postgres</em> gibt es das Programm <em>synapse_port_db</em>. Dieses kann auch mehrfach ausgeführt werden, falls man den Dienst weiterlaufen lässt und eine Kopie der <em>sqlite</em>-Datenbank verwendet hat oder es zu Fehlern kam. Ich habe aber einfach für die gesamte Zeit den Dienst bei mir abgeschaltet.</p><pre>% 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</pre><p>Wenn es zu einem Fehler kommt und in der Datei <em>port-synapse.log</em> etwas von
Failed to insert: room_depth
steht, dann zuerst einmal nachsehen, ob der <a href=„https://github.com/matrix-org/synapse/issues/3214#issuecomment-388917400“>Fehler 3214</a> bereits gelöst ist oder ggf. den
ALTER TABLE
-Befehl von dort ausführen und die Migration noch einmal starten.</p><p>Auf der Webseite von Matrix werden <a href=„https://matrix.org/docs/guides/#synapse-maintenance“>diverse Anleitungen zur Wartung von <em>Synapse</em></a> und <a href=„https://matrix.org/docs/guides/moderation“>Moderation von Matrix</a> angeboten.</p><p>Wichtig für eine Wiederherstellung einer <em>Matrix</em>-Installation sind</p><ul><li>die Konfigurationdateien unter <em>/etc/matrix-synapse</em>,</li><li>die Dateien unter <em>/var/lib/matrix-synapse</em> und</li><li>die Datenbank.</li></ul><p>Um das Backup zu verkleinern kann man die Verzeischnisse <em>/var/lib/matrix-synapse/media/(remote_|url_cache)*/*</em> auslassen. Deren Inhalt lässt sich im Nachhinein über andere Server wiederherstellen.</p><p>Bei der Wiederherstellung des Systems muss man mit dem Zugangsschlüssel (Access-Token) eines Admin-Benutzers den Cache zurücksetzen, damit <em>Synapse</em> die Dateien, die vom Backup ausgeschlossen waren, neu beschafft. Den Zugangsschlüssel findet man in <em>Element</em> unter <em>Einstellungen, Hilfe, Fortgeschritten</em> und nutzt diesen für <a href=„https://github.com/matrix-org/synapse/blob/master/docs/admin_api/media_admin_api.md#purge-remote-media-api“><em>purge_remote_media</em></a> mit aktuellem Zeitstempel:</p><pre>curl -H „Authorization: Bearer <access_token>“ -d '' „http://localhost:8086/_synapse/admin/v1/purge_media_cache?before_ts=$(date +%s000)“</pre><h2 id=„ungenutzterumeentfernen“>Ungenutzte Räume entfernen</h2><p>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:</p><pre>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</pre><p>In der Tabelle <em>state_groups_state</em> 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 <em><a href=„„https://github.com/matrix-org/rust-synapse-compress-state/““>rust-synapse-compress-state</a></em> aufräumen und somit den Speicherverbrauch eindämmen.</p><p>Wer Rust installiert hat, kompiliert das Programm besser selbst aus den Quellen, denn Releases passieren eher selten:</p><pre>cargo install –git https://github.com/matrix-org/rust-synapse-compress-state</pre><p>Danach liegt das Programm im Verzeichnis <em>~/.cargo/bin/synapse-compress-state</em>. 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 <a href=„„https://jo-so.de/2018-03/synapse-clear-state.sh““>synapse-clear-state</a> 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</p><pre>% 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</pre><p>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 <em>synapse-compress-state</em> die Mindestanzahl an Tabellenzeilen angeben, für die der neue Zustand genommen wird. Abgesehen von dieser Macke liefert das Programm aber teilweise eine Reduktion <em>auf</em> 10 % (sic!) bei einigen Räumen.</p><p><a href=„„https://github.com/matrix-org/rust-synapse-compress-state/issues/2#issuecomment-444039031““>Synapse muss während der Ausführung nicht angehalten werden</a>, 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.</p><h2 id=„„device_inboxaufrumen““><em>device_inbox</em> aufräumen</h2><p>Die Schema-Definition der Datenbank von Synapse ist <em>piep</em>. Daher werden Einträge in der Tabelle <em>device_inbox</em> nicht gelöscht, wenn die dazugehörigen Geräte gelöscht werden. Mit folgendem SQL-Befehl kann man dies händisch erledigen:</p><pre>DELETE– SELECT COUNT(*)FROM device_inboxWHERE device_id IN (SELECT device_id FROM devices WHERE hidden = true) OR device_id NOT IN (SELECT device_id FROM devices) </html>