24 KiB
Automatische Zertifikats-Erneuerung Konzept für Let's Encrypt
1. Übersicht
1.1 Ziel
Implementierung einer automatischen Erneuerungsfunktion für Let's Encrypt (LE) Zertifikate, die ablaufende Zertifikate rechtzeitig erneuert, bevor sie ablaufen.
1.2 Anforderungen
- Proaktive Erneuerung: Zertifikate werden erneuert, bevor sie ablaufen (z.B. 30 Tage vor Ablauf)
- Automatische Ausführung: Läuft im Hintergrund ohne Benutzerinteraktion
- Fehlerbehandlung: Robustes Error-Handling und Retry-Mechanismus
- Logging & Monitoring: Umfassendes Logging für Nachverfolgbarkeit
- Konfigurierbarkeit: Erneuerungs-Schwellenwerte und Intervalle konfigurierbar
- Berechtigungen: Respektiert bestehende Permission-Systeme
- DNS-Validierung: Automatische DNS-Challenge-Validierung vor Erneuerung
2. Architektur
2.1 Komponenten-Übersicht
┌─────────────────────────────────────────────────────────────┐
│ Auto-Renewal System │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Scheduler │───>│ Certificate │───>│ Renewal │ │
│ │ (Cron) │ │ Scanner │ │ Worker │ │
│ └──────────────┘ └──────────────┘ └─────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ v v v │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Config │ │ Database │ │ ACME │ │
│ │ Manager │ │ Queries │ │ Client │ │
│ └──────────────┘ └──────────────┘ └─────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Logger │ │ Notifier │ │ Retry │ │
│ │ Service │ │ Service │ │ Manager │ │
│ └──────────────┘ └──────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
2.2 Workflow
1. Scheduler startet (z.B. täglich um 02:00 Uhr)
│
├─> 2. Scanner identifiziert ablaufende Zertifikate
│ (expires_at < now + renewal_threshold)
│
├─> 3. Für jedes Zertifikat:
│ │
│ ├─> 3.1 Prüfe ob Auto-Renewal aktiviert
│ │
│ ├─> 3.2 Prüfe ob bereits Erneuerung läuft
│ │
│ ├─> 3.3 Prüfe Berechtigungen (Space-Zugriff)
│ │
│ ├─> 3.4 Validiere DNS (CNAME Check)
│ │
│ ├─> 3.5 Erstelle Renewal-Job
│ │
│ └─> 3.6 Queue für Worker
│
├─> 4. Worker verarbeitet Jobs sequenziell
│ │
│ ├─> 4.1 Hole FQDN-Informationen
│ │
│ ├─> 4.2 Hole ACME-Provider-Konfiguration
│ │
│ ├─> 4.3 Rufe RequestCertificate() auf
│ │
│ ├─> 4.4 Speichere neues Zertifikat
│ │
│ ├─> 4.5 Markiere altes Zertifikat als "replaced"
│ │
│ └─> 4.6 Logge Erfolg/Fehler
│
└─> 5. Cleanup & Reporting
3. Datenbank-Schema
3.1 Erweiterte Certificates-Tabelle
-- Migration: Erweitere certificates-Tabelle um Auto-Renewal-Felder
ALTER TABLE certificates ADD COLUMN auto_renewal_enabled BOOLEAN DEFAULT 1;
ALTER TABLE certificates ADD COLUMN renewal_attempts INTEGER DEFAULT 0;
ALTER TABLE certificates ADD COLUMN last_renewal_attempt DATETIME;
ALTER TABLE certificates ADD COLUMN next_renewal_check DATETIME;
ALTER TABLE certificates ADD COLUMN renewal_status TEXT; -- 'pending', 'in_progress', 'success', 'failed', 'disabled'
ALTER TABLE certificates ADD COLUMN replaced_by_cert_id TEXT; -- ID des neuen Zertifikats
ALTER TABLE certificates ADD COLUMN replaces_cert_id TEXT; -- ID des ersetzten Zertifikats
3.2 Neue Tabelle: certificate_renewal_logs
CREATE TABLE IF NOT EXISTS certificate_renewal_logs (
id TEXT PRIMARY KEY,
certificate_id TEXT NOT NULL,
fqdn_id TEXT NOT NULL,
space_id TEXT NOT NULL,
renewal_status TEXT NOT NULL, -- 'started', 'success', 'failed', 'skipped'
renewal_reason TEXT, -- 'expiring_soon', 'manual', 'retry'
error_message TEXT,
old_expires_at DATETIME,
new_expires_at DATETIME,
new_certificate_id TEXT,
renewal_duration_seconds INTEGER,
trace_id TEXT,
created_at DATETIME NOT NULL,
FOREIGN KEY (certificate_id) REFERENCES certificates(id) ON DELETE CASCADE,
FOREIGN KEY (fqdn_id) REFERENCES fqdns(id) ON DELETE CASCADE,
FOREIGN KEY (space_id) REFERENCES spaces(id) ON DELETE CASCADE
);
CREATE INDEX idx_renewal_logs_certificate_id ON certificate_renewal_logs(certificate_id);
CREATE INDEX idx_renewal_logs_created_at ON certificate_renewal_logs(created_at);
CREATE INDEX idx_renewal_logs_status ON certificate_renewal_logs(renewal_status);
3.3 Neue Tabelle: renewal_config
CREATE TABLE IF NOT EXISTS renewal_config (
id TEXT PRIMARY KEY DEFAULT 'global',
enabled BOOLEAN DEFAULT 1,
renewal_threshold_days INTEGER DEFAULT 30, -- Erneuere X Tage vor Ablauf
check_interval_hours INTEGER DEFAULT 24, -- Wie oft prüfen (in Stunden)
max_renewal_attempts INTEGER DEFAULT 3, -- Max. Versuche pro Zertifikat
retry_delay_hours INTEGER DEFAULT 24, -- Wartezeit zwischen Retries
notification_enabled BOOLEAN DEFAULT 0,
notification_email TEXT,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL
);
-- Initiale Konfiguration einfügen
INSERT INTO renewal_config (id, enabled, renewal_threshold_days, check_interval_hours, max_renewal_attempts, retry_delay_hours, created_at, updated_at)
VALUES ('global', 1, 30, 24, 3, 24, datetime('now'), datetime('now'));
3.4 FQDN-Tabelle Erweiterung
-- Optional: Pro-FQDN Auto-Renewal-Einstellungen
ALTER TABLE fqdns ADD COLUMN auto_renewal_enabled BOOLEAN DEFAULT 1;
4. Konfiguration
4.1 Global Configuration (Environment Variables)
# Auto-Renewal Einstellungen
AUTO_RENEWAL_ENABLED=true
AUTO_RENEWAL_THRESHOLD_DAYS=30
AUTO_RENEWAL_CHECK_INTERVAL_HOURS=24
AUTO_RENEWAL_SCHEDULE="0 2 * * *" # Cron-Format: Täglich um 02:00 Uhr
AUTO_RENEWAL_MAX_ATTEMPTS=3
AUTO_RENEWAL_RETRY_DELAY_HOURS=24
# Notifications
AUTO_RENEWAL_NOTIFICATIONS_ENABLED=false
AUTO_RENEWAL_NOTIFICATION_EMAIL=admin@example.com
# Concurrency
AUTO_RENEWAL_MAX_CONCURRENT=1 # Anzahl paralleler Erneuerungen
4.2 Per-FQDN Configuration
- Default: Auto-Renewal aktiviert für alle FQDNs
- Opt-out: Pro FQDN deaktivierbar über
fqdns.auto_renewal_enabled - Opt-out: Pro Zertifikat deaktivierbar über
certificates.auto_renewal_enabled
5. Scheduler-Implementierung
5.1 Optionen
Option A: Go Cron Library (Empfohlen)
import "github.com/robfig/cron/v3"
c := cron.New()
c.AddFunc("0 2 * * *", func() {
runCertificateRenewalScan()
})
c.Start()
Vorteile:
- Einfach zu implementieren
- Gut getestet
- Cron-Format unterstützt
Nachteile:
- Läuft nur im Backend-Prozess
- Bei Neustart muss Scheduler neu gestartet werden
Option B: Separate Background Service
// Separate Go-Routine die kontinuierlich läuft
go func() {
ticker := time.NewTicker(24 * time.Hour)
for {
select {
case <-ticker.C:
runCertificateRenewalScan()
case <-ctx.Done():
return
}
}
}()
Vorteile:
- Einfacher zu debuggen
- Keine externe Dependency
Nachteile:
- Weniger flexibel als Cron
- Muss selbst implementiert werden
Option C: System Cron Job
# /etc/cron.d/certigo-renewal
0 2 * * * curl -X POST http://localhost:8080/api/internal/renewal/scan
Vorteile:
- Unabhängig vom Backend-Prozess
- Läuft auch wenn Backend neu gestartet wird
Nachteile:
- Externe Dependency (curl)
- Schwieriger zu debuggen
- Benötigt separaten API-Endpunkt
Empfehlung: Option A (Go Cron Library)
6. Certificate Scanner
6.1 Query für ablaufende Zertifikate
SELECT
c.id,
c.fqdn_id,
c.space_id,
c.certificate_id,
c.provider_id,
c.expires_at,
c.auto_renewal_enabled,
c.renewal_status,
c.renewal_attempts,
c.last_renewal_attempt,
f.fqdn,
f.acme_email,
f.acme_key_id,
f.provider_id as fqdn_provider_id
FROM certificates c
INNER JOIN fqdns f ON c.fqdn_id = f.id
WHERE
-- Nur Leaf-Zertifikate (nicht Intermediate)
c.is_intermediate = 0
-- Nur Let's Encrypt Zertifikate (via certigo-acmeproxy)
AND c.provider_id = 'certigo-acmeproxy'
-- Nur gültige/ausgestellte Zertifikate
AND c.status = 'issued'
-- Auto-Renewal muss aktiviert sein
AND (c.auto_renewal_enabled IS NULL OR c.auto_renewal_enabled = 1)
AND (f.auto_renewal_enabled IS NULL OR f.auto_renewal_enabled = 1)
-- Zertifikat läuft bald ab
AND c.expires_at IS NOT NULL
AND datetime(c.expires_at) <= datetime('now', '+' || ? || ' days')
-- Keine laufende Erneuerung
AND (c.renewal_status IS NULL OR c.renewal_status != 'in_progress')
-- Nicht zu viele Versuche
AND (c.renewal_attempts IS NULL OR c.renewal_attempts < ?)
-- Retry-Delay eingehalten
AND (
c.last_renewal_attempt IS NULL
OR datetime(c.last_renewal_attempt) <= datetime('now', '-' || ? || ' hours')
)
ORDER BY c.expires_at ASC;
6.2 Filter-Logik
Ausschluss-Kriterien:
- ✅ Intermediate-Zertifikate (nur Leaf)
- ✅ Nur
certigo-acmeproxyProvider - ✅ Status = 'issued'
- ✅ Auto-Renewal aktiviert (Certificate + FQDN)
- ✅
expires_atinnerhalb Threshold - ✅ Keine laufende Erneuerung (
renewal_status != 'in_progress') - ✅ Max. Versuche nicht überschritten
- ✅ Retry-Delay eingehalten
7. Renewal Worker
7.1 Renewal-Prozess
func renewCertificate(certID string, fqdnID string, spaceID string) error {
traceID := generateTraceID()
// 1. Markiere als "in_progress"
updateRenewalStatus(certID, "in_progress", traceID)
// 2. Hole FQDN-Informationen
fqdn, err := getFQDN(fqdnID)
if err != nil {
logRenewalError(certID, traceID, "FQDN nicht gefunden", err)
return err
}
// 3. Prüfe DNS (CNAME)
if !validateDNSCNAME(fqdn.FQDN) {
logRenewalError(certID, traceID, "DNS-CNAME nicht gültig", nil)
return fmt.Errorf("DNS validation failed")
}
// 4. Hole ACME-Provider-Konfiguration
providerConfig, err := getACMEProviderConfig(fqdn.ProviderID)
if err != nil {
logRenewalError(certID, traceID, "Provider-Konfiguration nicht gefunden", err)
return err
}
// 5. Rufe RequestCertificate() auf
result, err := RequestCertificate(
fqdn.FQDN,
fqdn.AcmeEmail,
fqdnID,
fqdn.AcmeKeyID,
traceID,
updateTokenFunc,
cleanupTokenFunc,
statusCallback,
)
if err != nil {
// 6a. Fehler: Erhöhe Versuche, setze Retry-Zeitpunkt
incrementRenewalAttempts(certID)
setNextRenewalCheck(certID, time.Now().Add(retryDelay))
updateRenewalStatus(certID, "failed", traceID)
logRenewalError(certID, traceID, "Erneuerung fehlgeschlagen", err)
return err
}
// 6b. Erfolg: Speichere neues Zertifikat
newCertID, err := saveNewCertificate(result, fqdnID, spaceID)
if err != nil {
logRenewalError(certID, traceID, "Fehler beim Speichern", err)
return err
}
// 7. Verknüpfe alte und neue Zertifikate
linkCertificates(certID, newCertID)
// 8. Markiere als erfolgreich
updateRenewalStatus(certID, "success", traceID)
logRenewalSuccess(certID, newCertID, traceID)
// 9. Optional: Benachrichtigung senden
sendRenewalNotification(fqdn.FQDN, newCertID, traceID)
return nil
}
7.2 Concurrency Control
Sequenzielle Verarbeitung:
- Pro FQDN nur eine Erneuerung gleichzeitig
- Pro Space max. N Erneuerungen parallel (konfigurierbar)
- Global max. M Erneuerungen parallel (konfigurierbar)
Implementierung:
// Semaphore für Concurrency Control
var renewalSemaphore = make(chan struct{}, maxConcurrentRenewals)
func renewCertificateWithLock(certID string, fqdnID string, spaceID string) error {
renewalSemaphore <- struct{}{} // Acquire
defer func() { <-renewalSemaphore }() // Release
return renewCertificate(certID, fqdnID, spaceID)
}
8. Fehlerbehandlung & Retry
8.1 Fehler-Kategorien
| Fehler-Typ | Retry? | Max. Versuche | Beispiel |
|---|---|---|---|
| DNS-Validierung fehlgeschlagen | ✅ Ja | 3 | CNAME nicht gesetzt |
| ACME-Provider-Fehler | ✅ Ja | 3 | Rate Limit erreicht |
| Netzwerk-Fehler | ✅ Ja | 5 | Timeout, Connection Error |
| Konfigurations-Fehler | ❌ Nein | 0 | Provider nicht konfiguriert |
| Berechtigungs-Fehler | ❌ Nein | 0 | Kein Space-Zugriff |
8.2 Retry-Strategie
Exponential Backoff:
Versuch 1: Sofort
Versuch 2: Nach 24 Stunden
Versuch 3: Nach 48 Stunden
Versuch 4+: Nach 72 Stunden
Oder: Fixed Delay
Alle Retries: Nach X Stunden (konfigurierbar, Default: 24h)
8.3 Fehler-Logging
type RenewalError struct {
CertificateID string
FQDN string
ErrorType string // 'dns', 'acme', 'network', 'config'
ErrorMessage string
TraceID string
Timestamp time.Time
Attempt int
}
9. Logging & Monitoring
9.1 Structured Logging
Erfolgreiche Erneuerung:
{
"event": "certificate_renewal_success",
"trace_id": "abc123",
"certificate_id": "cert-uuid",
"fqdn": "example.com",
"old_expires_at": "2025-02-15T10:00:00Z",
"new_expires_at": "2025-05-15T10:00:00Z",
"new_certificate_id": "new-cert-uuid",
"duration_seconds": 45,
"timestamp": "2025-01-15T02:05:00Z"
}
Fehlgeschlagene Erneuerung:
{
"event": "certificate_renewal_failed",
"trace_id": "abc123",
"certificate_id": "cert-uuid",
"fqdn": "example.com",
"error_type": "dns_validation",
"error_message": "CNAME record not found",
"attempt": 1,
"max_attempts": 3,
"next_retry": "2025-01-16T02:00:00Z",
"timestamp": "2025-01-15T02:05:00Z"
}
9.2 Audit Logs
Integration in bestehendes Audit-System:
auditService.Track(ctx, "RENEW", "certificate", certID, "system", "auto-renewal", map[string]interface{}{
"fqdn": fqdn,
"old_expires_at": oldExpiresAt,
"new_expires_at": newExpiresAt,
"trace_id": traceID,
}, ipAddress, userAgent)
9.3 Metrics
Zu tracken:
- Anzahl Erneuerungen pro Tag/Woche/Monat
- Erfolgsrate (Erfolgreich / Gesamt)
- Durchschnittliche Erneuerungsdauer
- Anzahl fehlgeschlagener Erneuerungen
- Anzahl Retries
- Zertifikate die bald ablaufen (Warnung)
10. API-Endpunkte
10.1 Manuelle Erneuerung
POST /api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renew
Manuell eine Erneuerung auslösen.
Response:
{
"success": true,
"message": "Erneuerung gestartet",
"trace_id": "abc123",
"estimated_completion": "2025-01-15T02:05:00Z"
}
10.2 Erneuerungs-Status abrufen
GET /api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renewal-status
Response:
{
"auto_renewal_enabled": true,
"renewal_status": "success",
"renewal_attempts": 1,
"last_renewal_attempt": "2025-01-15T02:00:00Z",
"next_renewal_check": "2025-01-16T02:00:00Z",
"replaced_by_cert_id": "new-cert-uuid"
}
10.3 Erneuerungs-Logs abrufen
GET /api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/renewal-logs
Query Parameters:
limit(optional): Anzahl Einträge (Default: 50)offset(optional): Pagination Offset
Response:
{
"logs": [
{
"id": "log-uuid",
"renewal_status": "success",
"renewal_reason": "expiring_soon",
"old_expires_at": "2025-02-15T10:00:00Z",
"new_expires_at": "2025-05-15T10:00:00Z",
"new_certificate_id": "new-cert-uuid",
"renewal_duration_seconds": 45,
"trace_id": "abc123",
"created_at": "2025-01-15T02:00:00Z"
}
],
"total": 10,
"limit": 50,
"offset": 0
}
10.4 Auto-Renewal konfigurieren
PUT /api/spaces/{spaceId}/fqdns/{fqdnId}/certificates/{certId}/auto-renewal
Body:
{
"enabled": true
}
10.5 Global Configuration
GET /api/internal/renewal/config
Response:
{
"enabled": true,
"renewal_threshold_days": 30,
"check_interval_hours": 24,
"max_renewal_attempts": 3,
"retry_delay_hours": 24
}
PUT /api/internal/renewal/config
Body:
{
"enabled": true,
"renewal_threshold_days": 30,
"check_interval_hours": 24,
"max_renewal_attempts": 3,
"retry_delay_hours": 24
}
10.6 Manueller Scan (für Testing)
POST /api/internal/renewal/scan
Löst einen manuellen Scan aus (nur für Admins).
Response:
{
"success": true,
"certificates_found": 5,
"certificates_queued": 3,
"certificates_skipped": 2
}
11. Frontend-Integration
11.1 UI-Komponenten
Auto-Renewal Toggle
- Ort: Certificate Detail View
- Funktion: Ein/Aus-Schalter für Auto-Renewal pro Zertifikat
Renewal Status Badge
- Ort: Certificate List & Detail View
- Anzeige:
- 🟢 "Auto-Renewal aktiv" (wenn enabled)
- 🟡 "Erneuerung läuft" (wenn in_progress)
- 🔴 "Erneuerung fehlgeschlagen" (wenn failed)
- ⚪ "Auto-Renewal deaktiviert" (wenn disabled)
Renewal History
- Ort: Certificate Detail View
- Anzeige: Tabelle mit Erneuerungs-Logs
- Spalten: Datum, Status, Grund, Neue Ablaufzeit, Trace ID
Manuelle Erneuerung Button
- Ort: Certificate Detail View
- Funktion: "Jetzt erneuern" Button (falls Auto-Renewal deaktiviert)
Upcoming Renewals Dashboard
- Ort: Dashboard/Overview
- Anzeige: Liste von Zertifikaten die bald erneuert werden
- Filter: Nach Space, FQDN, Ablaufdatum
11.2 Notifications (Optional)
Email-Benachrichtigungen:
- Erfolgreiche Erneuerung
- Fehlgeschlagene Erneuerung (nach max. Versuchen)
- Warnung: Zertifikat läuft in X Tagen ab (falls Erneuerung fehlschlägt)
In-App Notifications:
- Toast-Notification bei erfolgreicher Erneuerung
- Alert bei fehlgeschlagener Erneuerung
12. Sicherheit & Berechtigungen
12.1 Berechtigungen
Auto-Renewal ausführen:
- System-User (für automatische Erneuerungen)
- Admin-User (für manuelle Erneuerungen)
- User mit
FULL_ACCESSauf Space (für manuelle Erneuerungen)
Auto-Renewal konfigurieren:
- Admin-User
- User mit
FULL_ACCESSauf Space
Erneuerungs-Logs anzeigen:
- Alle User mit Space-Zugriff (READ-Berechtigung)
12.2 Rate Limiting
Let's Encrypt Rate Limits:
- 50 Certificates per Registered Domain per week
- 300 New Orders per Account per 3 hours
Schutz:
- Tracke Anzahl Erneuerungen pro FQDN
- Verzögere Erneuerung wenn Rate Limit erreicht
- Logge Warnung bei Rate Limit
13. Testing & Rollout
13.1 Test-Plan
Phase 1: Unit Tests
- Certificate Scanner Query
- Renewal Worker Logic
- Retry-Mechanismus
- Error-Handling
Phase 2: Integration Tests
- End-to-End Erneuerung (mit Staging ACME)
- Fehler-Szenarien (DNS-Fehler, Rate Limit)
- Concurrency Tests
Phase 3: Staging Tests
- Test mit echten Staging-Zertifikaten
- Monitoring & Logging prüfen
- Performance-Tests
Phase 4: Production Rollout
- Feature Flag aktivieren
- Monitoring aktivieren
- Schrittweise Aktivierung (zuerst einzelne FQDNs)
13.2 Rollback-Plan
Falls Probleme auftreten:
- Auto-Renewal global deaktivieren (Config)
- Laufende Erneuerungen abbrechen (Status zurücksetzen)
- Manuelle Erneuerung weiterhin möglich
14. Monitoring & Alerting
14.1 Health Checks
Endpoint: GET /api/health/renewal
Response:
{
"status": "healthy",
"last_scan": "2025-01-15T02:00:00Z",
"next_scan": "2025-01-16T02:00:00Z",
"certificates_pending": 2,
"certificates_in_progress": 1,
"certificates_failed": 0
}
14.2 Alerts
Zu überwachen:
- ❌ Auto-Renewal Service läuft nicht
- ⚠️ Viele fehlgeschlagene Erneuerungen (> 10% in 24h)
- ⚠️ Zertifikate laufen in < 7 Tagen ab (ohne Erneuerung)
- ⚠️ Rate Limit erreicht
- ⚠️ Scheduler läuft nicht (letzter Scan > 48h her)
15. Zukünftige Erweiterungen
15.1 Multi-Provider Support
- Erneuerung für andere Provider (nicht nur Let's Encrypt)
15.2 Smart Scheduling
- Erneuerung basierend auf Traffic-Patterns
- Erneuerung außerhalb der Geschäftszeiten
15.3 Batch Renewals
- Erneuerung mehrerer Zertifikate gleichzeitig (wenn möglich)
15.4 Webhook-Integration
- Webhooks für erfolgreiche/fehlgeschlagene Erneuerungen
- Integration mit externen Monitoring-Tools
15.5 Certificate Rotation
- Automatische Rotation von Private Keys
- Unterstützung für Key-Rollover
16. Abhängigkeiten
16.1 Backend (Go)
// Cron Scheduler
github.com/robfig/cron/v3
// (Bereits vorhanden)
// - ACME Client (acme_client.go)
// - Certificate Parser (cert_parser.go)
// - Logger (cert_logger.go)
16.2 Frontend
Keine zusätzlichen Dependencies nötig.
17. Risiken & Mitigation
17.1 Risiken
| Risiko | Wahrscheinlichkeit | Impact | Mitigation |
|---|---|---|---|
| Rate Limit erreicht | Mittel | Hoch | Rate Limit Tracking, Verzögerung |
| DNS-Validierung fehlschlägt | Mittel | Hoch | DNS-Check vor Erneuerung, Retry |
| ACME-Provider Downtime | Niedrig | Hoch | Retry-Mechanismus, Fallback |
| Doppelte Erneuerung | Niedrig | Mittel | Status-Check, Locking |
| Datenbank-Lock | Niedrig | Mittel | Transaktionen, Timeouts |
17.2 Best Practices
- ✅ Idempotenz: Erneuerung kann mehrfach ausgeführt werden ohne Probleme
- ✅ Atomic Operations: Datenbank-Transaktionen für Konsistenz
- ✅ Graceful Degradation: Bei Fehlern weiterhin manuelle Erneuerung möglich
- ✅ Comprehensive Logging: Alle Schritte loggen für Debugging
- ✅ Rate Limit Awareness: Respektiere Let's Encrypt Limits
18. Zusammenfassung
18.1 Vorteile
- Automatisierung: Keine manuelle Intervention nötig
- Zuverlässigkeit: Zertifikate laufen nicht mehr ab
- Zeitersparnis: Weniger manuelle Arbeit
- Sicherheit: Immer gültige Zertifikate
18.2 Herausforderungen
- Komplexität: Zusätzliche Infrastruktur und Code
- Fehlerbehandlung: Robustes Error-Handling erforderlich
- Rate Limits: Let's Encrypt Limits beachten
- Testing: Umfangreiche Tests erforderlich
18.3 Empfohlene Implementierungs-Reihenfolge
- Phase 1: Datenbank-Schema & Grundfunktionalität
- Phase 2: Scanner & Worker
- Phase 3: Scheduler & Automation
- Phase 4: Frontend-Integration
- Phase 5: Monitoring & Alerting
- Phase 6: Notifications (Optional)
Erstellt am: 2025-01-XX
Version: 1.0
Status: Konzept - Noch nicht implementiert