Warnung ergaenzt, dass der wiki-Branch ein ueberholter Mai-Abzug ist und nicht die gepflegte Fassung (ADR-0006 im management-Repo). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
308 lines
15 KiB
Markdown
308 lines
15 KiB
Markdown
# 🚀 Element Server Suite (ESS) Community – GitOps Deployment Guide
|
||
|
||
Dieses Repository enthält die Infrastruktur-as-Code (IaC) für den Matrix-Homeserver (basierend auf der Element Server Suite Community Edition), der per **FluxCD** nach GitOps-Prinzipien verwaltet wird.
|
||
|
||
## 📑 Inhaltsverzeichnis
|
||
|
||
1. [Voraussetzungen & Lokale Tools](#1-voraussetzungen--lokale-tools)
|
||
2. [Architektur & Logik des Stacks](#2-architektur--logik-des-stacks)
|
||
3. [Aufbau des Repositories](#3-aufbau-des-repositories)
|
||
4. [Das Deployment (Aktueller Stand)](#4-das-deployment-aktueller-stand)
|
||
5. [Nützliche Befehle](#5-nützliche-befehle)
|
||
6. [Troubleshooting & Known Issues](#6-troubleshooting--known-issues)
|
||
7. [Weitere Ressourcen](#7-weitere-ressourcen)
|
||
|
||
-----
|
||
|
||
## 1\. Voraussetzungen & Lokale Tools
|
||
|
||
**Empfohlen: `.devcontainer/` nutzen** ("Reopen in Container" in VS Code, oder `docker build`
|
||
+ `docker run` manuell, siehe [`.devcontainer/README.md`](.devcontainer/README.md)) - bringt
|
||
alle unten genannten Tools bereits fertig eingerichtet mit, ohne sie lokal zu installieren.
|
||
|
||
Alternativ, um mit diesem Stack zu interagieren (Konfigurationen anzupassen, Secrets zu verschlüsseln, Fehler zu suchen), müssen folgende Tools lokal installiert sein:
|
||
|
||
### 🛠️ Benötigte CLI-Tools
|
||
|
||
* **`kubectl`**: Für die direkte Kommunikation mit dem Kubernetes-Cluster.
|
||
* **`flux`**: Für das manuelle Anstoßen von GitOps-Synchronisationen.
|
||
* **`sops`** & **`age`** (oder GPG): Für die Ver- und Entschlüsselung von Secrets direkt im Git-Repo.
|
||
* **`helm`**: (Optional) Zum Inspizieren von Chart-Values.
|
||
|
||
### 🍏 macOS (via Homebrew)
|
||
|
||
```bash
|
||
brew install kubectl fluxcd/tap/flux sops age helm
|
||
```
|
||
|
||
### 🐧 Linux
|
||
|
||
```bash
|
||
# kubectl & helm via Paketmanager (apt/dnf) oder curl
|
||
curl -sLS https://fluxcd.io/install.sh | sudo bash
|
||
# SOPS
|
||
wget https://github.com/getsops/sops/releases/download/v3.8.1/sops-v3.8.1.linux.amd64
|
||
sudo mv sops-v3.8.1.linux.amd64 /usr/local/bin/sops && sudo chmod +x /usr/local/bin/sops
|
||
sudo apt install age
|
||
```
|
||
|
||
### 🪟 Windows (via Winget oder WSL2)
|
||
|
||
*Empfehlung: Nutze WSL2 (Ubuntu) und folge den Linux-Schritten.* Nativ via Winget:
|
||
|
||
```powershell
|
||
winget install Kubernetes.kubectl FluxCD.Flux Mozilla.sops age-encryption.age Helm.Helm
|
||
```
|
||
|
||
### ⚙️ Lokale Konfiguration
|
||
|
||
1. **Kubeconfig:** Stelle sicher, dass die Datei `~/.kube/config` mit den Zugangsdaten zu deinem K3s-Cluster gefüllt ist. Test: `kubectl get nodes`.
|
||
2. **SOPS Key:** Du benötigst den privaten `age`-Key (oder GPG-Key), der in der `.sops.yaml` des Repositories hinterlegt ist, um Secrets bearbeiten zu können.
|
||
3. **Git Hooks installieren:** Nach dem Klonen dieses Repositories müssen Git Hooks installiert werden, um ConfigMap-Änderungen automatisch zu tracken:
|
||
```bash
|
||
cd prod/gitops
|
||
./scripts/install-hooks.sh
|
||
```
|
||
Siehe [📖 GitOps ConfigMap Auto-Sync](docs/ops-configmap-sync.md) für Details.
|
||
|
||
-----
|
||
|
||
## 2\. Architektur & Logik des Stacks
|
||
|
||
Das Setup basiert auf einer modernen, modularen GitOps-Architektur:
|
||
|
||
### Management-Komponenten
|
||
|
||
* **K3s**: Die leichtgewichtige Kubernetes-Distribution, die als Fundament dient.
|
||
* **FluxCD**: Der GitOps-Controller. Er überwacht dieses Git-Repository. Ändert sich hier eine Datei, wendet Flux die Änderung automatisch im Cluster an.
|
||
* **SOPS + age**: Erlaubt es, Secrets verschlüsselt in Git zu speichern. Flux entschlüsselt diese "on the fly" im Cluster. Mehrere Secrets nutzen zusätzlich einen zweiten, eng gescopten age-Key für automatisierte Rotation (siehe coturn TURN-Secret unten).
|
||
* **Traefik**: Der Ingress-Controller (Standard bei K3s). Er leitet Traffic von Port 80/443 an die richtigen internen Pods weiter.
|
||
* **Cert-Manager**: Spricht mit Let's Encrypt und stellt automatisch gültige TLS-Zertifikate für alle Ingress-Routen aus.
|
||
* **NetworkPolicies**: Default-Deny Ingress für die `matrix`- und `authentik`-Namespaces, mit expliziten Allow-Regeln pro Komponente (`apps/production/networkpolicy.yaml`, `apps/authentik/networkpolicy.yaml`).
|
||
|
||
### Matrix Stack (ESS Community v26.4.0)
|
||
|
||
Die Suite ist ein "Umbrella Chart", das aus mehreren Microservices besteht:
|
||
|
||
* **Synapse (`matrix.`):** Das eigentliche Backend (Homeserver) für die Chat-Nachrichten.
|
||
* **Matrix Authentication Service (MAS) (`account.`):** Der OIDC-basierte Login-Server. Zwingend erforderlich für moderne Matrix-Clients.
|
||
* **Element Web (`domain.tld`):** Eigener Fork (`sorb/threadnet-web`) des Web-Clients für die Endnutzer - Custom Themes, Element Desktop Setup-Seiten, Element-Call-Anpassungen.
|
||
* **Matrix RTC (`mrtc.`):** Die SFU (Selective Forwarding Unit) für Audio-/Video-Calls, mit eigenem Element-Call-Fork (`sorb/threadnet-call`) für höhere Video-Defaults (bis 1440p/60fps).
|
||
* **coturn:** TURN/STUN-Server für WebRTC hinter NAT (`hostNetwork: true`, außerhalb der NetworkPolicy-Kontrolle, stattdessen über die Hetzner Cloud Firewall abgesichert). Shared Secret wird monatlich automatisiert rotiert.
|
||
* **PostgreSQL:** Die relationale Datenbank für Synapse und MAS.
|
||
|
||
### Identity & Observability
|
||
|
||
* **Authentik** (`auth.`, `account.`): OIDC-Identity-Provider für Matrix-Enrollment, Passwort-Recovery und optionales 2FA/Passkey. Flows/Provider/Application deklarativ als Authentik-Blueprints erfasst (`apps/authentik/authentik-blueprints.yaml`), nicht nur in der UI geklickt.
|
||
* **Monitoring**: Grafana Alloy sammelt Metriken/Logs, Remote-Write zu einem externen Prometheus/Loki-Stack.
|
||
* **Backups**: Nächtliche, verschlüsselte & deduplizierte Borg-Backups (Postgres-Dumps + Synapse-`media_store`) zu einer Hetzner Storage Box, getrennt nach Namespace, mit eigenen Repos/Passphrasen.
|
||
|
||
### Moderation & Content Scanning
|
||
|
||
* **Draupnir**: Moderationsbot (Community-Nachfolger von Mjolnir) für Ban-Listen/Policy-Rooms.
|
||
* **ClamAV**: Zwei Bausteine für unterschiedliche Räume - ein eigenes Synapse-Modul (`clamav_spam_checker.py`) scannt Uploads in unverschlüsselten Räumen; ein zusätzlicher, eigenständiger `clamav-http-scanner`-Dienst wird vom gepatchten Element-Web-Client (`sorb/threadnet-web`) sowohl beim Senden als auch beim Empfangen aufgerufen und deckt damit auch verschlüsselte Räume/DMs ab. Details: `docs/deployment-guides/06-moderation-content-scanning.md`.
|
||
|
||
### Host-Level (nicht-GitOps) Änderungen
|
||
|
||
* `host-config/` ist bewusst der einzige Teil dieses Repos, den Flux **nicht** verwaltet - Skripte/systemd-Units, die direkt auf dem nackten Hetzner-Host laufen (z.B. `unattended-upgrades`-Vorab-Benachrichtigungen), für Dinge, die strukturell außerhalb der Reichweite von Flux liegen. Deployment erfolgt manuell per SSH, instanzspezifische Werte liegen in einer Config-Datei auf dem Host, nicht im versionierten Skript. Details: `docs/deployment-guides/07-host-maintenance-notifications.md`.
|
||
|
||
-----
|
||
|
||
## 3\. Aufbau des Repositories
|
||
|
||
Das Repository ist strikt nach "Infrastruktur" und "Applikation" getrennt, um Abhängigkeiten korrekt zu laden.
|
||
|
||
```text
|
||
gitops/
|
||
├── .sops.yaml # Definiert, wie Secrets verschlüsselt werden
|
||
├── clusters/matrix/ # Der Einstiegspunkt für FluxCD
|
||
├── apps/
|
||
│ ├── base/
|
||
│ │ ├── infra/ # Core-Dienste (Cert-Manager, Namespaces)
|
||
│ │ └── matrix/ # Die OCI Helm-Repository Definition für ESS
|
||
│ └── production/ # Das eigentliche Matrix-Deployment
|
||
│ ├── kustomization.yaml # Inhaltsverzeichnis
|
||
│ ├── element-server-suite.yaml # Das HelmRelease (Bestellung an Flux)
|
||
│ ├── cert-issuer.yaml # Let's Encrypt Konfiguration
|
||
│ ├── matrix-postgres-auth.yaml # DB-Passwörter
|
||
│ └── custom-configs/ # Eigene Anpassungen (Themes, Logging)
|
||
│ ├── synapse-values.yaml # Als ConfigMap
|
||
│ ├── element-values.yaml # Als ConfigMap
|
||
│ └── mas-secret.yaml # Als verschlüsseltes SOPS-Secret
|
||
```
|
||
|
||
Weitere Secret-Dateien liegen direkt unter `apps/production/` bzw. `apps/authentik/`
|
||
(z.B. `coturn-secret.yaml`, `synapse-turn-secret.yaml`, `synapse-backup-secret.yaml`,
|
||
`authentik-backup-secret.yaml`) - jede einzeln SOPS-verschlüsselt, nicht in `custom-configs/`
|
||
gebündelt.
|
||
|
||
### Repo-Topologie (seit 2026-07-31)
|
||
|
||
**Kanonisch ist `git.lab/axion1337.chat/axion1337.chat-gitops`** (Homelab-GitLab, nur im
|
||
Lab auflösbar) — dort wird gepusht und läuft der CI-Verifikations-Job (`.gitlab-ci.yml`).
|
||
Die Kopie auf `rohana.axion1337.de` ist ein automatischer **Push-Mirror** und bleibt die
|
||
**Flux-Quelle**: der Cluster zieht unverändert von Gitea, der Mirror liefert. **Niemals
|
||
direkt nach rohana pushen** — der Mirror überschreibt divergente Stände.
|
||
|
||
**Issues und Wiki liegen seit 2026-08-01/02 ebenfalls auf git.lab**
|
||
([Issues](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues) ·
|
||
[Wiki](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/wikis/home) — der
|
||
Wiki-Reiter oben im Projekt). ⚠️ Die Issue-Nummern haben sich beim Umzug verschoben;
|
||
ein alter Verweis „gitops#N" meint die Gitea-Nummer, verbindlich ist der
|
||
Migrations-Fußtext im jeweiligen Issue. **Releases bleiben auf Gitea** (öffentlicher
|
||
Download-Pfad). Der `wiki`-Branch in diesem Repo ist ein **überholter Abzug von
|
||
`docs/` aus dem Mai** und nicht die gepflegte Fassung.
|
||
|
||
Alle Dokumentationsquellen zusammen (Plattform, Homelab, Arbeitsweise) gibt es unter
|
||
**[wiki.lab](https://wiki.lab)** — Konfiguration im Repo
|
||
[`homelab/wiki`](https://git.lab/homelab/wiki).
|
||
|
||
**Abhängigkeits-Logik:** Flux installiert erst `infra-apps` (damit Namespaces und Repositories existieren) und danach `production-apps` (das eigentliche ESS-Chart).
|
||
|
||
-----
|
||
|
||
## 4\. Das Deployment (Aktueller Stand)
|
||
|
||
### Das HelmRepository (OCI)
|
||
|
||
Element verteilt die Community-Edition modern über die GitHub Container Registry (`ghcr.io`). Klassische HTTP-Helm-Repos werfen hier oft 404-Fehler.
|
||
|
||
```yaml
|
||
# apps/base/matrix/ess-repo.yaml
|
||
apiVersion: source.toolkit.fluxcd.io/v1
|
||
kind: HelmRepository
|
||
metadata:
|
||
name: element-ess-oci
|
||
spec:
|
||
type: oci
|
||
url: oci://ghcr.io/element-hq/ess-helm
|
||
```
|
||
|
||
### Das HelmRelease (Das Herzstück)
|
||
|
||
Das ESS-Chart (`v26.4.0`) hat ein extrem striktes JSON-Schema. Konfigurationen müssen exakt sitzen:
|
||
|
||
* `serverName` muss an der Wurzel stehen.
|
||
* Komponenten werden in `camelCase` geschrieben (`elementWeb`, `synapseAdmin`).
|
||
* Zertifikate werden durch `certManager: true` automatisch gemanaged. **Keine manuellen TLS-Einträge im Ingress-Block\!**
|
||
|
||
<!-- end list -->
|
||
|
||
```yaml
|
||
# apps/production/element-server-suite.yaml (Auszug)
|
||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||
kind: HelmRelease
|
||
metadata:
|
||
name: matrix-stack
|
||
spec:
|
||
chart:
|
||
spec:
|
||
chart: matrix-stack
|
||
version: "26.4.0"
|
||
valuesFrom:
|
||
- kind: ConfigMap
|
||
name: ess-synapse-custom
|
||
valuesKey: values.yaml
|
||
- kind: Secret
|
||
name: ess-mas-values-secret
|
||
valuesKey: values.yaml
|
||
- kind: Secret
|
||
name: synapse-turn-secret
|
||
valuesKey: values.yaml
|
||
values:
|
||
serverName: axion1337.chat
|
||
certManager: true
|
||
postgres:
|
||
enabled: true
|
||
synapse:
|
||
enabled: true
|
||
ingress: { host: matrix.axion1337.chat }
|
||
matrixAuthenticationService:
|
||
enabled: true
|
||
ingress: { host: account.axion1337.chat }
|
||
elementWeb:
|
||
enabled: true
|
||
ingress: { host: axion1337.chat }
|
||
wellKnownDelegation:
|
||
enabled: false # ! WICHTIG (Siehe Troubleshooting)
|
||
```
|
||
|
||
-----
|
||
|
||
## 5\. Nützliche Befehle
|
||
|
||
### 🔄 Flux / GitOps Sync erzwingen
|
||
|
||
Wenn man nicht auf den automatischen 10-Minuten-Timer von Flux warten will:
|
||
|
||
```bash
|
||
flux reconcile kustomization flux-system --with-source
|
||
flux reconcile kustomization production-apps --with-source
|
||
```
|
||
|
||
### 🔍 Status des Deployments prüfen
|
||
|
||
```bash
|
||
# Zeigt, ob Flux das Chart akzeptiert und angewendet hat
|
||
flux get helmreleases -A
|
||
|
||
# Zeigt an, ob die Pods erfolgreich starten
|
||
kubectl get pods -n matrix
|
||
```
|
||
|
||
### 🔐 Zertifikate (Let's Encrypt) debuggen
|
||
|
||
```bash
|
||
# Sind die Zertifikate da und gültig?
|
||
kubectl get certificate -n matrix
|
||
|
||
# Wo hängt der Request? (403 Fehler etc.)
|
||
kubectl get certificaterequest -n matrix
|
||
kubectl get challenges -n matrix
|
||
kubectl describe challenge <name> -n matrix
|
||
```
|
||
|
||
### 🛡️ Secrets mit SOPS bearbeiten
|
||
|
||
Um ein Passwort im GitOps-Repo zu ändern, editiert man die verschlüsselte Datei direkt via SOPS (sie wird transparent entschlüsselt und beim Speichern wieder verschlüsselt):
|
||
|
||
```bash
|
||
sops apps/production/custom-configs/mas-secret.yaml
|
||
```
|
||
|
||
-----
|
||
|
||
## 6\. Troubleshooting & Known Issues
|
||
|
||
### Issue 1: `HelmChart is not ready: stat ... no such file or directory`
|
||
|
||
* **Ursache:** Falscher Versuch, das Chart direkt aus dem GitHub-Repo-Code (als GitRepository) zu lesen. Das Chart erfordert Sub-Charts, die so nicht gerendert werden können.
|
||
* **Lösung:** Immer das OCI-Repository (`oci://ghcr.io/...`) und den Chartnamen `matrix-stack` verwenden.
|
||
|
||
### Issue 2: `values don't meet the specifications of the schema(s)`
|
||
|
||
* **Ursache:** Ab Version 26.x hat ESS ein sehr rigides JSON-Schema.
|
||
* **Lösung:** Logs genau lesen.
|
||
* `tls` darf nicht in den Ingress-Block der Komponenten.
|
||
* `serverName` muss ins Top-Level, nicht unter `synapse`.
|
||
* Keine `config:` Blöcke für Core-Komponenten.
|
||
|
||
### Issue 3: Let's Encrypt Error `403 Order's status is processing` auf der Hauptdomain
|
||
|
||
* **Ursache (Die ACME Race Condition):** Wenn `elementWeb` (auf `axion1337.chat`) und `wellKnownDelegation` (ebenfalls auf `axion1337.chat`) gleichzeitig aktiviert sind, fordert `cert-manager` zeitgleich zwei Zertifikate für dieselbe Domain an. Let's Encrypt blockt den zweiten Versuch und das Ingress-Setup hängt sich auf.
|
||
* **Lösung:** `wellKnownDelegation: enabled: false` im Helm-Chart setzen. Das `.well-known/matrix/server` File muss stattdessen entweder als statische JSON-Datei auf dem Webserver der Hauptdomain hinterlegt oder per Ingress-Route (Traefik Middleware) direkt auf den Synapse-Dienst umgebogen werden.
|
||
|
||
### Issue 4: Fehlende Zertifikate (`No resources found`)
|
||
|
||
* **Ursache:** Manuelle Kustomize-Patches kollidieren mit dem Helm-Chart.
|
||
* **Lösung:** Manuelle Patches löschen und das native Feature des Charts nutzen: `certManager: true` auf der obersten (Root-)Ebene der `values` setzen. Das Chart erstellt daraufhin die korrekten Ingress-Annotations und Secrets von selbst.
|
||
|
||
-----
|
||
|
||
## 7\. Weitere Ressourcen
|
||
|
||
* **`CLAUDE.md`** (Repo-Root): Technische Referenz für KI-gestützte Arbeit an diesem Repo - Architektur, bekannte Chart-Quirks, Troubleshooting-Checkliste.
|
||
* **`docs/TASKS.md`**: Backlog-Pointer zu den [Gitea Issues](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues) - Details werden nicht mehr doppelt gepflegt.
|
||
* **[Gitea Releases](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/releases)**: Versionshistorie (SemVer, `vMAJOR.MINOR.PATCH` als Änderungsgrößen-Konvention, kein Kompatibilitätsvertrag - siehe [[00-TASKS]] Wiki für die Konvention).
|
||
* **[Wiki](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/wikis/home)** (auf git.lab, Reiter *Wiki*): Ausführliche Historie, Incident-Notizen, Setup-Guides pro Komponente. Zusammen mit Homelab- und Verfahrensdoku auch unter **[wiki.lab](https://wiki.lab)**.
|
||
* **`docs/deployment-guides/`**: Detaillierte Guides für TURN-Server, Authentik, Monitoring, Element-Customization, Room-Policies, Moderation & Content-Scanning, Host-Wartungsbenachrichtigungen. |