eduardweb.
Apache & NginxIntermediar#nextjs#nginx#production

Nginx reverse proxy pentru Next.js — config bulletproof pentru producție

De Diana Oprea, 21 apr. 2026 · 5 vizualizări · 3 like-uri

Postat acum 1 zi

Folosesc același template de nginx.conf pe toate VPS-urile cu Next.js. Iată ce face și de ce:

Struct generală

upstream nextjs_upstream {
  server 127.0.0.1:3000;
  keepalive 64;
}

server {
  listen 80;
  server_name tine.ro www.tine.ro;
  return 301 https://tine.ro$request_uri;
}

server {
  listen 443 ssl http2;
  server_name tine.ro;

  ssl_certificate     /etc/letsencrypt/live/tine.ro/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/tine.ro/privkey.pem;
  # ssl best practices: ...

  # ... rest aici
}

1. Gzip (sau brotli dacă ai modul instalat)

gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_min_length 1000;

Reducere de bandwidth 60-80% pe JS/CSS. Brotli suplimentar ~15%.

2. Cache pentru _next/static

Fișierele din _next/static au hash în nume → le poți cache-ui forever:

location /_next/static {
  proxy_cache_valid 365d;
  add_header Cache-Control "public, max-age=31536000, immutable";
  proxy_pass http://nextjs_upstream;
}

Visitor-ul repetat nu mai re-descarcă JS-ul.

3. Cache pentru imagini

location ~* \.(jpg|jpeg|png|webp|avif|svg|ico)$ {
  expires 30d;
  add_header Cache-Control "public, max-age=2592000";
  proxy_pass http://nextjs_upstream;
}

4. Rate limiting

Protecție anti-bot pe endpoint-urile publice:

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

location /api/ {
  limit_req zone=api burst=20 nodelay;
  proxy_pass http://nextjs_upstream;
}

Boții primesc 503 după 10 req/s, user-ii reali nu observă.

5. Websocket support

Dacă ai realtime (Socket.IO, Pusher alternative):

location /ws {
  proxy_pass http://nextjs_upstream;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
  proxy_read_timeout 86400;
}

6. Headers de securitate

add_header X-Frame-Options "SAMEORIGIN" 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;

7. SSL modern

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;

A+ pe SSL Labs cu setările astea.

Ultim tip — logs structured

Default-ul nginx e greu de parsat. Schimbi cu JSON:

log_format json escape=json '{"time":"$time_iso8601","ip":"$remote_addr","method":"$request_method","url":"$request_uri","status":$status,"bytes":$body_bytes_sent,"rt":$request_time}';
access_log /var/log/nginx/tine.log json;

Acum poți pipe-ui direct în Loki / Elasticsearch / Datadog.

Test final

curl -I https://tine.ro → 200 + headere OK
curl -I https://tine.ro/_next/static/... → Cache-Control: immutable
ab -n 1000 -c 50 https://tine.ro/api/test → limit-uri active

Template-ul integral ajunge la ~120 linii. Îl pun pe fiecare proiect nou în 2 minute.

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.