Files
Thore CimbalandClaude Sonnet 5 eabde3747e fix(docs): make todo-tree detect markdown checkboxes, clean up stale TASKS.md backlog
todo-tree stopped triggering on docs/TASKS.md because the file was
restructured (2026-07-28 backlog migration) to use plain markdown
checkboxes with no literal TODO/FIXME/etc. keywords, which is all
todo-tree's default config matches on. Added the documented
todo-tree.regex.regex + [ ]/[x] tags configuration (see
Gruntfuggly/todo-tree wiki) so it actually detects checkbox items, plus
red/green highlighting for open vs done.

Also cleaned up 19 stale open checkbox items left behind by that same
migration - they duplicated content already tracked as individual Gitea
issues (in old pre-migration detail, not the established "-> Issue #N"
pointer format the rest of the file already uses), including two
(Database Backup Strategy, Synapse Media PVC Backups) for issues that
are actually already closed. Converted all to pointer format or removed
where closed. Replaced the stale M1-M7 milestone table (contradicted its
own file header - said M4 "In Progress" while the summary line above
already said 0 in progress) with a pointer to the new SemVer Releases.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
..

🐳 DevContainer für ESS Community GitOps

Dieses DevContainer-Setup ermöglicht dir, auf macOS, Windows und Linux einheitlich zu entwickeln.

🚀 Schnelstart

VSCode mit Remote Containers Extension

  1. VSCode Extension installieren:

    • Öffne VSCode → Extensions → Suche nach Dev Containers (Microsoft)
    • Installiere sie
  2. GitOps Verzeichnis öffnen:

    cd "april mit Ansible/prod/gitops"
    code .
    
  3. DevContainer starten:

    • Klick auf >< Symbol unten links in VSCode
    • Wähle Reopen in Container
    • Warte, bis das Image gebaut wurde (~3-5 Min beim ersten Mal)

Alternative: Docker + CLI

docker build -t ess-gitops .devcontainer
docker run -it --rm \
  -v ~/.kube:/home/vscode/.kube \
  -v ~/.ssh:/home/vscode/.ssh \
  -v ~/.age:/home/vscode/.age \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ess-gitops

📦 Enthaltene Tools

  • kubectl - Kubernetes CLI
  • flux - FluxCD GitOps Controller CLI
  • helm - Kubernetes Package Manager
  • sops - Secret Operations (Verschlüsselung)
  • age - Modern File Encryption
  • docker - Container CLI (über Host-Socket)
  • git - Versionskontrolle
  • jq/yq - JSON/YAML Processing
  • zsh + oh-my-zsh - Shell mit Plugins

🔐 Wichtige Verzeichnis-Binds

Der Container mountet automatisch:

Host Container Zweck
~/.kube /home/vscode/.kube Kubernetes Config
~/.ssh /home/vscode/.ssh SSH Keys
~/.age /home/vscode/.age Age Encryption Keys
/var/run/docker.sock /var/run/docker.sock Docker Daemon (für docker Befehle)

⚙️ Kubeconfig Einrichten

  1. Host-Machine (z.B. macOS):

    # Stelle sicher, dass ~/.kube/config existiert und den richtigen Cluster enthält
    kubectl get nodes
    
  2. Im Container:

    kubectl get nodes  # Sollte jetzt auch dein Cluster zeigen
    kubectl config current-context
    

🔐 SOPS + Age Setup

Damit du Secrets bearbeiten kannst, brauchst du den privaten age-Key. Dieser ist in .sops.yaml konfiguriert.

Schritt 1: Age-Key bereitstellen

# Host-Machine: Key-Datei erstellen
mkdir -p ~/.age
# Füge deinen privaten Key ein (Format: "age-secret-key-...")
echo "age-secret-key-xxx..." > ~/.age/keys.txt
chmod 600 ~/.age/keys.txt

Schritt 2: Im Container konfigurieren

Der Container mounted ~/.age automatisch. Setze die Umgebungsvariable:

# Im Container-Terminal (SOPS_AGE_KEY_FILE ist bereits automatisch gesetzt!)
# Jetzt kannst du Secrets bearbeiten (wird transparent ver-/entschlüsselt):
sops apps/production/custom-configs/mas-secret.yaml

Schritt 3: VSCode Integration (optional)

Um die Umgebungsvariable beim Start zu setzen, nutze die .devcontainer/devcontainer.json:

"remoteEnv": {
  "KUBECONFIG": "/home/vscode/.kube/config",
  "SOPS_AGE_KEY_FILE": "/home/vscode/.age/keys.txt"
}

Wie es funktioniert

  • .sops.yaml definiert, dass Secrets mit age verschlüsselt werden
  • Beim Öffnen mit sops <datei> wird die Datei entschlüsselt → du editierst den plaintext in deinem Editor
  • Beim Speichern wird alles wieder automatisch verschlüsselt
  • Wichtig: Niemals den plaintext-Buffer commiten!

📝 Nach Container-Start: Git Hooks Installieren

Wichtig für die ConfigMap Auto-Sync (verhindert Merge-Konflikte):

./scripts/install-hooks.sh

Mehr Details: docs/ops-configmap-sync.md

📝 Nützliche Befehle

# Status des Deployments
kubectl get pods -n matrix
flux get helmreleases -A

# Secrets bearbeiten (mit verschlüsselung)
sops apps/production/custom-configs/mas-secret.yaml

# FluxCD Sync erzwingen
flux reconcile kustomization production-apps --with-source

