diff --git a/docker-compose-prod.yml b/docker-compose-prod.yml new file mode 100644 index 0000000..704d305 --- /dev/null +++ b/docker-compose-prod.yml @@ -0,0 +1,70 @@ +# Production Docker Compose für Stargirlnails Kiel +# Mit Nginx Reverse Proxy und Let's Encrypt SSL-Zertifikaten + +version: '3.8' + +services: + # Hauptanwendung + stargirlnails: + build: . + container_name: stargirlnails-app + env_file: + - .env + environment: + - NODE_ENV=production + restart: unless-stopped + volumes: + - ./.storage:/app/.storage + networks: + - stargirlnails-network + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + depends_on: + - nginx + + # Nginx Reverse Proxy + nginx: + image: nginx:alpine + container_name: stargirlnails-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./nginx/conf.d:/etc/nginx/conf.d:ro + - certbot-certs:/etc/letsencrypt:ro + - certbot-webroot:/var/www/certbot:ro + networks: + - stargirlnails-network + depends_on: + - stargirlnails + command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" + + # Certbot für SSL-Zertifikate + certbot: + image: certbot/certbot + container_name: stargirlnails-certbot + restart: "no" + volumes: + - certbot-certs:/etc/letsencrypt + - certbot-webroot:/var/www/certbot + networks: + - stargirlnails-network + entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" + +# Volumes für persistente Daten +volumes: + certbot-certs: + driver: local + certbot-webroot: + driver: local + +# Netzwerk für interne Kommunikation +networks: + stargirlnails-network: + driver: bridge diff --git a/docs/production-deployment.md b/docs/production-deployment.md new file mode 100644 index 0000000..1d81a19 --- /dev/null +++ b/docs/production-deployment.md @@ -0,0 +1,259 @@ +# Produktions-Deployment für Stargirlnails Kiel + +Diese Anleitung beschreibt das Deployment der Stargirlnails Kiel Buchungsanwendung in einer produktiven Umgebung mit SSL-Zertifikaten. + +## 🏗️ Architektur + +``` +Internet → Nginx (Port 80/443) → Stargirlnails App (Port 3000) + ↓ + Certbot (SSL-Zertifikate) +``` + +### Services: +- **stargirlnails**: Hauptanwendung +- **nginx**: Reverse Proxy mit SSL-Terminierung +- **certbot**: Automatische SSL-Zertifikat-Verwaltung + +## 📋 Voraussetzungen + +### Server-Anforderungen: +- **OS**: Linux (Ubuntu 20.04+ empfohlen) +- **RAM**: Mindestens 2GB +- **CPU**: Mindestens 1 Core +- **Speicher**: Mindestens 10GB freier Speicher +- **Ports**: 80, 443 müssen erreichbar sein + +### Software: +- Docker & Docker Compose installiert +- Git installiert + +### Domain-Konfiguration: +- Domain muss auf Server-IP zeigen +- DNS-A-Eintrag korrekt konfiguriert + +## 🚀 Deployment + +### 1. Repository klonen +```bash +git clone +cd mybeautybooking +``` + +### 2. Umgebungsvariablen konfigurieren +```bash +cp .env.example .env +nano .env +``` + +**Wichtige Variablen für Produktion:** +```env +# Domain-Konfiguration (ERFORDERLICH für SSL) +DOMAIN=stargirlnails.de + +# Admin-Konfiguration (ERFORDERLICH für SSL) +ADMIN_EMAIL=admin@stargirlnails.de + +# E-Mail-Konfiguration +RESEND_API_KEY=your_resend_api_key_here +EMAIL_FROM=noreply@stargirlnails.de + +# Produktionsmodus +NODE_ENV=production +``` + +### 3. SSL-Setup und Deployment +```bash +# Linux/macOS +chmod +x scripts/setup-ssl.sh +./scripts/setup-ssl.sh + +# Windows (PowerShell) +.\scripts\setup-ssl.ps1 +``` + +Das Script: +- ✅ Erstellt Docker Volumes +- ✅ Konfiguriert Nginx mit der Domain +- ✅ Erstellt SSL-Zertifikat via Let's Encrypt +- ✅ Startet alle Services + +### 4. Verifikation +```bash +# Service-Status prüfen +docker-compose -f docker-compose-prod.yml ps + +# Logs anzeigen +docker-compose -f docker-compose-prod.yml logs -f + +# SSL-Zertifikat prüfen +curl -I https://your-domain.com +``` + +## 🔧 Verwaltung + +### Service-Befehle +```bash +# Services starten +docker-compose -f docker-compose-prod.yml up -d + +# Services stoppen +docker-compose -f docker-compose-prod.yml down + +# Logs anzeigen +docker-compose -f docker-compose-prod.yml logs -f + +# Einzelnen Service neu starten +docker-compose -f docker-compose-prod.yml restart stargirlnails +``` + +### SSL-Zertifikat-Verwaltung +```bash +# Zertifikat manuell erneuern +docker-compose -f docker-compose-prod.yml run --rm certbot certbot renew + +# Zertifikat-Status prüfen +docker-compose -f docker-compose-prod.yml run --rm certbot certbot certificates +``` + +**Automatische Erneuerung**: Certbot erneuert Zertifikate automatisch alle 12 Stunden. + +### Updates +```bash +# Code aktualisieren +git pull origin main + +# Neues Image bauen und starten +docker-compose -f docker-compose-prod.yml up -d --build + +# Alte Images aufräumen +docker image prune -f +``` + +## 🔒 Sicherheit + +### Nginx-Sicherheitsfeatures: +- ✅ **SSL/TLS**: TLS 1.2+ mit modernen Ciphern +- ✅ **HSTS**: Strict Transport Security Header +- ✅ **Rate Limiting**: API-Endpunkte geschützt +- ✅ **Security Headers**: XSS, CSRF, Clickjacking-Schutz +- ✅ **Gzip-Kompression**: Optimierte Performance + +### Rate Limits: +- **API-Endpunkte**: 10 Anfragen/Sekunde +- **Login-Endpunkte**: 5 Anfragen/Minute + +### Firewall-Empfehlung: +```bash +# UFW (Ubuntu) +sudo ufw allow 22/tcp # SSH +sudo ufw allow 80/tcp # HTTP +sudo ufw allow 443/tcp # HTTPS +sudo ufw enable +``` + +## 📊 Monitoring + +### Health Checks: +```bash +# Anwendungs-Health-Check +curl https://your-domain.com/health + +# SSL-Zertifikat-Status +openssl s_client -connect your-domain.com:443 -servername your-domain.com +``` + +### Logs überwachen: +```bash +# Alle Logs +docker-compose -f docker-compose-prod.yml logs -f + +# Nur Anwendungs-Logs +docker-compose -f docker-compose-prod.yml logs -f stargirlnails + +# Nur Nginx-Logs +docker-compose -f docker-compose-prod.yml logs -f nginx +``` + +### Ressourcen-Monitoring: +```bash +# Container-Ressourcen +docker stats + +# Disk-Usage +docker system df +``` + +## 🚨 Troubleshooting + +### Häufige Probleme: + +#### SSL-Zertifikat kann nicht erstellt werden +```bash +# Prüfe Domain-Erreichbarkeit +curl -I http://your-domain.com + +# Prüfe DNS-Einträge +nslookup your-domain.com + +# Prüfe Port 80 +telnet your-domain.com 80 +``` + +#### Services starten nicht +```bash +# Detaillierte Logs +docker-compose -f docker-compose-prod.yml logs + +# Container-Status +docker-compose -f docker-compose-prod.yml ps + +# Volumes prüfen +docker volume ls +``` + +#### Performance-Probleme +```bash +# Ressourcen-Check +docker stats + +# Nginx-Logs prüfen +docker-compose -f docker-compose-prod.yml logs nginx | grep -i error +``` + +### Log-Dateien: +- **Anwendung**: `docker-compose logs stargirlnails` +- **Nginx**: `docker-compose logs nginx` +- **Certbot**: `docker-compose logs certbot` + +## 🔄 Backup & Wiederherstellung + +### Daten-Backup: +```bash +# Storage-Daten sichern +tar -czf backup-$(date +%Y%m%d).tar.gz .storage/ + +# SSL-Zertifikate sichern +docker run --rm -v certbot-certs:/data -v $(pwd):/backup alpine tar czf /backup/ssl-backup-$(date +%Y%m%d).tar.gz -C /data . +``` + +### Wiederherstellung: +```bash +# Storage-Daten wiederherstellen +tar -xzf backup-YYYYMMDD.tar.gz + +# SSL-Zertifikate wiederherstellen +docker run --rm -v certbot-certs:/data -v $(pwd):/backup alpine tar xzf /backup/ssl-backup-YYYYMMDD.tar.gz -C /data +``` + +## 📞 Support + +Bei Problemen: +1. Prüfe die Logs: `docker-compose -f docker-compose-prod.yml logs` +2. Prüfe den Service-Status: `docker-compose -f docker-compose-prod.yml ps` +3. Prüfe die Dokumentation in `docs/` +4. Erstelle ein Issue im Repository + +--- + +**Wichtiger Hinweis**: Diese Konfiguration ist für Produktionsumgebungen optimiert. Für Entwicklung verwende `docker-compose.yml`. diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..c773f38 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,164 @@ +# Nginx Hauptkonfiguration für Stargirlnails Kiel +# Optimiert für Produktionsumgebung + +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; + use epoll; + multi_accept on; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Logging + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + + # Performance-Optimierungen + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + client_max_body_size 10M; + + # Gzip-Kompression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_proxied any; + gzip_comp_level 6; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/json + application/javascript + application/xml+rss + application/atom+xml + image/svg+xml; + + # Sicherheits-Header + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self';" always; + + # Rate Limiting + limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; + limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; + + # Upstream für die Anwendung + upstream stargirlnails { + server stargirlnails:3000; + } + + # HTTP-Server (leitet zu HTTPS weiter) + server { + listen 80; + server_name _; + + # Let's Encrypt Challenge + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } + + # Alle anderen Anfragen zu HTTPS weiterleiten + location / { + return 301 https://$host$request_uri; + } + } + + # HTTPS-Server + server { + listen 443 ssl http2; + server_name _; + + # SSL-Konfiguration + ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem; + + # SSL-Optimierungen + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384; + ssl_prefer_server_ciphers off; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + + # HSTS + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + # Proxy-Einstellungen + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # Timeouts + proxy_connect_timeout 30s; + proxy_send_timeout 30s; + proxy_read_timeout 30s; + + # API-Endpunkte mit Rate Limiting + location /rpc { + limit_req zone=api burst=20 nodelay; + proxy_pass http://stargirlnails; + } + + # Login-Endpunkte mit strengerem Rate Limiting + location ~ ^/(login|auth) { + limit_req zone=login burst=5 nodelay; + proxy_pass http://stargirlnails; + } + + # Statische Dateien (Assets) + location /static/ { + proxy_pass http://stargirlnails; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Assets-Verzeichnis + location /assets/ { + proxy_pass http://stargirlnails; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Favicon + location /favicon.ico { + proxy_pass http://stargirlnails; + expires 1y; + add_header Cache-Control "public"; + } + + # Health Check + location /health { + proxy_pass http://stargirlnails; + access_log off; + } + + # Security.txt + location /.well-known/security.txt { + proxy_pass http://stargirlnails; + expires 1d; + } + + # Alle anderen Anfragen + location / { + proxy_pass http://stargirlnails; + } + } +} diff --git a/scripts/setup-ssl.ps1 b/scripts/setup-ssl.ps1 new file mode 100644 index 0000000..4040a24 --- /dev/null +++ b/scripts/setup-ssl.ps1 @@ -0,0 +1,113 @@ +# PowerShell-Script für SSL-Setup auf Windows (Entwicklung) +# Für Produktionsumgebung verwende das Bash-Script auf Linux + +param( + [string]$Domain = "", + [string]$AdminEmail = "" +) + +Write-Host "🔧 Stargirlnails Kiel - SSL-Setup (Windows)" -ForegroundColor Blue +Write-Host "=============================================" + +# Prüfe ob .env-Datei existiert +if (-not (Test-Path ".env")) { + Write-Host "❌ .env-Datei nicht gefunden!" -ForegroundColor Red + Write-Host "Bitte erstelle eine .env-Datei mit DOMAIN und ADMIN_EMAIL" + exit 1 +} + +# Lade .env-Datei +$envContent = Get-Content ".env" +$envVars = @{} +foreach ($line in $envContent) { + if ($line -match "^([^#][^=]+)=(.*)$") { + $envVars[$matches[1]] = $matches[2] + } +} + +# Verwende Parameter oder .env-Werte +if ($Domain) { $envVars["DOMAIN"] = $Domain } +if ($AdminEmail) { $envVars["ADMIN_EMAIL"] = $AdminEmail } + +# Prüfe erforderliche Variablen +if (-not $envVars["DOMAIN"]) { + Write-Host "❌ DOMAIN nicht definiert!" -ForegroundColor Red + Write-Host "Verwende: .\setup-ssl.ps1 -Domain 'example.com' -AdminEmail 'admin@example.com'" + exit 1 +} + +if (-not $envVars["ADMIN_EMAIL"]) { + Write-Host "❌ ADMIN_EMAIL nicht definiert!" -ForegroundColor Red + Write-Host "Verwende: .\setup-ssl.ps1 -Domain 'example.com' -AdminEmail 'admin@example.com'" + exit 1 +} + +Write-Host "✅ Domain: $($envVars['DOMAIN'])" -ForegroundColor Green +Write-Host "✅ Admin E-Mail: $($envVars['ADMIN_EMAIL'])" -ForegroundColor Green +Write-Host "" + +# Erstelle nginx.conf mit korrekter Domain +Write-Host "📝 Erstelle Nginx-Konfiguration..." -ForegroundColor Yellow +$nginxConfig = Get-Content "nginx/nginx.conf" -Raw +$nginxConfig = $nginxConfig -replace '\$\{DOMAIN\}', $envVars["DOMAIN"] +Set-Content "nginx/nginx.conf" $nginxConfig + +# Erstelle Docker Volumes +Write-Host "📦 Erstelle Docker Volumes..." -ForegroundColor Yellow +docker volume create certbot-certs 2>$null +docker volume create certbot-webroot 2>$null + +# Starte temporären HTTP-Server +Write-Host "🌐 Starte temporären HTTP-Server..." -ForegroundColor Yellow +docker-compose -f docker-compose-prod.yml up -d nginx + +# Warte auf Nginx +Write-Host "⏳ Warte auf Nginx..." -ForegroundColor Yellow +Start-Sleep -Seconds 10 + +# Erstelle SSL-Zertifikat +Write-Host "🔐 Erstelle SSL-Zertifikat für $($envVars['DOMAIN'])..." -ForegroundColor Yellow +$certbotCmd = "docker-compose -f docker-compose-prod.yml run --rm certbot certbot certonly --webroot --webroot-path=/var/www/certbot --email $($envVars['ADMIN_EMAIL']) --agree-tos --no-eff-email --force-renewal -d $($envVars['DOMAIN'])" +Invoke-Expression $certbotCmd + +if ($LASTEXITCODE -eq 0) { + Write-Host "✅ SSL-Zertifikat erfolgreich erstellt!" -ForegroundColor Green +} else { + Write-Host "❌ SSL-Zertifikat-Erstellung fehlgeschlagen!" -ForegroundColor Red + Write-Host "Mögliche Ursachen:" + Write-Host "- Domain ist nicht erreichbar" + Write-Host "- Port 80 ist blockiert" + Write-Host "- DNS-Einträge sind nicht korrekt" + exit 1 +} + +# Starte alle Services +Write-Host "🚀 Starte alle Services..." -ForegroundColor Yellow +docker-compose -f docker-compose-prod.yml up -d + +# Prüfe Status +Write-Host "🔍 Prüfe Service-Status..." -ForegroundColor Yellow +Start-Sleep -Seconds 5 + +$services = docker-compose -f docker-compose-prod.yml ps +if ($services -match "Up") { + Write-Host "✅ Alle Services laufen!" -ForegroundColor Green + Write-Host "" + Write-Host "🌐 Deine Anwendung ist jetzt verfügbar unter:" -ForegroundColor Blue + Write-Host " https://$($envVars['DOMAIN'])" -ForegroundColor Green + Write-Host "" + Write-Host "📋 Nützliche Befehle:" -ForegroundColor Blue + Write-Host " Status anzeigen: docker-compose -f docker-compose-prod.yml ps" + Write-Host " Logs anzeigen: docker-compose -f docker-compose-prod.yml logs -f" + Write-Host " Services stoppen: docker-compose -f docker-compose-prod.yml down" + Write-Host " Zertifikat erneuern: docker-compose -f docker-compose-prod.yml run --rm certbot certbot renew" + Write-Host "" + Write-Host "⚠️ Wichtig:" -ForegroundColor Yellow + Write-Host " - SSL-Zertifikate werden automatisch alle 12 Stunden erneuert" + Write-Host " - Überwache die Logs regelmäßig" + Write-Host " - Stelle sicher, dass Port 80 und 443 erreichbar sind" +} else { + Write-Host "❌ Einige Services sind nicht gestartet!" -ForegroundColor Red + Write-Host "Prüfe die Logs: docker-compose -f docker-compose-prod.yml logs" + exit 1 +} diff --git a/scripts/setup-ssl.sh b/scripts/setup-ssl.sh new file mode 100644 index 0000000..7f56d66 --- /dev/null +++ b/scripts/setup-ssl.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# SSL-Setup-Script für Stargirlnails Kiel +# Erstellt Let's Encrypt-Zertifikate und startet die Produktionsumgebung + +set -e + +# Farben für Output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}🔧 Stargirlnails Kiel - SSL-Setup${NC}" +echo "==================================" + +# Prüfe ob .env-Datei existiert +if [ ! -f .env ]; then + echo -e "${RED}❌ .env-Datei nicht gefunden!${NC}" + echo "Bitte erstelle eine .env-Datei mit DOMAIN und ADMIN_EMAIL" + exit 1 +fi + +# Lade Umgebungsvariablen +source .env + +# Prüfe erforderliche Variablen +if [ -z "$DOMAIN" ]; then + echo -e "${RED}❌ DOMAIN nicht in .env definiert!${NC}" + exit 1 +fi + +if [ -z "$ADMIN_EMAIL" ]; then + echo -e "${RED}❌ ADMIN_EMAIL nicht in .env definiert!${NC}" + exit 1 +fi + +echo -e "${GREEN}✅ Domain: $DOMAIN${NC}" +echo -e "${GREEN}✅ Admin E-Mail: $ADMIN_EMAIL${NC}" +echo "" + +# Erstelle nginx.conf mit korrekter Domain +echo -e "${YELLOW}📝 Erstelle Nginx-Konfiguration...${NC}" +sed "s/\${DOMAIN}/$DOMAIN/g" nginx/nginx.conf > nginx/nginx.conf.tmp +mv nginx/nginx.conf.tmp nginx/nginx.conf + +# Erstelle Docker Volumes +echo -e "${YELLOW}📦 Erstelle Docker Volumes...${NC}" +docker volume create certbot-certs 2>/dev/null || true +docker volume create certbot-webroot 2>/dev/null || true + +# Starte temporären HTTP-Server für Domain-Validierung +echo -e "${YELLOW}🌐 Starte temporären HTTP-Server...${NC}" +docker-compose -f docker-compose-prod.yml up -d nginx + +# Warte bis Nginx läuft +echo -e "${YELLOW}⏳ Warte auf Nginx...${NC}" +sleep 10 + +# Erstelle SSL-Zertifikat +echo -e "${YELLOW}🔐 Erstelle SSL-Zertifikat für $DOMAIN...${NC}" +docker-compose -f docker-compose-prod.yml run --rm certbot certbot certonly \ + --webroot \ + --webroot-path=/var/www/certbot \ + --email $ADMIN_EMAIL \ + --agree-tos \ + --no-eff-email \ + --force-renewal \ + -d $DOMAIN + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✅ SSL-Zertifikat erfolgreich erstellt!${NC}" +else + echo -e "${RED}❌ SSL-Zertifikat-Erstellung fehlgeschlagen!${NC}" + echo "Mögliche Ursachen:" + echo "- Domain ist nicht erreichbar" + echo "- Port 80 ist blockiert" + echo "- DNS-Einträge sind nicht korrekt" + exit 1 +fi + +# Starte alle Services +echo -e "${YELLOW}🚀 Starte alle Services...${NC}" +docker-compose -f docker-compose-prod.yml up -d + +# Prüfe Status +echo -e "${YELLOW}🔍 Prüfe Service-Status...${NC}" +sleep 5 + +if docker-compose -f docker-compose-prod.yml ps | grep -q "Up"; then + echo -e "${GREEN}✅ Alle Services laufen!${NC}" + echo "" + echo -e "${BLUE}🌐 Deine Anwendung ist jetzt verfügbar unter:${NC}" + echo -e "${GREEN} https://$DOMAIN${NC}" + echo "" + echo -e "${BLUE}📋 Nützliche Befehle:${NC}" + echo " Status anzeigen: docker-compose -f docker-compose-prod.yml ps" + echo " Logs anzeigen: docker-compose -f docker-compose-prod.yml logs -f" + echo " Services stoppen: docker-compose -f docker-compose-prod.yml down" + echo " Zertifikat erneuern: docker-compose -f docker-compose-prod.yml run --rm certbot certbot renew" + echo "" + echo -e "${YELLOW}⚠️ Wichtig:${NC}" + echo " - SSL-Zertifikate werden automatisch alle 12 Stunden erneuert" + echo " - Überwache die Logs regelmäßig" + echo " - Stelle sicher, dass Port 80 und 443 erreichbar sind" +else + echo -e "${RED}❌ Einige Services sind nicht gestartet!${NC}" + echo "Prüfe die Logs: docker-compose -f docker-compose-prod.yml logs" + exit 1 +fi