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
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user