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.