# 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
