Teil unserer Performance & Scalability-Serie
Den vollständigen Leitfaden lesenNginx-Produktionskonfiguration: SSL, Caching und Sicherheit
Nginx ist der Produktions-Webserver, der praktisch alle Webbereitstellungen mit hohem Datenverkehr abwickelt. Bei guter Konfiguration bietet es SSL-Terminierung, effiziente Bereitstellung statischer Dateien, WebSocket-Proxy, Ratenbegrenzung und Sicherheitsheader – und das alles, bevor eine einzelne Anfrage Ihre Node.js-Anwendung erreicht. Bei schlechter Konfiguration kann es zu einem Engpass, einem Sicherheitsrisiko oder zur Ursache mysteriöser Cloudflare-Umleitungsschleifen kommen.
Dieser Leitfaden behandelt eine Nginx-Konfiguration in Produktionsqualität für eine Node.js-Bereitstellung mit mehreren Apps: Next.js-Frontend, NestJS-API und Docusaurus-Dokumente – alle laufen auf demselben Server hinter Cloudflare.
Wichtige Erkenntnisse
– Teilen Sie WWW und Nicht-WWW niemals in separate Serverblöcke hinter Cloudflare auf – dies führt zu Weiterleitungsschleifen – Verwenden Sie eine einzelne Nginx-Konfigurationsdatei in
/etc/nginx/conf.d/– verknüpfen Sie sie nicht auch mit einem Symlink insites-enabled/–X-XSS-Protectionist veraltet – verwenden Sie stattdessen CSP;X-Frame-Options: DENYist noch gültig –proxy_passmuss den abschließenden Schrägstrich enthalten, wenn ein Pfadpräfix verwendet wird
- Die Aktivierung der Gzip-Komprimierung für Text/*-MIME-Typen lohnt sich immer – Die Ratenbegrenzung erfordert die Definition von
limit_req_zoneauf der Ebenehttp{}, nicht auf der Ebeneserver{}- Let's Encrypt-Zertifikate erneuern sich automatisch mit Certbot; Fügen Sie einen Cron-Job hinzu, um Nginx nach der Erneuerung neu zu laden – WebSocket-Proxying erfordert bestimmte Header:
UpgradeundConnection
Verzeichnisstruktur
Halten Sie die Nginx-Konfiguration organisiert:
/etc/nginx/
nginx.conf — Main config (rarely touch this)
conf.d/
ecosire-production.conf — All your server blocks in ONE file
snippets/
ssl-params.snippet — SSL hardening (included by server blocks)
proxy-params.snippet — Common proxy headers
security-headers.snippet — Security headers
Kritisch: Geben Sie Ihre gesamte Konfiguration in conf.d/ecosire-production.conf ein. Fügen Sie es NICHT auch zu sites-enabled/ hinzu – dies führt dazu, dass Nginx die Konfiguration zweimal verarbeitet, was zu doppelten limit_req_zone-Fehlern und unerwartetem Verhalten führt.
Ratenbegrenzungszonen
Definieren Sie in Ihrer Konfiguration Ratenbegrenzungszonen auf der Ebene http{}. Sie können nicht innerhalb von server{}-Blöcken definiert werden:
# /etc/nginx/conf.d/ecosire-production.conf
# Must be at http{} level — these are in the main conf or conf.d root
limit_req_zone $binary_remote_addr zone=api_general:10m rate=60r/m;
limit_req_zone $binary_remote_addr zone=api_auth:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=api_public:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=static_files:10m rate=200r/m;
Hauptanwendungsserverblock
# Main web application — Next.js on port 3000
server {
listen 80;
listen [::]:80;
server_name ecosire.com www.ecosire.com;
# Cloudflare handles SSL termination — Nginx only sees HTTP
# (If direct SSL, add listen 443 ssl and certificate paths)
# Security headers
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# CSP — adjust based on your needs
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; frame-src https://js.stripe.com; connect-src 'self' https://api.ecosire.com;" always;
# Remove server version from responses
server_tokens off;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff2;
gzip_min_length 1024;
# ─── Static Files: Next.js build output ─────────────────────────
location /_next/static/ {
proxy_pass http://127.0.0.1:3000;
add_header Cache-Control "public, max-age=31536000, immutable";
# Files include content hash in filename — safe to cache forever
}
# ─── Public static assets ────────────────────────────────────────
location /assets/ {
proxy_pass http://127.0.0.1:3000;
add_header Cache-Control "public, max-age=86400"; # 1 day
}
# ─── Well-known files (no locale prefix) ─────────────────────────
location /.well-known/ {
proxy_pass http://127.0.0.1:3000;
add_header Cache-Control "public, max-age=86400";
}
# ─── App routes (rate limited) ───────────────────────────────────
location / {
limit_req zone=api_general burst=20 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
API-Serverblock
# NestJS API — port 3001
server {
listen 80;
listen [::]:80;
server_name api.ecosire.com;
server_tokens off;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# CORS — handled by NestJS, but Nginx can add preflight response
# for performance (avoids reaching Node.js for OPTIONS)
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "https://ecosire.com";
add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
add_header Access-Control-Allow-Credentials "true";
add_header Access-Control-Max-Age 1728000;
add_header Content-Length 0;
return 204;
}
limit_req zone=api_general burst=30 nodelay;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
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_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Stricter rate limits for auth endpoints
location ~ ^/api/auth/(login|exchange|callback) {
limit_req zone=api_auth burst=5 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:3001;
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;
}
# Health check — no rate limiting
location /api/health {
proxy_pass http://127.0.0.1:3001;
proxy_set_header Host $host;
access_log off; # Don't log health check spam
}
# Stripe webhook — needs raw body
location /api/billing/webhook {
proxy_pass http://127.0.0.1:3001;
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;
# No rate limiting on webhooks — Stripe IPs are trusted
# NestJS validates the Stripe signature
}
}
WebSocket-Proxying
Wenn Ihre Anwendung WebSockets (Socket.IO, NestJS WebSocket Gateway) verwendet, benötigt die Proxy-Konfiguration bestimmte Header:
# WebSocket upgrade handling
location /ws/ {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade"; # Capital U required
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# WebSocket connections can be long-lived
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
Ohne Upgrade- und Connection-Header schlägt der WebSocket-Handshake des Browsers mit einem 426 Upgrade Required- oder 101 Switching Protocols-Fehler fehl.
Direktes SSL (ohne Cloudflare)
Wenn Sie Cloudflare nicht verwenden, behandeln Sie die SSL-Beendigung direkt in Nginx:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name ecosire.com;
ssl_certificate /etc/letsencrypt/live/ecosire.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ecosire.com/privkey.pem;
# SSL hardening
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ... rest of server block
}
# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name ecosire.com www.ecosire.com;
return 301 https://ecosire.com$request_uri;
}
Cloudflare-spezifische Konfiguration
Hinter Cloudflare sieht Nginx nur die IPs von Cloudflare. So bewahren Sie echte Client-IPs:
# Real IP from Cloudflare — add this in http{} or at top of server{}
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
real_ip_header CF-Connecting-IP;
Außerdem: Niemals www.ecosire.com und ecosire.com in separate Nginx-Serverblöcke aufteilen, wenn Sie Cloudflare verwenden. Cloudflare übernimmt die WWW-Umleitung an seinem Rand. Wenn Sie einen www-Serverblock hinzufügen, der auf Nicht-www umleitet, und Cloudflare auch www umleitet, erhalten Sie eine Umleitungsschleife (ERR_TOO_MANY_REDIRECTS).
Protokollkonfiguration
# Custom log format with useful fields
log_format json_combined escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"cf_ip":"$http_cf_connecting_ip",'
'"method":"$request_method",'
'"uri":"$request_uri",'
'"status":$status,'
'"body_bytes":$body_bytes_sent,'
'"response_time":$request_time,'
'"referrer":"$http_referer",'
'"user_agent":"$http_user_agent"'
'}';
access_log /var/log/nginx/ecosire-access.log json_combined;
error_log /var/log/nginx/ecosire-error.log warn;
Testen Sie Ihre Konfiguration
# Test syntax before applying
nginx -t
# Reload without downtime
nginx -s reload
# Check which config file is active
nginx -T | grep "configuration file"
# Test a specific server block
curl -I https://ecosire.com
curl -I https://api.ecosire.com/api/health
# Check security headers
curl -I https://ecosire.com | grep -E "X-Frame|X-Content|Referrer|Content-Security"
Häufig gestellte Fragen
Soll ich Nginx oder Caddy für ein neues Projekt verwenden?
Caddy ist wesentlich einfacher zu konfigurieren – es verarbeitet Let's Encrypt SSL automatisch und verfügt standardmäßig über sinnvolle Standardeinstellungen. Nginx ist leistungsfähiger und verfügt über ein größeres Ökosystem an Modulen und Dokumentation. Für die meisten neuen Projekte ist Caddy der bessere Ausgangspunkt; Wechseln Sie zu Nginx, wenn Sie eine detaillierte Kontrolle über SSL, komplexes Upstream-Routing oder Nginx-spezifische Module benötigen. Bleiben Sie bei vorhandenen Linux-Servern, auf denen Nginx bereits installiert ist, bei Nginx.
Wie vermeide ich den doppelten limit_req_zone-Fehler?
Die limit_req_zone-Direktive muss auf der Kontextebene http{} erscheinen, nicht innerhalb von server{}-Blöcken. Stellen Sie in einer Turborepo-Monorepo-Bereitstellung, in der Sie mehrere Konfigurationsdateien einschließen, sicher, dass die Anweisung in allen enthaltenen Dateien nur einmal vorkommt. Wenn der Fehler angezeigt wird, prüfen Sie, ob sowohl conf.d/app.conf als auch ein sites-enabled/-Symlink auf dieselbe Datei verweisen.
Wie konfiguriere ich Nginx für Next.js ISR (Inkrementelle statische Regeneration)?
Next.js verarbeitet ISR intern – Nginx muss lediglich alle Anfragen an Next.js weiterleiten, ohne die Antworten zwischenzuspeichern. Fügen Sie keine Cache-Control-Header hinzu, die die ISR-Cache-Header von Next.js beeinträchtigen. Fügen Sie für statische Assets in /_next/static/ immutable-Cache-Header hinzu, da diese Dateien inhaltsgehashte Namen haben. Lassen Sie für alle anderen Routen Next.js die Cache-Header festlegen.
Warum sinkt mein SSL-Score, wenn Cloudflare aktiviert ist?
Wenn sich Cloudflare im Proxy-Modus befindet, testet SSL Labs das SSL von Cloudflare, nicht Ihres. Stellen Sie den SSL-Modus von Cloudflare auf „Vollständig (streng)“ ein, um sicherzustellen, dass Cloudflare Ihr Ursprungszertifikat validiert. Installieren Sie ein Cloudflare-Ursprungszertifikat auf Ihrem Server – es ist kostenlos und 15 Jahre gültig. Ihr SSL Labs-Score wird zum Cloudflare-Score (normalerweise A+), was tatsächlich eine Verbesserung gegenüber einem typischen selbstkonfigurierten Nginx-SSL-Setup darstellt.
Wie gehe ich mit mehreren Node.js-Apps auf demselben Server um?
Führen Sie jede App auf einem anderen Port aus (Next.js auf 3000, NestJS auf 3001, Docusaurus auf 3002 usw.) und fügen Sie einen Serverblock für jede Subdomäne in Ihrer Nginx-Konfiguration hinzu. Verwenden Sie PM2, um alle Node.js-Prozesse zu verwalten. Nginx leitet nach Subdomain (oder Pfadpräfix) an den richtigen Port weiter. Jeder Serverblock kann über eine eigene Konfiguration für Ratenbegrenzung, Caching und Sicherheitsheader verfügen.
Nächste Schritte
Eine Nginx-Produktionskonfiguration ist ein lebendiges Dokument – sie entwickelt sich weiter, wenn sich die Anforderungen Ihrer Anwendung ändern, sich Ihre Datenverkehrsmuster ändern und neue Best Practices für die Sicherheit entstehen. ECOSIRE führt Nginx in der Produktion aus und bedient mehrere Anwendungen, wobei es SSL-Terminierung, Ratenbegrenzung und Cloudflare-Integration über alle Domänen hinweg übernimmt.
Ganz gleich, ob Sie DevOps-Beratung, die Einrichtung einer Produktionsinfrastruktur oder einen vollständigen Entwurf einer Bereitstellungsarchitektur benötigen: [erkunden Sie unsere Dienste] (/services), um zu erfahren, wie wir Ihnen helfen können.
Geschrieben von
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
ECOSIRE
Erweitern Sie Ihr Geschäft mit ECOSIRE
Unternehmenslösungen in den Bereichen ERP, E-Commerce, KI, Analyse und Automatisierung.
Verwandte Artikel
KI-Betrugserkennung für E-Commerce: Schützen Sie Ihren Umsatz, ohne den Verkauf zu blockieren
Implementieren Sie eine KI-Betrugserkennung, die mehr als 95 % der betrügerischen Transaktionen erkennt und gleichzeitig die Falsch-Positiv-Rate unter 2 % hält. ML-Bewertung, Verhaltensanalyse und ROI-Leitfaden.
API-Ratenbegrenzung: Muster und Best Practices
Master-API-Ratenbegrenzung mit Token-Bucket, Schiebefenster und festen Zählermustern. Schützen Sie Ihr Backend mit NestJS Throttler, Redis und realen Konfigurationsbeispielen.
Cybersicherheitstrends 2026–2027: Zero Trust, KI-Bedrohungen und Verteidigung
Der definitive Leitfaden zu Cybersicherheitstrends für 2026–2027 – KI-gestützte Angriffe, Zero-Trust-Implementierung, Lieferkettensicherheit und Aufbau belastbarer Sicherheitsprogramme.
Mehr aus Performance & Scalability
Webhook-Debugging und -Überwachung: Der vollständige Leitfaden zur Fehlerbehebung
Beherrschen Sie das Webhook-Debugging mit diesem vollständigen Leitfaden, der Fehlermuster, Debugging-Tools, Wiederholungsstrategien, Überwachungs-Dashboards und Best Practices für die Sicherheit abdeckt.
k6-Lasttest: Führen Sie vor dem Start einen Stresstest für Ihre APIs durch
Master-K6-Lasttests für Node.js-APIs. Behandelt das Hochfahren virtueller Benutzer, Schwellenwerte, Szenarien, HTTP/2, WebSocket-Tests, Grafana-Dashboards und CI-Integrationsmuster.
Odoo Performance Tuning: PostgreSQL und Serveroptimierung
Expertenleitfaden zur Leistungsoptimierung von Odoo 19. Behandelt PostgreSQL-Konfiguration, Indizierung, Abfrageoptimierung, Nginx-Caching und Serverdimensionierung für Unternehmensbereitstellungen.
Odoo vs Acumatica: Cloud ERP für wachsende Unternehmen
Odoo vs. Acumatica im Vergleich für 2026: einzigartige Preismodelle, Skalierbarkeit, Fertigungstiefe und welches Cloud-ERP zu Ihrem Wachstumskurs passt.
Testen und Überwachen von KI-Agenten in der Produktion
Eine vollständige Anleitung zum Testen und Überwachen von KI-Agenten in Produktionsumgebungen. Behandelt Bewertungsrahmen, Beobachtbarkeit, Abweichungserkennung und Reaktion auf Vorfälle für OpenClaw-Bereitstellungen.
Compliance-Überwachungsagenten mit OpenClaw
Setzen Sie OpenClaw-KI-Agenten für eine kontinuierliche Compliance-Überwachung ein. Automatisieren Sie behördliche Prüfungen, die Durchsetzung von Richtlinien, die Erstellung von Audit-Trails und die Compliance-Berichterstellung.