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
271 lines
8.6 KiB
Markdown
271 lines
8.6 KiB
Markdown
# 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
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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**:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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`):
|
||
|
||
```nginx
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
sudo -u postgres psql -d synapse -c "SELECT name, admin FROM users;"
|
||
```
|
||
|
||
## 7. Funktionsprüfung
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
sudo systemctl status matrix-synapse
|
||
sudo journalctl -u matrix-synapse -f
|
||
```
|
||
|
||
Datenbank sichern:
|
||
|
||
```bash
|
||
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 |
|