Files
michaelschiemer/docs/deployment/ENV_SETUP.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

8.4 KiB

Environment Configuration Guide

📁 .env File Structure (Base + Override Pattern)

Die neue Struktur verwendet ein Base + Override Pattern (analog zu docker-compose):

├── .env.example            # Template für neue Entwickler (vollständige Dokumentation)
├── .env.base               # Gemeinsame Variablen für alle Environments (versioniert)
├── .env.local              # Lokale Development-Overrides (gitignored)
├── .env.staging            # Staging-spezifische Overrides (optional, gitignored)
└── .env.production         # Production (generiert durch Ansible, nicht im Repo)

🏗️ Development Setup

Initial Setup

# 1. .env.base ist bereits im Repository (gemeinsame Variablen)
# 2. Erstelle .env.local für lokale Overrides
cp .env.example .env.local

# 3. Passe .env.local an deine lokale Entwicklung an
# - DB Credentials (lokal)
# - API Keys (lokal)
# - Debug-Flags

Framework lädt automatisch: .env.base.env.local (Overrides)

Priorität:

  1. System Environment Variables (Docker ENV)
  2. .env.base (gemeinsame Basis)
  3. .env.local (lokale Overrides)
  4. .env.secrets (verschlüsselte Secrets, optional)

Wichtig: env_file in Docker Compose ist nicht nötig!

  • Framework lädt automatisch .env.base.env.local via EncryptedEnvLoader
  • Docker Compose env_file ist optional und wird nur für Container-interne Variablen benötigt
  • PHP-Anwendung lädt ENV-Variablen direkt aus den Dateien

Backward Compatibility:

  • Falls .env.base oder .env.local nicht existieren, wird .env geladen (Fallback)
  • Migration: Bestehende .env Files funktionieren weiterhin

🚀 Production Deployment

Production .env Management

WICHTIG: Production .env wird NICHT aus dem Repository deployed!

Single Source of Truth

Server: /home/deploy/michaelschiemer/shared/.env.production

Dieser File wird von Ansible automatisch erstellt aus:

deployment/infrastructure/templates/.env.production.j2

Production Deployment Process

# Ansible Playbook erstellt automatisch die Production .env
cd deployment/infrastructure
ansible-playbook -i inventories/production/hosts.yml \
    playbooks/deploy-rsync-based.yml \
    --vault-password-file .vault_pass

Ansible macht dabei:

  1. Template .env.production.j2 rendern
  2. Vault-verschlüsselte Secrets einsetzen
  3. File nach /home/deploy/michaelschiemer/shared/.env.production deployen
  4. Docker Compose mounted diesen File in Container

🔒 Security & Secret Management

Docker Secrets (Production & Staging)

Production und Staging verwenden Docker Secrets:

  1. Ansible Vault → Docker Secrets Dateien

    • Ansible Playbook erstellt Secret-Dateien in secrets/ Verzeichnis
    • Dateien haben sichere Permissions (0600)
  2. Docker Compose Secrets

    • Secrets werden in docker-compose.base.yml definiert
    • Environment-Variablen nutzen *_FILE Pattern (z.B. DB_PASSWORD_FILE=/run/secrets/db_user_password)
    • Framework lädt automatisch via DockerSecretsResolver
  3. Framework Support

    • DockerSecretsResolver unterstützt automatisch *_FILE Pattern
    • Kein manuelles Secret-Loading mehr nötig (wird automatisch vom Framework behandelt)

Development

# .env.local niemals committen
git status
# Should show: .env.local (untracked) ✅

# .env.base ist versioniert (keine Secrets!)
# Falls versehentlich staged:
git reset HEAD .env.local

