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
8.6 KiB
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_nameist 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_sizemuss mindestens so groß sein wiemax_upload_sizein Synapse, sonst brechen Uploads mit einem nginx-413 ab, bevor Synapse sie sieht.proxy_read_timeoutmuss großzügig sein. Clients halten/syncals 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 |