# 🐳 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:** ```bash 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 ```bash 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):** ```bash # Stelle sicher, dass ~/.kube/config existiert und den richtigen Cluster enthält kubectl get nodes ``` 2. **Im Container:** ```bash 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 ```bash # 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: ```bash # 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`: ```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 ` 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): ```bash ./scripts/install-hooks.sh ``` Mehr Details: `docs/ops-configmap-sync.md` ## 📝 Nützliche Befehle ```bash # 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:** ```bash 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: ```bash # 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: ```bash # Host kubectl get nodes # Test, ob Zugriff existiert # Dann Container neustarten ``` ### Problem: `HelmChart is not ready: stat ... no such file or directory` Siehe `README.md` → **Issue 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.md` → **Issue 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.md` → **Issue 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.io` → `404 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: ```bash 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 - [Dev Containers Docs](https://containers.dev) - [FluxCD Dokumentation](https://fluxcd.io) - [SOPS Anleitung](https://github.com/getsops/sops) - **Projekt-README:** `README.md` (Architektur, Issues, Best Practices) - **Setup-Docs:** `docs/setup/` - **Install-Guide:** `docs/install.md`