f in x
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sistemi Operativi & Sicurezza

Nginx e Web Server Configuration: La Guida Pillar Definitiva per Produzione

[2026-06-17] Author: Ing. Calogero Bono

Se il tuo server web va in crash al primo picco di traffico, o se carichi le pagine con la sensazione di guardare un caricatore di grano, non è colpa del codice. È colpa di come il web server è configurato. Noi di Meteora Web abbiamo visto decine di progetti arrivare con Apache lento, PHP-FPM non ottimizzato e Nginx installato con i default. Risultato: tempi di risposta da incubo, risorse sprecate e clienti che se ne vanno. In questa pillar page ti portiamo tutto quello che serve per trasformare Nginx in un missile per traffico reale. Nessuna teoria, solo comandi e decisioni che puoi applicare oggi.

Perché Nginx è il punto di partenza per ogni applicazione moderna

Nginx non è solo un web server. È un reverse proxy, un load balancer, un acceleratore di contenuti statici e un gateway API, tutto in uno. La sua architettura basata su eventi asincroni lo rende più leggero e scalabile di Apache a parità di hardware. Noi lo usiamo come front-end per ogni progetto: che sia Laravel, WordPress o una SPA in Vue, Nginx sta davanti e gestisce il traffico.

Il vantaggio concreto: con Nginx puoi servire migliaia di connessioni simultanee con pochissima RAM. I worker process sono configurabili in base ai core della CPU, le code di keepalive riducono i three-way handshake, e la cache delle richieste statiche toglie carico a PHP o Python. In pratica: spendi meno di server e dai più performance.

Installazione e configurazione base

Su Ubuntu (la distribuzione che usiamo nella maggior parte dei server) ci bastano due comandi:

sudo apt update
sudo apt install nginx

Poi abilitiamo il servizio e controlliamo che giri:

sudo systemctl enable nginx
sudo systemctl start nginx
curl localhost

Se vedi il welcome page di Nginx, sei a posto. Da qui, la prima cosa che facciamo è creare un virtual host (server block) per il dominio.

Sponsored Protocol

Struttura dei virtual host

Su Nginx, ogni dominio ha il suo file in /etc/nginx/sites-available/, poi lo abiliti con un symlink in /etc/nginx/sites-enabled/. Ecco un esempio minimo per un sito statico:

server {
    listen 80;
    server_name tuodominio.it www.tuodominio.it;
    root /var/www/tuodominio;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

Dopo ogni modifica, testa la configurazione con sudo nginx -t e poi ricarica con sudo systemctl reload nginx. Sempre. Altrimenti rischi di buttare giù il server.

Nginx come reverse proxy

Qui Nginx dà il meglio. Tutte le applicazioni moderne (PHP-FPM, Node.js, Python) girano su porte interne (es. 9000, 3000, 8000). Nginx espone la porta 80/443 e inoltra le richieste. Così:

  • Proteggi l'applicazione da attacchi diretti
  • Centralizzi SSL, header di sicurezza e limiti
  • Metti la cache statica davanti a tutto

Reverse proxy per PHP-FPM (WordPress, Laravel)

server {
    listen 80;
    server_name mio-sito.it;
    root /var/www/mio-sito/public;
    index index.php;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    location ~ /\.ht {
        deny all;
    }
}

Nota il socket unix:: più veloce della porta TCP. Su server condivisi o container, usa TCP (127.0.0.1:9000).

Reverse proxy per Node.js (Express, Nuxt, Next)

server {
    listen 80;
    server_name api.mio-sito.it;
    location / {
        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_cache_bypass $http_upgrade;
    }
}

Il passaggio proxy_http_version 1.1 con gli header di upgrade è fondamentale per le WebSocket. Senza, le connessioni real-time muoiono.

Sponsored Protocol

SSL/TLS con Let's Encrypt e rinnovo automatico

Noi di Meteora Web rifiutiamo i certificati a pagamento da quando Let's Encrypt ha reso il TLS gratuito e automatizzato. La configurazione è un sudo apt install certbot python3-certbot-nginx e poi:

sudo certbot --nginx -d tuodominio.it -d www.tuodominio.it

Certbot modifica automaticamente i server block e imposta il redirect HTTP→HTTPS. Poi abilitiamo il rinnovo automatico con un timer systemd:

sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

Una volta che un cliente ci ha chiamato in emergenza perché il certificato era scaduto. Il timer non era partito. Da allora controlliamo sempre: sudo systemctl list-timers | grep certbot. Un minuto che risparmia settimane di down.

Configurazione TLS robusta

Aggiungi nel blocchetto server che ascolta sulla 443:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

Niente TLSv1.0 e 1.1: sono deprecati. Usa solo suite di cifratura moderne. Se vuoi testare la sicurezza del tuo dominio, usa SSL Labs.

Performance tuning: worker, cache e keepalive

I default di Nginx sono pensati per un server condiviso con risorse minime. Se hai un VPS con 2 core e 4 GB, puoi spingere molto di più.

Worker process e connessioni

worker_processes auto;
events {
    worker_connections 1024;
}

auto imposta il numero di worker pari ai core CPU. Poi alziamo worker_connections a 1024 (default 512). Il prodotto worker_processes * worker_connections ti dice quante connessioni simultanee puoi gestire.

Sponsored Protocol

Keepalive e buffer

http {
    keepalive_timeout 65;
    keepalive_requests 100;
    client_body_buffer_size 128k;
    client_max_body_size 10m;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
}

sendfile riduce il copying dei buffer. tcp_nopush e tcp_nodelay ottimizzano la trasmissione. Una nota: client_max_body_size va alzato se carichi file via upload (es. 50m per form con documenti).

Cache statica delle richieste

Per file statici (CSS, JS, immagini) puoi settare la cache nel browser e sul server:

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}