Production

  • Secrets in Ansible Vault
  • Ansible erstellt Docker Secrets Dateien (secrets/*.txt)
  • Docker Compose Secrets aktiviert
  • Framework lädt automatisch via *_FILE Pattern
  • .env.production auf Server wird NICHT ins Repository committed
  • Template application.env.j2 verwendet *_FILE Pattern

📝 Adding New Environment Variables

Development

# 1. Add to .env.base if shared across environments
echo "NEW_API_KEY=" >> .env.base

# 2. Add to .env.local for local development
echo "NEW_API_KEY=abc123..." >> .env.local

# 3. Update .env.example for documentation
echo "NEW_API_KEY=your_api_key_here" >> .env.example

Hinweis: Wenn die Variable nur für lokale Entwicklung ist, nur in .env.local hinzufügen.

Production (mit Docker Secrets)

# 1. Add to Ansible Template (use *_FILE pattern for secrets)
# File: deployment/ansible/templates/application.env.j2
echo "# Use Docker Secrets via *_FILE pattern" >> application.env.j2
echo "NEW_API_KEY_FILE=/run/secrets/new_api_key" >> application.env.j2

# 2. Add to docker-compose.base.yml secrets section
# File: docker-compose.base.yml
# secrets:
#   new_api_key:
#     file: ./secrets/new_api_key.txt

# 3. Add secret to Ansible Vault
ansible-vault edit deployment/ansible/secrets/production.vault.yml
# Add: vault_new_api_key: "production_value"

# 4. Update setup-production-secrets.yml to create secret file
# File: deployment/ansible/playbooks/setup-production-secrets.yml
# Add to loop:
#   - name: new_api_key
#     value: "{{ vault_new_api_key }}"

# 5. Deploy
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
    playbooks/setup-production-secrets.yml \
    --vault-password-file .vault_pass

Production (ohne Docker Secrets, fallback)

Falls Docker Secrets nicht verwendet werden sollen:

# 1. Add to Ansible Template
# File: deployment/ansible/templates/application.env.j2
echo "NEW_API_KEY={{ vault_new_api_key }}" >> application.env.j2

# 2. Add secret to Ansible Vault
ansible-vault edit deployment/ansible/secrets/production.vault.yml
# Add: vault_new_api_key: "production_value"

# 3. Deploy
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
    playbooks/deploy-update.yml

🗑️ Removed Files (Consolidation 27.10.2024)

Diese Files wurden gelöscht, da sie redundant/nicht verwendet wurden:

❌ .env.production              (Root - redundant)
❌ .env.production.example      (Root - nicht verwendet)
❌ .env.backup.20250912_133135  (Altes Backup)
❌ .env.analytics.example       (In .env.example integriert)
❌ .env.secrets.example         (In .env.example integriert)
❌ deployment/applications/environments/  (Gesamtes Directory gelöscht)

Current State

Local Development

  • Base File: .env.base (versioniert, gemeinsame Variablen)
  • Override File: .env.local (gitignored, lokale Anpassungen)
  • Template: .env.example (Dokumentation)
  • Framework lädt automatisch: .env.base.env.local (Overrides)

Production

  • Single Source: /home/deploy/michaelschiemer/shared/.env.production (auf Server)
  • Verwaltet durch: Ansible Template application.env.j2
  • Secrets: Docker Secrets (secrets/*.txt Dateien)
  • Framework lädt automatisch via *_FILE Pattern (DockerSecretsResolver)
  • Keine Duplikate

Staging

  • Docker Compose Environment Variables
  • Docker Secrets aktiviert (wie Production)
  • Optional: .env.staging für Staging-spezifische Overrides

🔍 Verification

# Check local .env files
ls -la .env*
# Should show: .env.base (versioniert), .env.local (gitignored), .env.example

# Check Ansible template exists
ls -la deployment/ansible/templates/application.env.j2
# Should exist

# Check Docker Secrets files exist (on server)
ls -la {{ app_stack_path }}/secrets/
# Should show: db_user_password.txt, redis_password.txt, app_key.txt, etc.

# Check NO old files remain
find . -name ".env.production" -o -name ".env.*.example" | grep -v .env.example | grep -v .env.base
# Should be empty

📞 Support

Bei Fragen zum .env Setup:

  • Development: Siehe .env.base (gemeinsame Variablen) und .env.example (Dokumentation)
  • Production: Siehe deployment/ansible/templates/application.env.j2
  • Secrets: Docker Secrets aktiviert, verwaltet durch Ansible Vault
  • Migration: Framework unterstützt Fallback auf .env (alte Struktur)

🔄 Migration von alter Struktur

Von .env zu .env.base + .env.local:

# 1. Erstelle .env.base (gemeinsame Variablen extrahieren)
#    (wird automatisch vom Framework erkannt)

# 2. Erstelle .env.local (nur lokale Overrides)
cp .env .env.local

# 3. Entferne gemeinsame Variablen aus .env.local
#    (nur lokale Anpassungen behalten)

# 4. Alte .env kann später entfernt werden
#    (nach erfolgreicher Migration)

Hinweis: Framework lädt automatisch .env.base + .env.local. Falls diese nicht existieren, wird .env als Fallback geladen (Backward Compatibility).