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 Research and Development Team
Entwicklung von Enterprise-Digitalprodukten bei ECOSIRE. Einblicke in Odoo-Integrationen, E-Commerce-Automatisierung und KI-gestützte Geschäftslösungen.
Verwandte Artikel
API Rate Limiting: Patterns and Best Practices
Master API rate limiting with token bucket, sliding window, and fixed counter patterns. Protect your backend with NestJS throttler, Redis, and real-world configuration examples.
Cybersecurity Trends 2026-2027: Zero Trust, AI Threats, and Defense
The definitive guide to cybersecurity trends for 2026-2027—AI-powered attacks, zero trust implementation, supply chain security, and building resilient security programs.
Financial Services ERP Implementation: Regulatory and Security Requirements
A practitioner's guide to implementing ERP in regulated financial services firms, covering security controls, compliance validation, data governance, and phased rollout.
Mehr aus Performance & Scalability
k6 Load Testing: Stress-Test Your APIs Before Launch
Master k6 load testing for Node.js APIs. Covers virtual user ramp-ups, thresholds, scenarios, HTTP/2, WebSocket testing, Grafana dashboards, and CI integration patterns.
Odoo Performance Tuning: PostgreSQL and Server Optimization
Expert guide to Odoo 19 performance tuning. Covers PostgreSQL configuration, indexing, query optimization, Nginx caching, and server sizing for enterprise deployments.
Odoo vs Acumatica: Cloud ERP for Growing Businesses
Odoo vs Acumatica compared for 2026: unique pricing models, scalability, manufacturing depth, and which cloud ERP fits your growth trajectory.
Testing and Monitoring AI Agents in Production
A complete guide to testing and monitoring AI agents in production environments. Covers evaluation frameworks, observability, drift detection, and incident response for OpenClaw deployments.
Compliance Monitoring Agents with OpenClaw
Deploy OpenClaw AI agents for continuous compliance monitoring. Automate regulatory checks, policy enforcement, audit trail generation, and compliance reporting.
Optimizing AI Agent Costs: Token Usage and Caching
Practical strategies for reducing AI agent operational costs through token optimization, caching, model routing, and usage monitoring. Real savings from production OpenClaw deployments.