Erkenntnisse und Erfahrungen rund um Matrix • Am Interneteingang 8

Originalartikel

Backup

<html> <p><a href=„https://matrix.org/“><em>Matrix</em></a> ist ein neues Kommunikationssystem, allerdings nicht mit dem Anspruch, das n&#228;chste coole, hippe Teil zu werden, sondern <em>Matrix</em> setzt von Anfang an auf Integration und will Br&#252;cken zu anderen Systemen bauen.</p><p>Die Kommunikation im Internet hat sich leider zu einer <a href=„https://xkcd.com/1810/“>zerkl&#252;fteten Inselwelt</a> entwickelt, in der jede Gruppe mit ihrem eigenen System arbeitet und inkompatibel zur Au&#223;enwelt ist. Da der Umzug von einem Netzwerk in ein anderes umst&#228;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&#228;llt &#8211;&#160;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&#160;&#8211; und <em>Matrix</em> kommuniziert mit ihnen. Ein Ansatz, der mir wahnsinnig gut gef&#228;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 &#246;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&#160;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&#252;r Clients erreichbar ist, kann man per <em>netcat</em> oder <em>telnet</em> pr&#252;fen (auch f&#252;rs System-Monitoring hilfreich):</p><pre>% netcat localhost 8008 &lt;&lt;&lt;$'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&#252;r andere Server erreichbar ist, also ob die <em>Federation</em> funktioniert, kann man &#252;ber die Adresse

https://matrix.org/federationtester/api/report?server_name=&#8230;

mit dem entsprechenden Servernamen pr&#252;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&#160;2019) von <em>Synapse</em>, aber ihr Einsatz lohnt sich. Ziel der Entwicklung ist es, Teile aus dem Hauptprozess herauszul&#246;sen und in eigenst&#228;ndige Prozesse zu gliedern. Auf diese Weise kann man &#8230;</p><h2 id=„elementeinrichten“><em>Element</em> einrichten</h2><p><em>Element</em> ist ein Webclient f&#252;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&#228;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&#228;sten deaktiviert

"disable_guests": true

, bei den Raum-Servern meinen eigenen erg&#228;nzt und bei <em>piwik</em> den Schl&#252;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&#252;r Clients und 8448 f&#252;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&#246;glichkeiten <em>Nginx'</em> nutzen kann: SSL-Zertifikate, HTTP/2.0, Einschr&#228;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&#252;fung kann man im Browser die Adresse

/_matrix/client/versions

seines Servers aufrufen und sollte eine Ausgabe &#228;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&#252;r die regelm&#228;&#223;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 &#252;ber die Weboberfl&#228;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: "&lt;SECRET KEY&gt;"

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&#252;cksetzen des Passworts gibt es die <a href=„https://github.com/matrix-org/synapse/blob/master/README.rst#password-reset“>h&#228;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&#252;r Video- und Audioverbindungen einrichten</h2><p>F&#252;r Video- und Audioverbindungen ist neben dem <em>Matrix</em>-Server noch ein <em>TURN</em>-Server notwendig, der zwischen Ger&#228;ten vermittelt, die sich nicht direkt erreichen k&#246;nnen; z.&#8239;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&#252;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&#252;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&#252;ssel</pre><p>Die Konfiguration f&#252;r <em>Systemd</em> wird bei der Installation automatisch generiert, weshalb ich sie durch folgende ersetzt (