Attenzione: non usare immutable su risorse che cambi spesso (es. JS bundle con hash). In quel caso, max-age=31536000 e immutable vanno bene perché il nome file cambia.

Load balancing con Nginx

Quando un'applicazione scala, serve distribuire il carico su più server backend. Nginx lo fa nativamente con il modulo upstream.

upstream backend {
    server 10.0.0.1:3000 weight=3;
    server 10.0.0.2:3000;
    server 10.0.0.3:3000 backup;
}
server {
    listen 80;
    server_name loadbalanced.it;
    location / {
        proxy_pass http://backend;
    }
}
  • Round Robin: default, distribuisce in ordine
  • Least Connections: least_conn; all'interno del blocco upstream
  • IP Hash: ip_hash; per sessioni sticky (utile per carrelli senza Redis)

Per servizi più complessi (API Gateway con autenticazione, routing basato su path) o un confronto con strumenti come Kong e Traefik, leggi il nostro articolo su API Gateway: Kong, Traefik e AWS.

Security headers e protezione base

Purtroppo la sicurezza nelle PMI italiane è sistematicamente sottovalutata. Noi di Meteora Web lo vediamo ogni giorno. Ecco gli header che mettiamo in ogni virtual host:

Sponsored Protocol

add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy strict-origin-when-cross-origin;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()";

Block di IP dannosi con deny all; in location dedicate, o con un modulo WAF come ModSecurity (lo usiamo per clienti con traffico critico).

Rate limiting per proteggere le API

Le API pubbliche vanno limitate per evitare abusi:

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    server {
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend;
        }
    }
}

Qui: massimo 10 richieste al secondo per IP, con un burst di 20 che vengono servite subito (nodelay). Se superi, 429 Too Many Requests.

Nginx con Docker

In molti progetti usiamo Docker. Nginx diventa il gateway del cluster di container. Ecco un esempio di docker-compose.yml:

version: '3'
services:
  nginx:
    image: nginx:stable-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - php
      - node
  php:
    image: php:8.3-fpm-alpine
    volumes:
      - ./html:/usr/share/nginx/html

La configurazione Nginx si allinea a quella vista sopra, con proxy_pass ai servizi Docker interni.

Access log e error log: parsing e monitoring

Una configurazione senza log è come un aereo senza strumenti. Noi impostiamo sempre formati personalizzati:

http {
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" $request_time';
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
}

Il $request_time è fondamentale per monitorare le performance. Lo passiamo a un tool come Grafana (vedi la nostra guida a Grafana) per alert su latenze anomale.

Sponsored Protocol

Nginx vs Apache vs Caddy

Dopo 8 anni di progetti, possiamo dare un parere netto:

  • Apache: ancora utile se hai bisogno di moduli PHP embedded (mod_php), ma perde in performance e gestione concorrenza. Oggi lo sconsigliamo per nuovi progetti.
  • Caddy: interessante per la facilità di configurazione (HTTPS automatico, file Caddyfile semplice). Ma la sua maturità e comunità sono inferiori. Per progetti piccolissimi va bene.
  • Nginx: il punto di equilibrio tra flessibilità, performance e comunità. Ha un ecosistema enorme e si integra con tutto. È la nostra scelta di default.

Se vuoi approfondire le configurazioni per microservizi, abbiamo un articolo dedicato a API Gateway deployment for microservices.

In sintesi – cosa fare adesso

  1. Installa Nginx su un server di test e crea un virtual host con SSL gratuito.
  2. Ripeti i passaggi di reverse proxy per la tua applicazione (PHP, Node, Python).
  3. Applica i tuning di performance (worker, keepalive, cache statica).
  4. Configura rate limiting e security headers su almeno un endpoint pubblico.
  5. Imposta un monitoring con access log e verifica con nginx -t dopo ogni modifica.

Noi di Meteora Web usiamo queste stesse tecniche ogni giorno per clienti in tutta Italia. Se vuoi che diamo un'occhiata al tuo server, contattaci. Il tuo sito merita un web server che non crolli al primo colpo.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()