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
142 lines
4.8 KiB
Markdown
142 lines
4.8 KiB
Markdown
# Element Web
|
||
|
||
Web-Client für den eigenen Matrix-Server, ausgeliefert als statische Dateien
|
||
über nginx.
|
||
|
||
| Punkt | Wert |
|
||
|---|---|
|
||
| Software | `element-web` (Release-Tarball) |
|
||
| Öffentlich | `https://element.example.com` |
|
||
| Verzeichnis | `/var/www/element` |
|
||
|
||
## Warum eine eigene Domain?
|
||
|
||
Element **darf nicht** unter derselben Domain laufen wie die Client-API des
|
||
Homeservers. Beide teilen sich sonst denselben Origin, und eine Schwachstelle im
|
||
Client könnte direkt auf die API zugreifen. Deshalb:
|
||
|
||
- `matrix.example.com` → nur Synapse
|
||
- `element.example.com` → nur der Web-Client
|
||
|
||
## 1. Herunterladen und Signatur prüfen
|
||
|
||
```bash
|
||
VER=$(curl -s https://api.github.com/repos/element-hq/element-web/releases/latest \
|
||
| python3 -c "import json,sys; print(json.load(sys.stdin)['tag_name'])")
|
||
echo "$VER"
|
||
|
||
curl -fLO "https://github.com/element-hq/element-web/releases/download/${VER}/element-${VER}.tar.gz"
|
||
curl -fLO "https://github.com/element-hq/element-web/releases/download/${VER}/element-${VER}.tar.gz.asc"
|
||
```
|
||
|
||
Die Signatur zu prüfen ist hier keine Formsache: das Paket läuft später im
|
||
Browser mit vollem Zugriff auf die Sitzung.
|
||
|
||
```bash
|
||
curl -fsSL -o element-release-key.gpg https://packages.element.io/element-release-key.gpg
|
||
gpg --import element-release-key.gpg
|
||
gpg --verify element-${VER}.tar.gz.asc element-${VER}.tar.gz
|
||
```
|
||
|
||
Erwartet wird `Good signature from "Element Releases <releases@riot.im>"` mit dem
|
||
Fingerprint `712B FBEE 92DC A452 52DB 17D7 C7BE 97EF A179 B100`.
|
||
|
||
Die Meldung „This key is not certified with a trusted signature“ ist dabei
|
||
normal – sie besagt nur, dass der Schlüssel lokal nicht als vertrauenswürdig
|
||
markiert wurde. Entscheidend ist, dass der Fingerprint stimmt.
|
||
|
||
## 2. Ausrollen
|
||
|
||
```bash
|
||
sudo tar xzf element-${VER}.tar.gz -C /var/www
|
||
sudo rm -rf /var/www/element
|
||
sudo mv /var/www/element-${VER} /var/www/element
|
||
sudo chown -R www-data:www-data /var/www/element
|
||
```
|
||
|
||
## 3. Konfiguration
|
||
|
||
`config.json.example` nach `/var/www/element/config.json` kopieren und anpassen.
|
||
Wichtig ist der Unterschied der beiden Felder:
|
||
|
||
- `base_url` → wo die API tatsächlich liegt (`https://matrix.example.com`)
|
||
- `server_name` → was dem Benutzer angezeigt wird (`example.com`)
|
||
|
||
```json
|
||
{
|
||
"default_server_config": {
|
||
"m.homeserver": {
|
||
"base_url": "https://matrix.example.com",
|
||
"server_name": "example.com"
|
||
}
|
||
},
|
||
"disable_guests": true
|
||
}
|
||
```
|
||
|
||
## 4. nginx
|
||
|
||
`nginx/element.example.com.conf` und `nginx/element-security.conf` kopieren:
|
||
|
||
```bash
|
||
sudo cp nginx/element-security.conf /etc/nginx/snippets/
|
||
sudo cp nginx/element.example.com.conf /etc/nginx/sites-available/
|
||
sudo ln -s /etc/nginx/sites-available/element.example.com.conf /etc/nginx/sites-enabled/
|
||
sudo nginx -t && sudo systemctl reload nginx
|
||
```
|
||
|
||
### Zwei Fallstricke in der nginx-Konfiguration
|
||
|
||
**Caching.** `index.html`, `config.json` und `version` dürfen nicht dauerhaft
|
||
gecacht werden. Sonst zeigt der Browser nach einem Update weiter die alte
|
||
Version oder alte Serverdaten. Die Dateien unter `/bundles/` tragen dagegen
|
||
einen Hash im Namen und dürfen unbegrenzt gecacht werden.
|
||
|
||
**Header-Vererbung.** nginx vererbt `add_header` **nicht**, sobald ein
|
||
`location`-Block eigene `add_header`-Direktiven enthält. Da `location /` per
|
||
`try_files` auf `/index.html` verweist und dieser Block ein eigenes
|
||
`Cache-Control` setzt, würden die Sicherheitsheader dort stillschweigend
|
||
verschwinden. Deshalb liegen sie in einem Snippet, das in **jedem** betroffenen
|
||
Block eingebunden wird.
|
||
|
||
Kontrolle:
|
||
|
||
```bash
|
||
curl -s -o /dev/null -D - https://element.example.com/ | grep -iE '^x-|^strict|^referrer'
|
||
```
|
||
|
||
Es müssen `x-frame-options`, `x-content-type-options`, `referrer-policy` und
|
||
`strict-transport-security` auftauchen.
|
||
|
||
## 5. Prüfung
|
||
|
||
```bash
|
||
curl -s -o /dev/null -w "%{http_code}\n" https://element.example.com/
|
||
curl -s https://element.example.com/version
|
||
curl -s https://element.example.com/config.json
|
||
```
|
||
|
||
Danach im Browser öffnen und mit einem Konto anmelden. Der Anmeldedialog sollte
|
||
`example.com` als Server anzeigen, nicht `matrix.example.com`.
|
||
|
||
## Aktualisieren
|
||
|
||
Element ist rein statisch – ein Update ist ein Austausch des Verzeichnisses.
|
||
Die `config.json` liegt im Verzeichnis und muss dabei gesichert werden:
|
||
|
||
```bash
|
||
sudo cp /var/www/element/config.json /tmp/element-config.json
|
||
# ... neue Version wie oben entpacken ...
|
||
sudo cp /tmp/element-config.json /var/www/element/config.json
|
||
sudo chown -R www-data:www-data /var/www/element
|
||
```
|
||
|
||
## Stolpersteine
|
||
|
||
| Symptom | Ursache |
|
||
|---|---|
|
||
| Nach Update alte Version im Browser | `index.html`/`version` wurden gecacht |
|
||
| Sicherheitsheader fehlen | `add_header`-Vererbung durch eigenen `location`-Block gekippt |
|
||
| Anmeldung zeigt falschen Servernamen | `server_name` in `config.json` falsch |
|
||
| Konfiguration nach Update weg | `config.json` liegt im ausgetauschten Verzeichnis |
|