# Zertifikate debuggen
kubectl get certificate -n matrix
kubectl describe certificate matrix-ingress -n matrix

# HelmRelease Status prüfen
flux describe helmrelease matrix-stack -n matrix

🛠️ Anpassungen für Windows/WSL2

Falls du Windows nutzt:

  1. Docker Desktop installieren (mit WSL2 Backend)
  2. VSCode mit WSL Extension öffnen
  3. Im WSL Terminal:
    cd /mnt/c/path/to/projekt
    code .
    
  4. Dann Dev Containers: Reopen in Container

Das funktioniert seamless, weil Docker Desktop unter WSL2 läuft.

🔧 Troubleshooting

Problem: SOPS_AGE_KEY_FILE not found

Lösung: Key muss in ~/.age/keys.txt auf der Host-Machine sein:

# Host
mkdir -p ~/.age
echo "your-age-private-key" > ~/.age/keys.txt

Der Container mountet ~/.age automatisch → sollte dann funktionieren.

Problem: kubectl: connection refused

Lösung: ~/.kube/config muss auf Host vorhanden sein:

# Host
kubectl get nodes  # Test, ob Zugriff existiert
# Dann Container neustarten

Problem: HelmChart is not ready: stat ... no such file or directory

Siehe README.mdIssue 1. Kontrolliere:

  • HelmRepository nutzt type: oci
  • URL ist oci://ghcr.io/element-hq/ess-helm

Problem: values don't meet the specifications of the schema

Siehe README.mdIssue 2. Häufige Fehler:

  • tls: darf nicht im ingress: Block sein
  • serverName muss auf Root-Ebene der values stehen
  • Komponenten-Namen: camelCase (z.B. elementWeb, matrixAuthenticationService)

Problem: Let's Encrypt 403 Order's status is processing

Siehe README.mdIssue 3. Kurz:

  • wellKnownDelegation: enabled: false setzen
  • Oder .well-known/matrix/server manuell auf elementWeb weiterleiten

⚠️ Wartungshinweis: Warum dieser Container regelmäßig getestet werden muss

Der Dockerfile installiert mehrere Tools über externe apt-Repos und Install-Skripte (pkgs.k8s.io, download.docker.com, GitHub-Releases, fluxcd.io/ohmyzsh.sh Installer). Diese Quellen sind nicht unter unserer Kontrolle und können jederzeit brechen — genau das ist am 2026-07-28 passiert: der Container konnte seit Fertigstellung nie erfolgreich gebaut werden, ohne dass es jemand bemerkt hat, weil niemand ihn zwischenzeitlich tatsächlich gebaut hat. Gefundene und behobene Probleme:

# Problem Ursache Fix
1 apt.kubernetes.io404 Not Found Google hat das alte Kubernetes-apt-Repo 2023 abgeschaltet Umgestellt auf das offizielle Nachfolge-Repo pkgs.k8s.io (versioniert pro k8s-Minor-Version, aktuell v1.34)
2 docker-ce-cli "has no installation candidate" auf Apple Silicon Repo-Zeile hatte arch=amd64 hartkodiert, Build lief aber auf arm64 arch=$(dpkg --print-architecture) zur Build-Zeit ermitteln
3 useradd: group 'docker' does not exist Nur die Docker-CLI wird installiert (kein Daemon), daher legt kein Paket die docker-Gruppe automatisch an groupadd docker explizit vor useradd
4 oh-my-zsh-Install schlägt mit Quoting-Fehler fehl Verschachtelte sh -c '...'-Anführungszeichen in einer Zeile Install-Skript erst in eine Datei laden, dann sauber mit su - vscode -c "sh /tmp/install-omz.sh --unattended" ausführen
5 sops-Binary war hart auf linux.amd64 gepinnt Lief auf Apple Silicon nur zufällig per QEMU-Emulation von Docker Desktop mit, nicht nativ Arch dynamisch über dpkg --print-architecture auflösen (linux.arm64 / linux.amd64)
6 docker.sock-Zugriff im Container: permission denied Der gemountete Host-Socket gehört (je nach Docker-Setup) einer Gruppe/GID, die im Container nicht existiert oder nicht der docker-Gruppe entspricht (auf Docker Desktop für Mac/Windows z.B. GID 0/root statt einer eigenen docker-Gruppe) docker-init.sh: Root-Entrypoint gleicht beim Container-Start die GID der docker-Gruppe an den tatsächlich gemounteten Socket an (bzw. tritt der GID-Inhaber-Gruppe bei, falls die GID schon vergeben ist), wechselt danach per gosu zu vscode

Konsequenz für die Zukunft: Vor jeder größeren Änderung an .devcontainer/ (oder mindestens vierteljährlich) einmal real bauen und laufen lassen:

docker build -f .devcontainer/Dockerfile -t ess-gitops-devcontainer-test .devcontainer
docker run --rm \
  -v ~/.kube:/home/vscode/.kube \
  -v ~/.age:/home/vscode/.age \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ess-gitops-devcontainer-test bash -c '
    kubectl version --client && helm version --short && flux --version && \
    sops --version && age --version && docker version --format "{{.Server.Version}}" && \
    id vscode
  '

Wenn docker version hier den echten Server, nicht nur die Client-Version zeigt, und id vscode die passende Docker-Gruppe/GID auflistet, funktioniert der Socket-Zugriff tatsächlich — nicht nur der Build.

📚 Weitere Ressourcen