The devcontainer could never actually be built successfully - verified by building it from scratch for the first time in a while. Found and fixed six issues: - kubectl: apt.kubernetes.io was deprecated/shut down by Google in 2023, switched to the official successor repo pkgs.k8s.io - docker-ce-cli: apt line hardcoded arch=amd64, breaking the build on Apple Silicon; resolved dynamically via dpkg --print-architecture - useradd -G docker failed because only the Docker CLI (no daemon) is installed, so no package ever creates the docker group; added explicit groupadd - oh-my-zsh install had a nested-quoting bug that made the RUN step fail; simplified to download-then-run instead of one nested `su -c "sh -c ..."` - sops binary was hardcoded to linux.amd64, only working on arm64 by luck via Docker Desktop's QEMU emulation; resolved dynamically like docker-ce - docker.sock was mounted but unusable (permission denied) since the container's docker group GID never matched the host socket's GID; added a root entrypoint (docker-init.sh) that reconciles this at container start, then drops to the vscode user via gosu Also fixed two stale mas-secrets.sops.yaml references (actual filename is mas-secret.yaml) in README.md and postCreateCommand.sh, set the vscode user's default shell to zsh (oh-my-zsh was installed but never used by default), and documented all of the above plus a build+run verification snippet in README.md so this class of drift is caught before it goes unnoticed again. Verified end-to-end: cold `docker build --no-cache`, then a real container run against the actual mounted kubeconfig, age key, and docker socket - kubectl reaches the live cluster, sops decrypts a real secret, and docker ps talks to the real daemon as the vscode user. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🐳 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
-
VSCode Extension installieren:
- Öffne VSCode → Extensions → Suche nach
Dev Containers(Microsoft) - Installiere sie
- Öffne VSCode → Extensions → Suche nach
-
GitOps Verzeichnis öffnen:
cd "april mit Ansible/prod/gitops" code . -
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)
- Klick auf
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
-
Host-Machine (z.B. macOS):
# Stelle sicher, dass ~/.kube/config existiert und den richtigen Cluster enthält kubectl get nodes -
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.yamldefiniert, dass Secrets mitageverschlü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:
- Docker Desktop installieren (mit WSL2 Backend)
- VSCode mit WSL Extension öffnen
- Im WSL Terminal:
cd /mnt/c/path/to/projekt code . - 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.md → Issue 1. Kontrolliere:
HelmRepositorynutzttype: 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 imingress:Block seinserverNamemuss auf Root-Ebene dervaluesstehen- 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: falsesetzen- Oder
.well-known/matrix/servermanuell aufelementWebweiterleiten
⚠️ 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:
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
- FluxCD Dokumentation
- SOPS Anleitung
- Projekt-README:
README.md(Architektur, Issues, Best Practices) - Setup-Docs:
docs/setup/ - Install-Guide:
docs/install.md