# Plan: Vereinheitlichung der lokalen Entwicklungsumgebung mit Staging/Production **Datum**: 2025-11-04 **Ziel**: Lokale Entwicklungsumgebung auf Docker Secrets und Redis-Passwort umstellen, um Konsistenz mit Staging/Production zu erreichen ## Aktuelle Situation ### Lokal (docker-compose.local.yml) - ? **Redis**: Kein Passwort (nur redis.conf) - ? **Docker Secrets**: Nicht verwendet - ? ***_FILE Pattern**: Nicht verwendet - ? **Secrets**: Direkt in `.env.local` (plain text) ### Staging/Production - ? **Redis**: Mit Passwort via Docker Secrets - ? **Docker Secrets**: Aktiviert - ? ***_FILE Pattern**: F?r alle Secrets - ? **Framework**: `DockerSecretsResolver` unterst?tzt automatisch `*_FILE` Pattern ## Vorteile der Vereinheitlichung ### 1. Konsistenz - ? **Gleiche Konfiguration** in allen Umgebungen - ? **Weniger ?berraschungen** bei Deployment - ? **Einfachere Fehlersuche** (gleiche Konfiguration = gleiche Probleme) ### 2. Framework-Support - ? **Framework unterst?tzt bereits `DockerSecretsResolver`** - ? **Automatisches Laden** von `*_FILE` Pattern - ? **Kein Code-Change n?tig** - nur Konfiguration ### 3. Sicherheit - ? **Bessere Praxis** auch in Entwicklung - ? **Secrets nicht in `.env.local`** (kann versehentlich committed werden) - ? **Dateisystem-Permissions** f?r Secrets ### 4. Entwickler-Erfahrung - ? **Testen mit Production-?hnlicher Konfiguration** - ? **Fr?hes Erkennen** von Secrets-Problemen - ? **Einheitliches Setup** f?r alle Entwickler ## Nachteile / ?berlegungen ### 1. Komplexit?t - ?? **Mehr Setup-Schritte** f?r neue Entwickler - ?? **Zus?tzliche Secrets-Dateien** m?ssen erstellt werden - ?? **Lokale Secrets-Verwaltung** n?tig ### 2. Migration - ?? **Bestehende `.env.local`** muss angepasst werden - ?? **Secrets-Verzeichnis** muss erstellt werden - ?? **Dokumentation** muss aktualisiert werden ## Implementierungsplan ### Phase 1: Secrets-Verzeichnis und Struktur #### 1.1 Secrets-Verzeichnis erstellen ```bash mkdir -p secrets chmod 700 secrets ``` #### 1.2 .gitignore aktualisieren ```gitignore # Secrets (lokal) secrets/*.txt !secrets/*.example ``` #### 1.3 Beispiel-Secrets erstellen ```bash # secrets/redis_password.txt.example # Beispiel: local-dev-redis-password-2024 # secrets/db_user_password.txt.example # Beispiel: local-dev-db-password-2024 # secrets/app_key.txt.example # Beispiel: base64:local-dev-app-key-generated ``` ### Phase 2: Docker Compose Konfiguration #### 2.1 docker-compose.local.yml aktualisieren **Redis Service:** ```yaml redis: secrets: - redis_password command: > sh -c "redis-server --requirepass $$(cat /run/secrets/redis_password) --maxmemory 256mb --maxmemory-policy allkeys-lru --save 900 1 --save 300 10 --save 60 10000 --appendonly yes --appendfsync everysec" healthcheck: test: ["CMD", "sh", "-c", "redis-cli --no-auth-warning -a $$(cat /run/secrets/redis_password) ping"] ``` **PHP Service:** ```yaml php: environment: - REDIS_PASSWORD_FILE=/run/secrets/redis_password - DB_PASSWORD_FILE=/run/secrets/db_user_password - APP_KEY_FILE=/run/secrets/app_key secrets: - redis_password - db_user_password - app_key ``` **Queue-Worker Service:** ```yaml queue-worker: environment: - REDIS_PASSWORD_FILE=/run/secrets/redis_password - DB_PASSWORD_FILE=/run/secrets/db_user_password secrets: - redis_password - db_user_password ``` #### 2.2 docker-compose.base.yml Secrets erweitern **Secrets-Sektion:** ```yaml secrets: db_user_password: file: ./secrets/db_user_password.txt external: false redis_password: file: ./secrets/redis_password.txt external: false app_key: file: ./secrets/app_key.txt external: false ``` **Hinweis**: `external: false` bedeutet, dass die Dateien lokal sein m?ssen (nicht external wie in Production). ### Phase 3: Redis-Konfiguration #### 3.1 redis.conf anpassen **Option A**: redis.conf entfernt (nur Command-Line-Args) **Option B**: redis.conf mit requirepass (aus Secret geladen) **Empfehlung**: Option A - Command-Line-Args sind flexibler und konsistenter mit Staging/Production. #### 3.2 redis.conf entfernen oder anpassen ```ini # docker/redis/redis.conf # Hinweis: Passwort wird via Command-Line-Args gesetzt (aus Docker Secret) # requirepass wird nicht hier gesetzt, sondern via --requirepass Argument ``` ### Phase 4: Migration bestehender .env.local #### 4.1 Secrets aus .env.local extrahieren ```bash # Script: scripts/migrate-env-to-secrets.sh #!/bin/bash SECRETS_DIR="./secrets" mkdir -p "$SECRETS_DIR" # Redis Password if grep -q "REDIS_PASSWORD=" .env.local; then grep "REDIS_PASSWORD=" .env.local | cut -d'=' -f2 > "$SECRETS_DIR/redis_password.txt" chmod 600 "$SECRETS_DIR/redis_password.txt" echo "? Created secrets/redis_password.txt" # Entferne aus .env.local (kommentiere aus oder entferne) sed -i '/^REDIS_PASSWORD=/d' .env.local fi # DB Password if grep -q "DB_PASSWORD=" .env.local; then grep "DB_PASSWORD=" .env.local | cut -d'=' -f2 > "$SECRETS_DIR/db_user_password.txt" chmod 600 "$SECRETS_DIR/db_user_password.txt" echo "? Created secrets/db_user_password.txt" sed -i '/^DB_PASSWORD=/d' .env.local fi # APP_KEY if grep -q "APP_KEY=" .env.local; then grep "APP_KEY=" .env.local | cut -d'=' -f2 > "$SECRETS_DIR/app_key.txt" chmod 600 "$SECRETS_DIR/app_key.txt" echo "? Created secrets/app_key.txt" sed -i '/^APP_KEY=/d' .env.local fi echo "? Migration completed. Please review .env.local and remove migrated secrets." ``` #### 4.2 .env.local bereinigen - Entferne: `REDIS_PASSWORD=`, `DB_PASSWORD=`, `APP_KEY=` - Behalte: Alle anderen Konfigurationen (DB_HOST, DB_PORT, etc.) ### Phase 5: Dokumentation #### 5.1 ENV_SETUP.md aktualisieren - Lokales Setup mit Secrets dokumentieren - Migration-Anleitung hinzuf?gen - Beispiel-Secrets erw?hnen #### 5.2 README.md aktualisieren - Setup-Schritte f?r neue Entwickler - Secrets-Verzeichnis erstellen - Beispiel-Secrets kopieren #### 5.3 .env.example aktualisieren - Kommentare zu `*_FILE` Pattern hinzuf?gen - Hinweis auf Secrets-Verzeichnis ## Detaillierte ?nderungen ### Datei: docker-compose.local.yml ```yaml services: php: environment: # Use Docker Secrets via *_FILE pattern (Framework supports this automatically) - DB_PASSWORD_FILE=/run/secrets/db_user_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password - APP_KEY_FILE=/run/secrets/app_key secrets: - db_user_password - redis_password - app_key redis: secrets: - redis_password command: > sh -c "redis-server --requirepass $$(cat /run/secrets/redis_password) --maxmemory 256mb --maxmemory-policy allkeys-lru --save 900 1 --save 300 10 --save 60 10000 --appendonly yes --appendfsync everysec" healthcheck: test: ["CMD", "sh", "-c", "redis-cli --no-auth-warning -a $$(cat /run/secrets/redis_password) ping"] interval: 30s timeout: 5s retries: 3 start_period: 10s queue-worker: environment: - DB_PASSWORD_FILE=/run/secrets/db_user_password - REDIS_PASSWORD_FILE=/run/secrets/redis_password secrets: - db_user_password - redis_password secrets: db_user_password: file: ./secrets/db_user_password.txt external: false redis_password: file: ./secrets/redis_password.txt external: false app_key: file: ./secrets/app_key.txt external: false ``` ### Datei: docker-compose.base.yml **Secrets-Sektion bereits vorhanden** (Zeilen 192-224), muss nur genutzt werden. ### Datei: docker/redis/redis.conf **Anpassen oder entfernen:** ```ini # docker/redis/redis.conf # Hinweis: Passwort wird via Docker Secrets geladen # requirepass wird nicht hier gesetzt, sondern via Command-Line-Args # In docker-compose.local.yml wird --requirepass verwendet ``` ## Migration f?r bestehende Entwickler ### Schritt-f?r-Schritt Anleitung ```bash # 1. Secrets-Verzeichnis erstellen mkdir -p secrets chmod 700 secrets # 2. Secrets aus .env.local extrahieren # Redis Password REDIS_PASS=$(grep "^REDIS_PASSWORD=" .env.local | cut -d'=' -f2) if [ -n "$REDIS_PASS" ]; then echo "$REDIS_PASS" > secrets/redis_password.txt chmod 600 secrets/redis_password.txt echo "? Created secrets/redis_password.txt" fi # DB Password DB_PASS=$(grep "^DB_PASSWORD=" .env.local | cut -d'=' -f2) if [ -n "$DB_PASS" ]; then echo "$DB_PASS" > secrets/db_user_password.txt chmod 600 secrets/db_user_password.txt echo "? Created secrets/db_user_password.txt" fi # APP_KEY APP_KEY=$(grep "^APP_KEY=" .env.local | cut -d'=' -f2) if [ -n "$APP_KEY" ]; then echo "$APP_KEY" > secrets/app_key.txt chmod 600 secrets/app_key.txt echo "? Created secrets/app_key.txt" fi # 3. Entferne Secrets aus .env.local (oder kommentiere aus) sed -i '/^REDIS_PASSWORD=/d' .env.local sed -i '/^DB_PASSWORD=/d' .env.local sed -i '/^APP_KEY=/d' .env.local # 4. Pr?fe Secrets ls -la secrets/ # Sollte zeigen: redis_password.txt, db_user_password.txt, app_key.txt # 5. Teste Konfiguration docker compose -f docker-compose.base.yml -f docker-compose.local.yml config # 6. Starte Container docker compose -f docker-compose.base.yml -f docker-compose.local.yml up -d # 7. Teste Redis-Verbindung docker compose exec redis redis-cli --no-auth-warning -a $(cat secrets/redis_password.txt) ping # Erwartet: PONG ``` ## Setup f?r neue Entwickler ### Initial Setup Script ```bash #!/bin/bash # scripts/setup-local-secrets.sh echo "?? Setting up local development secrets..." SECRETS_DIR="./secrets" mkdir -p "$SECRETS_DIR" chmod 700 "$SECRETS_DIR" # Generate Redis Password if [ ! -f "$SECRETS_DIR/redis_password.txt" ]; then REDIS_PASS=$(openssl rand -base64 32) echo "$REDIS_PASS" > "$SECRETS_DIR/redis_password.txt" chmod 600 "$SECRETS_DIR/redis_password.txt" echo "? Generated secrets/redis_password.txt" fi # Generate DB Password if [ ! -f "$SECRETS_DIR/db_user_password.txt" ]; then DB_PASS=$(openssl rand -base64 32) echo "$DB_PASS" > "$SECRETS_DIR/db_user_password.txt" chmod 600 "$SECRETS_DIR/db_user_password.txt" echo "? Generated secrets/db_user_password.txt" echo "?? Update DB_PASSWORD in .env.local if needed" fi # Generate APP_KEY (if not exists) if [ ! -f "$SECRETS_DIR/app_key.txt" ]; then APP_KEY=$(php -r "echo 'base64:' . base64_encode(random_bytes(32));") echo "$APP_KEY" > "$SECRETS_DIR/app_key.txt" chmod 600 "$SECRETS_DIR/app_key.txt" echo "? Generated secrets/app_key.txt" fi echo "? Local secrets setup completed!" echo "" echo "?? Next steps:" echo "1. Review secrets/*.txt files" echo "2. Update .env.local if needed (DB_USERNAME, DB_HOST, etc.)" echo "3. Start containers: docker compose -f docker-compose.base.yml -f docker-compose.local.yml up -d" ``` ## Vorteile dieser L?sung ### 1. Konsistenz - ? Gleiche Konfiguration in Local, Staging, Production - ? Framework nutzt `DockerSecretsResolver` ?berall - ? Keine Environment-spezifischen Code-Pfade ### 2. Sicherheit - ? Secrets nicht in `.env.local` (kann versehentlich committed werden) - ? Dateisystem-Permissions (600) f?r Secrets - ? `.gitignore` verhindert versehentliches Committen ### 3. Wartbarkeit - ? Einheitliche Konfiguration - ? Framework unterst?tzt `*_FILE` Pattern automatisch - ? Klare Trennung: Secrets vs. Konfiguration ### 4. Entwickler-Erfahrung - ? Testen mit Production-?hnlicher Konfiguration - ? Fr?hes Erkennen von Secrets-Problemen - ? Setup-Script f?r neue Entwickler ## Nachteile / ?berlegungen ### 1. Komplexit?t - ?? **Mehr Setup-Schritte** f?r neue Entwickler - ?? **Zus?tzliche Secrets-Dateien** m?ssen verwaltet werden - ?? **Lokale Secrets-Verwaltung** n?tig **L?sung**: Setup-Script automatisiert die Erstellung ### 2. Migration - ?? **Bestehende `.env.local`** muss angepasst werden - ?? **Secrets-Verzeichnis** muss erstellt werden - ?? **Dokumentation** muss aktualisiert werden **L?sung**: Migration-Script unterst?tzt den ?bergang ### 3. Redis-Passwort lokal - ?? **Mehr Konfiguration** f?r lokale Entwicklung - ?? **Passwort muss bekannt sein** f?r Redis-CLI-Zugriff **L?sung**: - Passwort in `secrets/redis_password.txt` (leicht zug?nglich lokal) - Helper-Script: `scripts/redis-cli.sh` f?r einfachen Zugriff ## Alternative Ans?tze ### Option A: Secrets optional machen (nicht empfohlen) - Redis-Passwort nur wenn Secret vorhanden - Komplexer, weniger konsistent ### Option B: Nur Production/Staging mit Secrets (aktuell) - Lokal bleibt ohne Secrets - **Nachteil**: Inkonsistenz zwischen Umgebungen ### Option C: Vereinheitlichung (empfohlen) - Alle Umgebungen nutzen Secrets - **Vorteil**: Maximale Konsistenz ## Empfehlung **Vereinheitlichung (Option C)** ist die beste L?sung, weil: 1. ? **Maximale Konsistenz** zwischen allen Umgebungen 2. ? **Framework unterst?tzt bereits** `DockerSecretsResolver` 3. ? **Bessere Sicherheit** auch lokal 4. ? **Fr?hes Erkennen** von Secrets-Problemen 5. ? **Setup-Script** macht Migration einfach ## N?chste Schritte 1. ? Plan erstellt 2. ? Diskussion: Ist Vereinheitlichung gew?nscht? 3. ? Implementierung: docker-compose.local.yml anpassen 4. ? Migration: Secrets aus .env.local extrahieren 5. ? Dokumentation: ENV_SETUP.md und README.md aktualisieren 6. ? Testing: Lokale Entwicklungsumgebung testen 7. ? Setup-Script: scripts/setup-local-secrets.sh erstellen