- Add example secret files for `app_key`, `db_user_password`, and `redis_password`. - Introduce `local.vault.yml.example` for Ansible Vault encryption of local secrets. - Create migration and setup scripts for transitioning from `.env.local` to secrets files. - Update `docker-compose.local.yml` to adopt Docker Secrets and `_FILE` pattern for local configurations. - Add deployment playbooks and enhanced logging configurations for local development.
471 lines
13 KiB
Markdown
471 lines
13 KiB
Markdown
# 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
|