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
4.8 KiB
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 Synapseelement.example.com→ nur der Web-Client
1. Herunterladen und Signatur prüfen
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.
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
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)
{
"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:
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:
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
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:
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 |