# SSL/TLS Deployment Guide Vollständige Anleitung für Let's Encrypt SSL/TLS Setup im Custom PHP Framework. ## Übersicht Das Framework nutzt **Let's Encrypt** mit einem **Certbot Sidecar Container** für automatische SSL-Zertifikatsverwaltung. **Architektur**: ``` ┌─────────────────────────────────────────────────────────┐ │ Nginx Container (macbre/nginx-http3) │ │ • HTTP/3 & QUIC Support │ │ • TLS 1.3 & TLS 1.2 │ │ • Security Headers │ │ • Shared Volume: /etc/letsencrypt (read-only) │ └──────────────────┬──────────────────────────────────────┘ │ │ Shared Volumes ↓ ┌─────────────────────────────────────────────────────────┐ │ Certbot Sidecar Container (certbot/certbot) │ │ • Auto-renewal every 12h │ │ • HTTP-01 Challenge via webroot │ │ • Shared Volume: /etc/letsencrypt (read-write) │ └─────────────────────────────────────────────────────────┘ ``` ## Voraussetzungen 1. **Domain konfiguriert**: DNS A-Record zeigt auf Server-IP 2. **Firewall**: Port 80 und 443 offen 3. **Docker & Docker Compose** installiert 4. **Production Environment** konfiguriert ## Initial Setup ### 1. Environment Configuration ```bash # Kopiere Production Template cp .env.production.example .env.production # Bearbeite .env.production nano .env.production ``` **Wichtige Variablen**: ```bash DOMAIN_NAME=michaelschiemer.de SSL_EMAIL=mail@michaelschiemer.de LETSENCRYPT_ENABLED=true APP_ENV=production APP_DEBUG=false ``` ### 2. SSL Zertifikat Initial Holen ```bash # Führe SSL Initialization Script aus ./scripts/ssl-init.sh # Mit Custom Domain und Email ./scripts/ssl-init.sh yourdomain.com admin@yourdomain.com # Testing Mode (Staging Certificates - empfohlen für ersten Test) LETSENCRYPT_STAGING=1 ./scripts/ssl-init.sh ``` **Das Script macht**: 1. Startet Nginx Container 2. Erstellt ACME Challenge Verzeichnis 3. Holt Let's Encrypt Zertifikat via HTTP-01 4. Speichert Zertifikate in Docker Volume 5. Startet Nginx mit SSL neu ### 3. Production Stack Starten ```bash # Starte kompletten Production Stack docker-compose -f docker-compose.yml -f docker-compose.production.yml up -d # Check Logs docker-compose -f docker-compose.yml -f docker-compose.production.yml logs -f web certbot ``` ## SSL Testing & Validation ### Lokaler Test ```bash # Führe SSL Test Script aus ./scripts/ssl-test.sh # Mit Custom Domain ./scripts/ssl-test.sh yourdomain.com ``` **Test Prüft**: - ✅ Port 443 Erreichbarkeit - ✅ Zertifikatsgültigkeit - ✅ Let's Encrypt Issuer - ✅ TLS 1.3 & TLS 1.2 Support - ✅ HTTP → HTTPS Redirect - ✅ HSTS Header - ✅ Security Headers ### Online SSL Tests **SSL Labs** (A+ Rating anstreben): ``` https://www.ssllabs.com/ssltest/analyze.html?d=michaelschiemer.de ``` **Mozilla Observatory**: ``` https://observatory.mozilla.org/analyze/michaelschiemer.de ``` **Security Headers**: ``` https://securityheaders.com/?q=michaelschiemer.de ``` ## Auto-Renewal ### Certbot Sidecar Container Der Certbot Container läuft permanent und prüft alle **12 Stunden** ob Zertifikate erneuert werden müssen. ```bash # Check Certbot Logs docker logs certbot # Manuelles Renewal testen (Dry-Run) docker exec certbot certbot renew --dry-run # Manuelles Renewal (falls nötig) docker exec certbot certbot renew # Nginx nach Manual Renewal neu laden docker-compose restart web ``` ### Renewal Monitoring **Zertifikats-Ablaufdatum prüfen**: ```bash # Via Script ./scripts/ssl-test.sh # Manuell docker exec certbot certbot certificates ``` **Empfohlene Monitoring-Strategie**: - Certbot Logs täglich checken - Alert wenn Zertifikat < 30 Tage gültig - Automatisches Monitoring via Cron/SystemD Timer ## Troubleshooting ### Problem: Zertifikat kann nicht geholt werden **Symptom**: `ssl-init.sh` schlägt fehl **Ursachen & Lösungen**: 1. **DNS nicht korrekt**: ```bash # DNS prüfen dig michaelschiemer.de nslookup michaelschiemer.de # Warte bis DNS propagiert ist (kann 1-48h dauern) ``` 2. **Port 80 nicht erreichbar**: ```bash # Firewall prüfen sudo ufw status sudo ufw allow 80 sudo ufw allow 443 # Nginx Test curl -I http://michaelschiemer.de/.well-known/acme-challenge/test ``` 3. **ACME Challenge Location fehlt**: ```bash # Nginx Config prüfen docker exec web nginx -t # Log prüfen docker logs web ``` ### Problem: Zertifikat wird nicht erneuert **Symptom**: Certbot Renewal schlägt fehl **Lösungen**: 1. **Certbot Logs prüfen**: ```bash docker logs certbot docker exec certbot certbot renew --dry-run --verbose ``` 2. **Webroot Permissions**: ```bash # Permissions prüfen docker exec web ls -la /var/www/certbot/.well-known/acme-challenge/ ``` 3. **Nginx Config Syntax**: ```bash docker exec web nginx -t ``` ### Problem: HTTPS funktioniert nicht nach Renewal **Symptom**: Alte Zertifikate werden verwendet **Lösung**: ```bash # Nginx neu laden docker-compose restart web # Oder ohne Downtime docker exec web nginx -s reload ``` ## Zero-Downtime Renewal Nginx unterstützt **graceful reload** ohne Connection-Drops: ```bash # Reload ohne Downtime docker exec web nginx -s reload # In Auto-Renewal integrieren docker exec certbot certbot renew --post-hook "nginx -s reload" ``` ## Production Best Practices ### 1. Monitoring Setup **Cron Job für tägliche Checks**: ```bash # /etc/cron.daily/ssl-check #!/bin/bash /path/to/scripts/ssl-test.sh michaelschiemer.de > /var/log/ssl-check.log 2>&1 # Alert wenn weniger als 30 Tage DAYS_LEFT=$(docker exec certbot certbot certificates | grep "VALID:" | awk '{print $6}' | head -1) if [ "$DAYS_LEFT" -lt "30" ]; then echo "WARNING: SSL certificate expires in $DAYS_LEFT days" | mail -s "SSL Alert" admin@michaelschiemer.de fi ``` ### 2. Backup Strategy **Zertifikate Backup**: ```bash # Backup Let's Encrypt Config docker run --rm \ -v certbot-conf:/etc/letsencrypt \ -v $(pwd)/backups:/backup \ alpine tar czf /backup/letsencrypt-$(date +%Y%m%d).tar.gz /etc/letsencrypt # Restore docker run --rm \ -v certbot-conf:/etc/letsencrypt \ -v $(pwd)/backups:/backup \ alpine tar xzf /backup/letsencrypt-20241220.tar.gz -C / ``` ### 3. Security Hardening **HTTP/3 aktivieren** (bereits konfiguriert): ```nginx listen 443 quic reuseport; http3 on; add_header Alt-Svc 'h3=":443"; ma=86400'; ``` **HSTS Preload** (nach 6 Monaten stabiler Betrieb): ```nginx add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; ``` Dann einreichen bei: https://hstspreload.org/ ## Makefile Integration Füge zu `Makefile` hinzu: ```makefile # SSL Certificate Management ssl-init: ## Initialize Let's Encrypt certificates ./scripts/ssl-init.sh ssl-test: ## Test SSL configuration ./scripts/ssl-test.sh ssl-renew: ## Manually renew certificates docker exec certbot certbot renew docker-compose restart web ssl-status: ## Check certificate status docker exec certbot certbot certificates ``` **Verwendung**: ```bash make ssl-init # Initial Setup make ssl-test # Test SSL make ssl-renew # Manual Renewal make ssl-status # Check Expiry ``` ## Migration von Self-Signed zu Let's Encrypt Wenn du von Self-Signed Zertifikaten migrierst: ```bash # 1. Backup alte Zertifikate cp -r docker/nginx/ssl docker/nginx/ssl.backup # 2. SSL Init ausführen ./scripts/ssl-init.sh # 3. Nginx Config Update (automatisch via docker-compose.production.yml) # 4. Stack neu starten docker-compose -f docker-compose.yml -f docker-compose.production.yml restart ``` ## Kosten **Let's Encrypt**: ✅ **Kostenlos** - Unlimitierte Zertifikate - Automatische Renewal - Wildcard-Zertifikate möglich (DNS-01 Challenge) **Rate Limits**: - 50 Zertifikate pro Domain pro Woche - 5 Duplicate Certificates pro Woche - Kein Problem für normale Production-Nutzung ## Support & Dokumentation **Let's Encrypt Dokumentation**: https://letsencrypt.org/docs/ **Certbot Dokumentation**: https://eff-certbot.readthedocs.io/ **Framework SSL Issues**: https://github.com/yourusername/framework/issues ## Zusammenfassung **Setup-Schritte**: 1. ✅ `.env.production` konfigurieren 2. ✅ `./scripts/ssl-init.sh` ausführen 3. ✅ Production Stack starten 4. ✅ `./scripts/ssl-test.sh` validieren 5. ✅ SSL Labs Test (A+ Rating) **Auto-Renewal**: ✅ Certbot Container erneuert automatisch **Zero-Downtime**: ✅ Nginx reload ohne Connection-Drops **Production-Ready**: ✅ HTTP/3, TLS 1.3, Security Headers