systemctl edit --full coturn.service

) habe. Damit l&#228;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 &lt;tunables/global&gt;profile /usr/bin/turnserver { include &lt;abstractions/base&gt; include &lt;abstractions/ssl_certs&gt; include &lt;abstractions/ssl_keys&gt; /etc/turnserver.conf r, owner /var/lib/turn/turndb rwk,}</pre><p><strong>Sicherheitshinweis:</strong> Trotz der Einstellungen f&#252;r Verschl&#252;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&#228;te direkt per IPv6 kommuniziert haben, ohne den Weg &#252;ber den <em>TURN</em>-Server.</p><p>Ich habe urspr&#252;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&#228;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 &amp;&amp; createdb -O matrix-synapse -l C.UTF-8 -T template0 matrix'</pre><p>In der Konfiguration <em>homeserver.yaml</em> m&#252;ssen noch die Einstellungen wie folgt ge&#228;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&#228;tzlich zu den <a href=„http://initd.org/psycopg/docs/module.html#psycopg2.connect“>Parametern f&#252;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&#252;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&#223;t. Eine L&#246;sung hierf&#252;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&#252;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&#252;hrt werden, falls man den Dienst weiterlaufen l&#228;sst und eine Kopie der <em>sqlite</em>-Datenbank verwendet hat oder es zu Fehlern kam. Ich habe aber einfach f&#252;r die gesamte Zeit den Dienst bei mir abgeschaltet.</p><pre>% cd /tmp &amp;&amp; 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&#160;3214</a> bereits gel&#246;st ist oder ggf. den

ALTER TABLE

-Befehl von dort ausf&#252;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&#252;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&#228;sst sich im Nachhinein &#252;ber andere Server wiederherstellen.</p><p>Bei der Wiederherstellung des Systems muss man mit dem Zugangsschl&#252;ssel (Access-Token) eines Admin-Benutzers den Cache zur&#252;cksetzen, damit <em>Synapse</em> die Dateien, die vom Backup ausgeschlossen waren, neu beschafft. Den Zugangsschl&#252;ssel findet man in <em>Element</em> unter <em>Einstellungen, Hilfe, Fortgeschritten</em> und nutzt diesen f&#252;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 &lt;access_token&gt;“ -d '' „http://localhost:8086/_synapse/admin/v1/purge_media_cache?before_ts=$(date +%s000)“</pre><h2 id=„ungenutzterumeentfernen“>Ungenutzte R&#228;ume entfernen</h2><p>Wenn Nutzer einen Raum verlassen, der &#252;ber mehrere Server verteilt liegt, bleiben auf dem eigenen Server die alten Nachrichten zur&#252;ck. Da diese nicht mehr genutzt werden, ist es sinnvoll, diese zu entfernen:</p><pre>mx_token=&lt;Token eines Admins&gt;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&#223; 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&#228;umen und somit den Speicherverbrauch eind&#228;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 &#196;nderungen beschreiben. Man muss also nach jedem Durchlauf des Programms noch das entstandene SQL-Skript ausf&#252;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&#252;r durchzuf&#252;hren. Dieses Hilfsprogramm rufe ich mithilfe von Systemd auf, damit es im Hintergrund l&#228;uft (bei mir dauert es &#252;ber 2&#160;Stunden) und ich die Meldungen im Nachhinein pr&#252;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&#228;mlich die Macke und erzeugt ein gr&#246;&#223;eres Ergebnis als der Ausgangszustand. Da auch die Pr&#252;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&#252;r die der neue Zustand genommen wird. Abgesehen von dieser Macke liefert das Programm aber teilweise eine Reduktion <em>auf</em> 10&#8239;% (sic!) bei einigen R&#228;umen.</p><p><a href=„„https://github.com/matrix-org/rust-synapse-compress-state/issues/2#issuecomment-444039031““>Synapse muss w&#228;hrend der Ausf&#252;hrung nicht angehalten werden</a>, sodass es egal ist, wie lange das Programm l&#228;uft oder ob man es zwischendurch abbricht. Ich rufe es bei mir unregelm&#228;&#223;ig alle paar Wochen auf.</p><h2 id=„„device_inboxaufrumen““><em>device_inbox</em> aufr&#228;umen</h2><p>Die Schema-Definition der Datenbank von Synapse ist <em>piep</em>. Daher werden Eintr&#228;ge in der Tabelle <em>device_inbox</em> nicht gel&#246;scht, wenn die dazugeh&#246;rigen Ger&#228;te gel&#246;scht werden. Mit folgendem SQL-Befehl kann man dies h&#228;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>

1)
„python“,pid=24088,fd=10