Files
homelab/services/matrix-synapse/README.md
T
x3 4a55944aa8 Homelab-Dokumentation und Konfigurationsvorlagen
Dokumentation aus dem Wiki uebernommen und um die Dienste auf dem Server
erweitert. Alle Anleitungen sind so geschrieben, dass sich der jeweilige
Dienst allein daraus neu aufsetzen laesst.

docs/      Dienste im Heimnetz (aus dem Wiki, anonymisiert)
services/  Dienste auf dem Server mit Konfigurationsvorlagen
           - matrix-synapse: Homeserver, Postgres, Well-Known-Delegation
           - coturn:         TURN-Relay fuer Anrufe
           - element-web:    Web-Client
           - wikijs, gitea, nginx

Durchgehend anonymisiert: echte Domain durch example.com ersetzt, IP-Adressen
und E-Mail-Adressen durch Platzhalter. Konfigurationsdateien liegen nur als
.example mit Platzhaltern statt echter Secrets vor.

Die Anleitungen halten die Stolpersteine fest, die beim Aufbau tatsaechlich
aufgetreten sind, unter anderem:
- Synapse verlangt LC_COLLATE=C, sonst startet es nicht
- server_name ist nachtraeglich nicht aenderbar -> Delegation noetig
- register_new_matrix_user liest conf.d nicht, Secret muss per -k kommen
- coturn braucht external-ip, sonst kommen keine Medien durch
- Gruppenmitgliedschaft fuer den Zertifikatszugriff wirkt erst beim Neustart
- nginx vererbt add_header nicht in location-Bloecke mit eigenen Direktiven
2026-08-31 17:56:02 +00:00

8.6 KiB
Raw Blame History

Matrix-Homeserver (Synapse)

Eigener Matrix-Server mit PostgreSQL, nginx als TLS-Terminierung und Well-Known-Delegation, damit die Benutzer-IDs kurz bleiben.

Punkt Wert
Software Synapse (Paket matrix-synapse-py3 von packages.matrix.org)
Datenbank PostgreSQL
Interner Listener 127.0.0.1:8008 (kein TLS, das macht nginx)
Öffentlich https://matrix.example.com
Benutzer-IDs @name:example.com

Warum zwei Domains?

Das ist der Punkt, an dem die meisten Anleitungen unnötig kompliziert werden.

Der server_name ist der hintere Teil jeder Benutzer-ID. Setzt man ihn auf matrix.example.com, heißen alle Benutzer @name:matrix.example.com unschön und nicht mehr änderbar, denn der server_name lässt sich nachträglich nicht umstellen, ohne alle Konten und Räume zu verlieren.

Deshalb:

  • server_name: example.com → IDs lauten @name:example.com
  • Synapse läuft aber auf matrix.example.com
  • Zwei kleine JSON-Dokumente unter https://example.com/.well-known/matrix/… verweisen andere Server und Clients dorthin

Die Apex-Domain muss dafür nur diese zwei Dateien ausliefern, sonst nichts.

Voraussetzungen

  • Debian/Ubuntu mit root-Rechten
  • PostgreSQL
  • nginx
  • certbot
  • DNS-A-Records auf den Server: example.com, matrix.example.com

1. Paketquelle und Installation

sudo install -d -m 0755 /etc/apt/keyrings
sudo curl -fsSL -o /etc/apt/keyrings/matrix-org-archive-keyring.gpg \
  https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg

# <suite> ist der Codename der Distribution, z. B. noble, trixie, resolute
echo "deb [signed-by=/etc/apt/keyrings/matrix-org-archive-keyring.gpg] \
https://packages.matrix.org/debian/ <suite> main" \
  | sudo tee /etc/apt/sources.list.d/matrix-org.list

sudo apt-get update

Ob es für die eigene Distribution ein Paket gibt, lässt sich vorher prüfen:

curl -s https://packages.matrix.org/debian/dists/<suite>/main/binary-amd64/Packages \
  | grep -E "^Package:|^Version:"

Installation. Der server_name wird per debconf vorbelegt, damit die Installation nicht interaktiv nachfragt:

echo "matrix-synapse-py3 matrix-synapse/server-name string example.com" \
  | sudo debconf-set-selections
echo "matrix-synapse-py3 matrix-synapse/report-stats boolean false" \
  | sudo debconf-set-selections

sudo DEBIAN_FRONTEND=noninteractive apt-get install -y matrix-synapse-py3

Wichtig: Der hier gesetzte server_name ist endgültig. Er landet in /etc/matrix-synapse/conf.d/server_name.yaml.

2. Datenbank

Synapse besteht auf C-Collation. Eine mit den üblichen de_DE.UTF-8-Vorgaben angelegte Datenbank wird beim Start abgelehnt:

sudo -u postgres psql <<'SQL'
CREATE ROLE synapse_user LOGIN PASSWORD 'HIER-EIN-STARKES-PASSWORT';
CREATE DATABASE synapse
  ENCODING 'UTF8'
  LC_COLLATE='C'
  LC_CTYPE='C'
  template=template0
  OWNER synapse_user;
SQL

Kontrolle unter Collate/Ctype muss C stehen:

sudo -u postgres psql -c "\l synapse"

3. Konfiguration

Eigene Einstellungen gehören nach /etc/matrix-synapse/conf.d/. Die homeserver.yaml wird vom Paket verwaltet und bei Upgrades überschrieben.

Der von der Installation angelegte SQLite-Block in homeserver.yaml muss entfernt oder auskommentiert werden, sonst kollidiert er mit der conf.d-Datei:

sudo sed -i '/^database:/,/database: \/var\/lib\/matrix-synapse\/homeserver.db/d' \
  /etc/matrix-synapse/homeserver.yaml

