- Update Ansible playbooks and roles for application deployment - Add new Gitea/Traefik troubleshooting playbooks - Update Docker Compose configurations (base, local, staging, production) - Enhance EncryptedEnvLoader with improved error handling - Add deployment scripts (autossh setup, migration, secret testing) - Update CI/CD workflows and documentation - Add Semaphore stack configuration
408 lines
13 KiB
Markdown
408 lines
13 KiB
Markdown
# Production Environment Configuration Template
|
|
|
|
Production-optimierte `.env` Konfiguration für das Custom PHP Framework.
|
|
|
|
## `.env.production` Template
|
|
|
|
```env
|
|
# ============================================================================
|
|
# PRODUCTION ENVIRONMENT CONFIGURATION
|
|
# ============================================================================
|
|
# SECURITY: Never commit this file to version control!
|
|
# SECURITY: Store sensitive values in Vault, reference here only
|
|
# ============================================================================
|
|
|
|
# ============================================================================
|
|
# APPLICATION CONFIGURATION
|
|
# ============================================================================
|
|
COMPOSE_PROJECT_NAME=michaelschiemer-prod
|
|
APP_ENV=production
|
|
APP_DEBUG=false
|
|
APP_URL=https://your-domain.com
|
|
|
|
# Application Port (behind reverse proxy/load balancer)
|
|
APP_PORT=80
|
|
|
|
# PHP Version
|
|
PHP_VERSION=8.4
|
|
|
|
# ============================================================================
|
|
# DATABASE CONFIGURATION (PostgreSQL)
|
|
# ============================================================================
|
|
# SECURITY: Use strong passwords (minimum 32 characters)
|
|
# Generate with: openssl rand -base64 32
|
|
DB_DRIVER=pgsql
|
|
DB_HOST=db
|
|
DB_PORT=5432
|
|
DB_DATABASE=michaelschiemer_prod
|
|
DB_USERNAME=postgres
|
|
DB_PASSWORD=CHANGE_ME_STRONG_PASSWORD_32_CHARS_MIN
|
|
DB_CHARSET=utf8
|
|
DB_SCHEMA=public
|
|
|
|
# Connection Pooling (Production Optimized)
|
|
DB_POOL_MIN=5
|
|
DB_POOL_MAX=20
|
|
|
|
# ============================================================================
|
|
# REDIS CONFIGURATION
|
|
# ============================================================================
|
|
# SECURITY: Enable Redis password authentication in production
|
|
REDIS_SCHEME=tcp
|
|
REDIS_HOST=redis
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=CHANGE_ME_STRONG_REDIS_PASSWORD
|
|
|
|
# ============================================================================
|
|
# RATE LIMITING CONFIGURATION
|
|
# ============================================================================
|
|
# Production values - stricter than development
|
|
RATE_LIMIT_DEFAULT=30
|
|
RATE_LIMIT_WINDOW=60
|
|
RATE_LIMIT_AUTH=5
|
|
RATE_LIMIT_AUTH_WINDOW=300
|
|
RATE_LIMIT_API=20
|
|
RATE_LIMIT_API_WINDOW=60
|
|
|
|
# ============================================================================
|
|
# SECURITY CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Vault Configuration
|
|
# Generate with: php console.php vault:generate-key
|
|
# CRITICAL: Store this key securely, losing it means losing all encrypted data
|
|
VAULT_ENCRYPTION_KEY=CHANGE_ME_GENERATE_WITH_CONSOLE_COMMAND
|
|
|
|
# Admin IP Whitelist (comma-separated)
|
|
# SECURITY: Restrict admin access to known IPs only
|
|
ADMIN_ALLOWED_IPS=203.0.113.42,198.51.100.10
|
|
|
|
# CSRF Token Configuration
|
|
CSRF_TOKEN_LIFETIME=3600
|
|
|
|
# Session Configuration
|
|
SESSION_LIFETIME=3600
|
|
SESSION_SECURE_COOKIE=true
|
|
SESSION_HTTP_ONLY=true
|
|
SESSION_SAME_SITE=strict
|
|
|
|
# ============================================================================
|
|
# SSL/TLS CONFIGURATION
|
|
# ============================================================================
|
|
# Let's Encrypt / Certbot Configuration
|
|
SSL_ENABLED=true
|
|
SSL_DOMAIN=your-domain.com
|
|
SSL_EMAIL=admin@your-domain.com
|
|
SSL_MODE=production
|
|
# CERTBOT_STAGING=false # Set to true for testing
|
|
CERTBOT_CONF_DIR=/etc/letsencrypt
|
|
CERTBOT_WEBROOT=/var/www/certbot
|
|
CERTBOT_LOGS_DIR=/var/log/letsencrypt
|
|
|
|
# ============================================================================
|
|
# MONITORING & LOGGING CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Logging Level (emergency, alert, critical, error, warning, notice, info, debug)
|
|
LOG_LEVEL=warning
|
|
|
|
# Performance Monitoring
|
|
PERFORMANCE_MONITORING_ENABLED=true
|
|
PERFORMANCE_THRESHOLD_MS=500
|
|
|
|
# Error Reporting
|
|
ERROR_REPORTING_ENABLED=true
|
|
ERROR_AGGREGATION_ENABLED=true
|
|
|
|
# N+1 Detection (Disable ML in production for performance)
|
|
NPLUSONE_ML_ENABLED=false
|
|
NPLUSONE_ML_TIMEOUT_MS=5000
|
|
NPLUSONE_ML_CONFIDENCE_THRESHOLD=70.0
|
|
|
|
# Health Check Endpoint
|
|
HEALTH_CHECK_ENABLED=true
|
|
HEALTH_CHECK_PATH=/health
|
|
|
|
# ============================================================================
|
|
# EXTERNAL API CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# RapidMail API
|
|
# SECURITY: Store credentials in Vault, reference here
|
|
RAPIDMAIL_USERNAME=CHANGE_ME_YOUR_RAPIDMAIL_USERNAME
|
|
RAPIDMAIL_PASSWORD=CHANGE_ME_YOUR_RAPIDMAIL_PASSWORD
|
|
RAPIDMAIL_DEFAULT_LIST_ID=CHANGE_ME_YOUR_LIST_ID
|
|
|
|
# Shopify API
|
|
# SECURITY: Store access token in Vault
|
|
SHOPIFY_SHOP_DOMAIN=yourstore.myshopify.com
|
|
SHOPIFY_ACCESS_TOKEN=CHANGE_ME_SHOPIFY_ACCESS_TOKEN
|
|
SHOPIFY_API_VERSION=2024-04
|
|
|
|
# ============================================================================
|
|
# OAUTH PROVIDER CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Spotify OAuth
|
|
SPOTIFY_CLIENT_ID=CHANGE_ME_SPOTIFY_CLIENT_ID
|
|
SPOTIFY_CLIENT_SECRET=CHANGE_ME_SPOTIFY_CLIENT_SECRET
|
|
SPOTIFY_REDIRECT_URI=https://your-domain.com/oauth/spotify/callback
|
|
|
|
# Apple Music OAuth
|
|
APPLE_MUSIC_CLIENT_ID=CHANGE_ME_APPLE_MUSIC_CLIENT_ID
|
|
APPLE_MUSIC_TEAM_ID=CHANGE_ME_APPLE_MUSIC_TEAM_ID
|
|
APPLE_MUSIC_KEY_ID=CHANGE_ME_APPLE_MUSIC_KEY_ID
|
|
APPLE_MUSIC_PRIVATE_KEY=/path/to/apple_music_private_key.p8
|
|
APPLE_MUSIC_REDIRECT_URI=https://your-domain.com/oauth/apple-music/callback
|
|
|
|
# Tidal OAuth
|
|
TIDAL_CLIENT_ID=CHANGE_ME_TIDAL_CLIENT_ID
|
|
TIDAL_CLIENT_SECRET=CHANGE_ME_TIDAL_CLIENT_SECRET
|
|
TIDAL_REDIRECT_URI=https://your-domain.com/oauth/tidal/callback
|
|
|
|
# ============================================================================
|
|
# FILESYSTEM & CACHING CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Filesystem Performance (leave caching enabled in production)
|
|
FILESYSTEM_DISABLE_CACHE=false
|
|
|
|
# OPcache Configuration (handled via php.production.ini)
|
|
# See: docker/php/php.production.ini
|
|
|
|
# ============================================================================
|
|
# BACKUP CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Database Backup Configuration
|
|
BACKUP_ENABLED=true
|
|
BACKUP_SCHEDULE=0 2 * * * # Daily at 2 AM
|
|
BACKUP_RETENTION_DAYS=30
|
|
BACKUP_ENCRYPTION_ENABLED=true
|
|
BACKUP_STORAGE_PATH=/backups
|
|
|
|
# ============================================================================
|
|
# DEPLOYMENT CONFIGURATION
|
|
# ============================================================================
|
|
|
|
# Zero-Downtime Deployment
|
|
DEPLOYMENT_MODE=rolling
|
|
DEPLOYMENT_HEALTH_CHECK_TIMEOUT=60
|
|
DEPLOYMENT_MAX_RETRIES=3
|
|
|
|
# Container Resource Limits (set in docker-compose.production.yml)
|
|
# PHP_MEMORY_LIMIT=512M
|
|
# PHP_MAX_EXECUTION_TIME=30
|
|
# NGINX_WORKER_PROCESSES=auto
|
|
# NGINX_WORKER_CONNECTIONS=2048
|
|
|
|
# ============================================================================
|
|
# OPTIONAL FEATURES
|
|
# ============================================================================
|
|
|
|
# Feature Flags
|
|
FEATURE_GRAPHQL_ENABLED=true
|
|
FEATURE_ASYNC_PROCESSING_ENABLED=true
|
|
FEATURE_LIVE_COMPONENTS_ENABLED=true
|
|
|
|
# Queue Configuration
|
|
QUEUE_DRIVER=redis
|
|
QUEUE_CONNECTION=default
|
|
QUEUE_RETRY_AFTER=90
|
|
|
|
# Scheduler Configuration
|
|
SCHEDULER_ENABLED=true
|
|
SCHEDULER_TIMEZONE=Europe/Berlin
|
|
|
|
# ============================================================================
|
|
# ENVIRONMENT-SPECIFIC OVERRIDES
|
|
# ============================================================================
|
|
|
|
# Staging Environment (if needed)
|
|
# Copy this file to .env.staging and adjust values:
|
|
# - APP_ENV=staging
|
|
# - APP_DEBUG=false
|
|
# - SSL_MODE=staging (Let's Encrypt staging)
|
|
# - Less restrictive rate limits
|
|
# - Test database/Redis instances
|
|
|
|
```
|
|
|
|
## Security Checklist
|
|
|
|
### Before Deployment
|
|
|
|
- [ ] Replace ALL `CHANGE_ME_*` placeholders with actual values
|
|
- [ ] Generate VAULT_ENCRYPTION_KEY: `php console.php vault:generate-key`
|
|
- [ ] Generate strong database password (32+ characters)
|
|
- [ ] Generate strong Redis password
|
|
- [ ] Configure ADMIN_ALLOWED_IPS with production IPs
|
|
- [ ] Verify SSL_DOMAIN matches DNS configuration
|
|
- [ ] Verify SSL_EMAIL is valid for Let's Encrypt notifications
|
|
- [ ] Store sensitive credentials in Vault (not in .env file)
|
|
- [ ] Set APP_DEBUG=false (CRITICAL: Never enable debug in production)
|
|
- [ ] Set SESSION_SECURE_COOKIE=true
|
|
- [ ] Verify all OAuth redirect URIs match production domain
|
|
|
|
### After Deployment
|
|
|
|
- [ ] Verify .env.production is not committed to version control
|
|
- [ ] Set file permissions: `chmod 600 .env.production`
|
|
- [ ] Verify environment variables loaded: `php console.php env:check`
|
|
- [ ] Test Vault encryption: `php console.php vault:test`
|
|
- [ ] Initialize SSL certificates: `php console.php ssl:init`
|
|
- [ ] Verify SSL certificate status: `php console.php ssl:status`
|
|
- [ ] Test health check endpoint: `curl https://your-domain.com/health`
|
|
- [ ] Monitor logs for errors: `docker-compose logs -f --tail=100`
|
|
|
|
## Secrets Management Strategy
|
|
|
|
**CRITICAL**: Do NOT store sensitive values in `.env.production` directly.
|
|
|
|
### Recommended Approach
|
|
|
|
1. **Use Vault for Sensitive Data**:
|
|
```bash
|
|
# Store sensitive values in Vault
|
|
php console.php vault:store rapidmail_password "actual_password_here"
|
|
php console.php vault:store shopify_access_token "actual_token_here"
|
|
|
|
# Reference in application code
|
|
$password = $vault->get('rapidmail_password');
|
|
```
|
|
|
|
2. **Environment-Specific Vaults**:
|
|
- Production Vault (encrypted with VAULT_ENCRYPTION_KEY)
|
|
- Staging Vault (different encryption key)
|
|
- Development Vault (different encryption key)
|
|
|
|
3. **Key Rotation Schedule**:
|
|
- Vault encryption key: Rotate quarterly
|
|
- Database passwords: Rotate semi-annually
|
|
- API tokens: Rotate when provider recommends
|
|
- SSL certificates: Auto-renewed by Certbot
|
|
|
|
## Configuration Validation
|
|
|
|
```bash
|
|
# Validate production configuration
|
|
php console.php config:validate --env=production
|
|
|
|
# Check for missing required values
|
|
php console.php config:check --strict
|
|
|
|
# Test database connection
|
|
php console.php db:test-connection
|
|
|
|
# Test Redis connection
|
|
php console.php redis:test-connection
|
|
|
|
# Verify SSL configuration
|
|
php console.php ssl:test
|
|
```
|
|
|
|
## Environment File Hierarchy
|
|
|
|
**New Base + Override Pattern (Development):**
|
|
```
|
|
.env.example # Template with placeholders (documentation)
|
|
.env.base # Shared variables for all environments (versioned)
|
|
.env.local # Local development overrides (gitignored)
|
|
.env.staging # Staging-specific overrides (optional, gitignored)
|
|
.env.production # Production (generated by Ansible - this template)
|
|
```
|
|
|
|
**Production Load Priority**: Docker ENV vars → `.env.production` (generated by Ansible) → Environment Variables → Defaults
|
|
|
|
**Development Load Priority**: `.env.base` → `.env.local` → System ENV vars
|
|
|
|
**Note**: Framework automatically loads `.env.base` + `.env.local` in development. For production, Ansible generates `.env.production` with `*_FILE` pattern for Docker Secrets.
|
|
|
|
## Docker Compose Integration
|
|
|
|
Production environment is loaded via docker-compose:
|
|
|
|
```bash
|
|
# Load production environment
|
|
docker-compose -f docker-compose.yml -f docker-compose.production.yml --env-file .env.production up -d
|
|
|
|
# Verify environment loaded correctly
|
|
docker-compose -f docker-compose.yml -f docker-compose.production.yml --env-file .env.production config
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Problem: Environment variables not loaded
|
|
|
|
```bash
|
|
# Check if .env.production exists
|
|
ls -la .env.production
|
|
|
|
# Verify file permissions
|
|
chmod 600 .env.production
|
|
|
|
# Check Docker Compose loads it
|
|
docker-compose --env-file .env.production config | grep APP_ENV
|
|
```
|
|
|
|
### Problem: Vault encryption key lost
|
|
|
|
**WARNING**: If VAULT_ENCRYPTION_KEY is lost, all encrypted data is UNRECOVERABLE.
|
|
|
|
**Prevention**:
|
|
- Store key in secure password manager
|
|
- Backup key to encrypted offline storage
|
|
- Document key rotation procedure
|
|
|
|
**Recovery**:
|
|
- Restore from encrypted backup (if available)
|
|
- Regenerate key and re-encrypt all data
|
|
- Update all services with new key
|
|
|
|
### Problem: SSL certificate initialization fails
|
|
|
|
```bash
|
|
# Test configuration
|
|
php console.php ssl:test
|
|
|
|
# Check DNS configuration
|
|
dig +short your-domain.com
|
|
|
|
# Verify ports 80/443 open
|
|
netstat -tuln | grep -E ':(80|443)'
|
|
|
|
# Check Certbot logs
|
|
docker-compose logs certbot
|
|
tail -f /var/log/letsencrypt/letsencrypt.log
|
|
```
|
|
|
|
## Production Deployment Command
|
|
|
|
```bash
|
|
# Complete production deployment
|
|
./scripts/deploy-production.sh
|
|
|
|
# Or manual deployment
|
|
docker-compose -f docker-compose.yml \
|
|
-f docker-compose.production.yml \
|
|
--env-file .env.production \
|
|
up -d --build
|
|
|
|
# Wait for health checks
|
|
./scripts/wait-for-health.sh
|
|
|
|
# Run database migrations
|
|
docker exec php php console.php db:migrate --env=production
|
|
|
|
# Verify deployment
|
|
curl -f https://your-domain.com/health || exit 1
|
|
```
|
|
|
|
## See Also
|
|
|
|
- **Prerequisites**: `docs/deployment/production-prerequisites.md`
|
|
- **SSL Setup**: `docs/deployment/ssl-setup.md`
|
|
- **Database Migrations**: `docs/deployment/database-migrations.md` (TODO)
|
|
- **Monitoring**: `docs/deployment/monitoring.md` (TODO)
|
|
- **Rollback Guide**: `docs/deployment/rollback-guide.md` (TODO)
|