Home Chi Sono
Servizi
WordPress Sviluppo Web Server & Hosting Assistenza Tecnica Windows Android
Blog
Tutti gli Articoli WordPress Hosting Plesk Assistenza Computer Windows Android A.I.
Contatti

Come Configuro un Reverse Proxy Nginx per Gestire Più Siti su un Solo Server: Guida Pratica

Come Configuro un Reverse Proxy Nginx per Gestire Più Siti su un Solo Server: Guida Pratica

Se gestite più siti web o applicazioni su un singolo server, prima o poi vi troverete a dover affrontare un problema fondamentale: come instradare correttamente il traffico in ingresso verso il backend giusto? Nella mia esperienza di system administrator, la risposta è quasi sempre la stessa: configurare Nginx come reverse proxy.

Nel corso degli anni ho configurato decine di server con più domini serviti dallo stesso indirizzo IP, e il reverse proxy Nginx si è sempre dimostrato la soluzione più affidabile, performante e scalabile. In questa guida vi mostro esattamente come faccio, partendo dall’installazione fino alla messa in sicurezza completa, con configurazioni reali che uso quotidianamente.

Se avete già letto il mio articolo su come abilito la compressione Brotli su Nginx, sapete che considero Nginx uno strumento essenziale nel mio toolkit. Oggi approfondiamo un aspetto ancora più critico: il reverse proxy per più siti.

Cos’è un Reverse Proxy Nginx e Perché Usarlo

Un reverse proxy è un server che si interpone tra i client e i backend, ricevendo le richieste in ingresso e inoltrandole al servizio appropriato. A differenza di un forward proxy, che nasconde i client ai server, il reverse proxy nasconde l’infrastruttura interna ai visitatori.

Nginx è la scelta più popolare per i deployment come reverse proxy grazie alla sua architettura event-driven, al basso consumo di memoria e alla capacità di gestire migliaia di connessioni simultanee in modo efficiente. Un singolo worker process di Nginx può gestire migliaia di connessioni concorrenti con un overhead minimo di risorse.

I vantaggi principali che ottengo utilizzando Nginx come reverse proxy sono:

  • Load balancing — distribuire le richieste su più backend
  • SSL termination — gestire la crittografia TLS in un unico punto
  • Caching — servire risposte ripetute senza colpire il backend
  • Sicurezza — nascondere l’infrastruttura interna e filtrare richieste malevole
  • Compressione — ridurre la banda con gzip/Brotli prima dell’invio al client

Prerequisiti e Installazione di Nginx

Prima di partire, assicuratevi di avere:

  • Un server Linux (Ubuntu 22.04/24.04 o Debian 12) con accesso root
  • Almeno due domini o sottodomini puntati all’IP del server
  • Le applicazioni o i siti già in esecuzione su porte interne diverse

Installazione di Nginx su Ubuntu/Debian

Aggiorno i pacchetti e installo Nginx:

sudo apt update && sudo apt upgrade -y
sudo apt install nginx -y

Verifico che il servizio sia attivo:

sudo systemctl status nginx
sudo systemctl enable nginx

Installazione su RHEL/Rocky Linux/AlmaLinux

Per le distribuzioni RHEL-based il procedimento è leggermente diverso:

sudo dnf install epel-release -y
sudo dnf install nginx -y
sudo systemctl start nginx && sudo systemctl enable nginx

Configurare il Reverse Proxy Nginx per Più Siti: Server Block

Il cuore della configurazione è il concetto di server block (l’equivalente dei Virtual Host di Apache). Ogni server block rappresenta un sito o un’applicazione separata e definisce come Nginx gestisce le richieste in ingresso per quel dominio specifico.

Creo un file di configurazione separato per ogni sito nella directory /etc/nginx/sites-available/:

Primo sito: sito1.example.com