Dann die Vorlagen aus diesem Verzeichnis kopieren und die Platzhalter füllen:

sudo cp conf.d/database.yaml.example /etc/matrix-synapse/conf.d/database.yaml
sudo cp conf.d/homelab.yaml.example  /etc/matrix-synapse/conf.d/homelab.yaml

sudo chown root:matrix-synapse /etc/matrix-synapse/conf.d/*.yaml
sudo chmod 640 /etc/matrix-synapse/conf.d/*.yaml

Secrets explizit setzen

Fehlen macaroon_secret_key und form_secret, leitet Synapse sie aus dem Signing-Key ab und warnt beim Start. Wird der Signing-Key später ersetzt, sind schlagartig alle Access-Tokens ungültig. Deshalb einmalig festlegen:

sudo tee /etc/matrix-synapse/conf.d/secrets.yaml >/dev/null <<EOF
macaroon_secret_key: "$(openssl rand -base64 48 | tr -d '\n')"
form_secret: "$(openssl rand -base64 48 | tr -d '\n')"
EOF
sudo chown root:matrix-synapse /etc/matrix-synapse/conf.d/secrets.yaml
sudo chmod 640 /etc/matrix-synapse/conf.d/secrets.yaml

Registrierungs-Secret separat ablegen, damit es nicht in einer YAML steht:

openssl rand -hex 32 | sudo tee /etc/matrix-synapse/registration_shared_secret >/dev/null
sudo chown root:matrix-synapse /etc/matrix-synapse/registration_shared_secret
sudo chmod 640 /etc/matrix-synapse/registration_shared_secret

Start:

sudo systemctl restart matrix-synapse
sudo systemctl status matrix-synapse
curl -s http://127.0.0.1:8008/_matrix/client/versions

4. nginx

nginx/matrix.conf nach /etc/nginx/sites-available/ kopieren, verlinken und ein Zertifikat holen:

sudo certbot certonly --webroot -w /var/www/html -d matrix.example.com
sudo ln -s /etc/nginx/sites-available/matrix.example.com \
           /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Zwei Details in der Konfiguration sind nicht optional:

  • client_max_body_size muss mindestens so groß sein wie max_upload_size in Synapse, sonst brechen Uploads mit einem nginx-413 ab, bevor Synapse sie sieht.
  • proxy_read_timeout muss großzügig sein. Clients halten /sync als Long-Poll offen; beim nginx-Standard von 60 Sekunden reißt die Verbindung ständig ab.

5. Well-Known-Delegation

Im vHost der Apex-Domain (example.com):

location = /.well-known/matrix/server {
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
    return 200 '{"m.server": "matrix.example.com:443"}';
}

location = /.well-known/matrix/client {
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
    return 200 '{"m.homeserver": {"base_url": "https://matrix.example.com"}}';
}

Der Access-Control-Allow-Origin-Header ist beim Client-Dokument zwingend ohne ihn verweigern Browser-Clients die Abfrage.

Prüfen:

curl -s https://example.com/.well-known/matrix/server
curl -s https://example.com/.well-known/matrix/client

6. Admin-Benutzer anlegen

Die Registrierung ist bewusst geschlossen (enable_registration: false), sonst wird der Server binnen Tagen als Spam-Relay missbraucht. Benutzer werden per Shared Secret angelegt.

register_new_matrix_user liest nur die mit -c übergebene Datei. Liegt das Secret in conf.d/, findet es der Befehl nicht deshalb direkt übergeben:

SECRET=$(sudo cat /etc/matrix-synapse/registration_shared_secret)
sudo register_new_matrix_user -k "$SECRET" \
  -u admin -p 'PASSWORT' -a http://127.0.0.1:8008

-a macht den Benutzer zum Server-Admin. Kontrolle:

sudo -u postgres psql -d synapse -c "SELECT name, admin FROM users;"

7. Funktionsprüfung

# Login über die öffentliche URL
curl -s -X POST https://matrix.example.com/_matrix/client/v3/login \
  -H 'Content-Type: application/json' \
  -d '{"type":"m.login.password",
       "identifier":{"type":"m.id.user","user":"admin"},
       "password":"PASSWORT"}'

# Föderation von außen prüfen (offizieller Tester)
curl -s "https://federationtester.matrix.org/api/report?server_name=example.com" \
  | python3 -c "import json,sys; print('FederationOK:', json.load(sys.stdin)['FederationOK'])"

FederationOK: True ist das Ziel. Schlägt es fehl, liegt es fast immer an der Well-Known-Datei oder an einer unvollständigen Zertifikatskette.

Betrieb

sudo systemctl status matrix-synapse
sudo journalctl -u matrix-synapse -f

Datenbank sichern:

sudo -u postgres pg_dump -Fc synapse > synapse-$(date +%F).dump

Mitzusichern sind außerdem:

  • /etc/matrix-synapse/homeserver.signing.key ohne diesen Schlüssel ist der Server für andere Server eine andere Identität. Nicht ersetzbar.
  • /etc/matrix-synapse/conf.d/ enthält die Secrets
  • /var/lib/matrix-synapse/media hochgeladene Dateien

Stolpersteine

Symptom Ursache
Start bricht mit Collation-Fehler ab Datenbank ohne LC_COLLATE='C' angelegt
„Config is missing macaroon_secret_key“ secrets.yaml fehlt
Uploads scheitern mit 413 client_max_body_size < max_upload_size
Clients verlieren dauernd die Verbindung proxy_read_timeout zu klein
Föderation schlägt fehl Well-Known falsch oder Zertifikatskette unvollständig
IDs lauten @name:matrix.example.com server_name falsch gesetzt nicht mehr korrigierbar