Almost every tracked file in the repo had drifted to mode 777 on disk (only files created fresh this session were unaffected), and a chunk of that drift had already been committed as spurious +x bits on plain YAML/Markdown files (authentik.yaml, kustomization.yaml, coturn.yaml, element-server-suite.yaml, TASKS.md, install.md, etc.) - none of these need to be executable. Restored to 644 for regular files, 755 only for actual scripts (postCreateCommand.sh, docker-init.sh, install-hooks.sh, pre-commit hook, element-setup-linux.sh). Also found element-setup-macos.command was missing +x despite having a shebang and being meant for double-click execution on macOS - fixed. Added .gitignore for .DS_Store and .claude/ and stopped tracking the five .DS_Store files that had been committed by accident. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
242 lines
8.8 KiB
Markdown
242 lines
8.8 KiB
Markdown
# 🐳 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 <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):
|
|
|
|
```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`
|