# /etc/nginx/sites-available/sito1.example.com
server {
    listen 80;
    server_name sito1.example.com www.sito1.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Secondo sito: sito2.example.com

# /etc/nginx/sites-available/sito2.example.com
server {
    listen 80;
    server_name sito2.example.com www.sito2.example.com;

    location / {
        proxy_pass http://127.0.0.1:4000;
        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;
    }
}

La direttiva proxy_pass è la base della configurazione del reverse proxy Nginx: dice a Nginx dove inoltrare le richieste in ingresso. Ogni sito gira su una porta differente (3000, 4000, ecc.) e Nginx instrada il traffico in base al dominio.

Attivazione e Test della Configurazione

Attivo i siti creando i symlink e testo la configurazione:

# Creo i symlink
sudo ln -s /etc/nginx/sites-available/sito1.example.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/sito2.example.com /etc/nginx/sites-enabled/

# Testo la configurazione (FONDAMENTALE prima di ogni reload)
sudo nginx -t

# Se il test è ok, ricarico senza downtime
sudo systemctl reload nginx

Consiglio importante: testate sempre la configurazione con nginx -t prima di ricaricare. All’inizio della mia carriera ho causato più di un downtime dimenticando questo passaggio!

Gli Header Essenziali per il Reverse Proxy

Quando Nginx fa da reverse proxy, le applicazioni backend perdono informazioni critiche sul client originale. Per default, Nginx modifica gli header “Host” e “Connection” nelle richieste proxiate ed elimina quelli con valori vuoti.

Ecco gli header che configuro sempre:

  • Host $host — passa il dominio originale richiesto dal client
  • X-Real-IP $remote_addr — l’IP reale del visitatore
  • X-Forwarded-For $proxy_add_x_forwarded_for — mantiene la catena completa di proxy attraversati
  • X-Forwarded-Proto $scheme — indica se la richiesta originale era HTTP o HTTPS
  • X-Forwarded-Host $host — il dominio originale della richiesta
  • X-Forwarded-Port $server_port — la porta della richiesta originale

Senza questi header, il backend vedrà tutte le richieste come provenienti da 127.0.0.1 — un problema serio per i log, la sicurezza e la corretta generazione degli URL.

Abilitare HTTPS con Let’s Encrypt e Certbot

Un reverse proxy senza HTTPS è un rischio inaccettabile. Nella mia configurazione abilito sempre la SSL termination su Nginx, così i backend interni comunicano in HTTP sulla rete locale, mentre tutto il traffico esterno è cifrato.

# Installo Certbot con il plugin Nginx
sudo apt install certbot python3-certbot-nginx -y

# Genero i certificati per entrambi i siti
sudo certbot --nginx -d sito1.example.com -d www.sito1.example.com
sudo certbot --nginx -d sito2.example.com -d www.sito2.example.com

Certbot modificherà automaticamente i server block aggiungendo le direttive SSL. Se avete bisogno di certificati wildcard, ho spiegato la procedura completa nel mio articolo su Let’s Encrypt Wildcard con validazione DNS-01.

Hardening TLS: la mia configurazione

Dopo l’installazione del certificato, applico sempre un hardening TLS aggiuntivo. Nascondere informazioni come la versione di Nginx, PHP e del sistema operativo è fondamentale per ridurre la superficie d’attacco:

# Dentro il server block HTTPS
server {
    listen 443 ssl http2;
    server_name sito1.example.com;

    ssl_certificate /etc/letsencrypt/live/sito1.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sito1.example.com/privkey.pem;

    # Nascondo la versione di Nginx
    server_tokens off;

    # Protocolli TLS sicuri
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;

    # Session caching per performance
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # Security headers
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options DENY;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Se volete approfondire la sicurezza del server, vi consiglio di leggere anche come configuro Fail2Ban per bloccare gli attacchi e come gestisco la protezione WordPress da attacchi brute force.

Rate Limiting e Protezione DoS

Una delle prime cose che configuro su ogni reverse proxy è il rate limiting, per proteggere i backend da attacchi DoS e da bot aggressivi:

# Nel blocco http di nginx.conf
http {
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

    # ...altre configurazioni...
}

# Nel server block specifico
server {
    location / {
        limit_req zone=general burst=20 nodelay;
        proxy_pass http://127.0.0.1:3000;
    }

    location /wp-login.php {
        limit_req zone=login burst=3 nodelay;
        proxy_pass http://127.0.0.1:3000;
    }
}

Con questa configurazione limito a 10 richieste/secondo per IP sull’intero sito e a 1 richiesta/secondo sulle pagine di login — una misura semplice ma efficacissima.

Load Balancing con Upstream Block

Quando i siti crescono, spesso serve distribuire il carico su più backend. Nginx brilla particolarmente nelle architetture ad alta disponibilità grazie ai blocchi upstream:

upstream backend_sito1 {
    server 192.168.1.10:3000;
    server 192.168.1.11:3000;
    server 192.168.1.12:3000 backup;
}

server {
    listen 443 ssl http2;
    server_name sito1.example.com;

    location / {
        proxy_pass http://backend_sito1;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Nota critica: quando usate keepalive con gli upstream, dovete impostare proxy_http_version 1.1 e azzerare l’header Connection. HTTP/1.0 chiude le connessioni di default, vanificando completamente il keepalive.

Buffering e Ottimizzazione delle Performance

Nginx bufferizza le risposte dai backend prima di inviarle ai client. Questo libera rapidamente i server backend mentre Nginx gestisce le connessioni lente dei client. Nella mia esperienza, un tuning corretto del buffering fa una differenza enorme:

location / {
    proxy_pass http://127.0.0.1:3000;

    # Buffering ottimizzato
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;

    # Timeout ragionevoli
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 90s;
}

Per ottimizzare ulteriormente le performance, vi consiglio di combinare queste impostazioni con la configurazione di PHP-FPM e OPcache e di attivare anche HTTP/3 QUIC dove possibile.

Monitoraggio e Logging del Reverse Proxy

Configuro sempre log separati per ogni sito proxiato, così posso diagnosticare rapidamente i problemi:

server {
    server_name sito1.example.com;

    access_log /var/log/nginx/sito1.access.log;
    error_log /var/log/nginx/sito1.error.log;

    # ...resto della configurazione...
}

Per un monitoraggio più avanzato, nel mio articolo su Grafana e Prometheus per il monitoraggio server spiego come creare dashboard in tempo reale che includono le metriche di Nginx.

Troubleshooting: Errori Comuni e Come li Risolvo

Errore 502 Bad Gateway

È l’errore più frequente. Significa che Nginx ha ricevuto la richiesta ma il backend ha risposto in modo invalido o non ha risposto affatto. Le cause più comuni nella mia esperienza:

  1. Il backend non è in esecuzione — verifico con systemctl status o docker ps
  2. La proxy_pass punta alla porta sbagliata
  3. Il backend ascolta su 127.0.0.1 ma Nginx lo cerca su 0.0.0.0 (o viceversa)
  4. Problemi con IPv6 — a volte un modprobe ipv6 risolve tutto

Errore 504 Gateway Timeout

Il backend è troppo lento. Aumento i timeout nella configurazione del proxy e verifico le risorse del server.

Errore 403 Forbidden

Spesso un problema di permessi sui file o di configurazione del server block. Verifico che la direttiva server_name corrisponda esattamente al dominio richiesto.

Reverse Proxy Nginx con Docker

Se utilizzate Docker per i vostri servizi, il reverse proxy diventa ancora più potente. Ogni container gira su una porta interna e Nginx instrada il traffico:

# Esempio per due container Docker
server {
    listen 443 ssl http2;
    server_name app1.example.com;

    location / {
        proxy_pass http://172.17.0.2:8080;
        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;
    }
}

server {
    listen 443 ssl http2;
    server_name app2.example.com;

    location / {
        proxy_pass http://172.17.0.3:9090;
        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;
    }
}

In questo scenario, nessun container ha bisogno di esporre le porte direttamente al mondo esterno: tutta la comunicazione passa attraverso il reverse proxy, che gestisce anche SSL e sicurezza.

FAQ

Quanti siti posso gestire con un solo reverse proxy Nginx?

Non c’è un limite pratico al numero di server block che potete configurare. Nginx è estremamente efficiente e nella mia esperienza gestisco tranquillamente 20-30 siti sullo stesso reverse proxy senza problemi. Il collo di bottiglia sarà la RAM e la CPU del server, non Nginx.

Il reverse proxy Nginx rallenta il sito?

No, anzi. Nginx aggiunge un overhead trascurabile (millisecondi) e nella pratica migliora le performance grazie al buffering, alla compressione e al caching. Il backend viene liberato più rapidamente perché Nginx gestisce le connessioni lente dei client.

Posso usare Nginx come reverse proxy davanti ad Apache?

Assolutamente sì, ed è una configurazione molto comune. Apache gestisce l’elaborazione PHP e Nginx fa da frontend per SSL termination, caching e servire i file statici. Basta che Apache ascolti su una porta interna diversa dalla 80 (ad esempio 8080).

Come gestisco i certificati SSL per molti domini?

Uso Certbot con il plugin Nginx per generare certificati Let’s Encrypt individuali per ogni dominio. Per i sottodomini uso certificati wildcard con validazione DNS-01. Il rinnovo automatico è gestito da un cronjob di Certbot. Se volete approfondire, leggete la mia guida sui cronjob per automazione e manutenzione.

Qual è la differenza tra reverse proxy e load balancer?

Un reverse proxy instrada le richieste a uno o più backend, gestendo SSL, caching e sicurezza. Un load balancer è una funzione specifica del reverse proxy che distribuisce il carico tra più server identici. Nginx può fare entrambe le cose contemporaneamente tramite i blocchi upstream.

Conclusione

Configurare un reverse proxy Nginx per gestire più siti su un solo server è una competenza fondamentale per ogni sysadmin. Come avete visto, il processo non è complicato ma richiede attenzione ai dettagli: header corretti, SSL hardening, rate limiting e monitoraggio costante.

Nella mia esperienza quotidiana, questa architettura mi permette di gestire decine di siti e applicazioni in modo efficiente, sicuro e facilmente manutenibile. Ogni volta che aggiungo un nuovo sito, mi basta creare un nuovo server block, generare il certificato SSL e ricaricare Nginx — il tutto senza alcun downtime.

Se state pensando di migrare la vostra infrastruttura, date un’occhiata anche al mio articolo su come migro un sito su nuovo hosting senza downtime e a quello sulle alternative open source a Plesk per un pannello di controllo gratuito.

Avete domande o volete condividere la vostra configurazione? Scrivetemi nei commenti!

Share: