Cheatsheet Nginx: comandi, snippet di configurazione e correzione errori
Riferimento rapido per le operazioni quotidiane di Nginx su Debian 12 e Ubuntu 24.04. Organizzato per attività per trovare rapidamente ciò che serve. Per una guida completa, vedi Amministrazione di Nginx su un VPS.
Come gestisco il servizio Nginx?
Usa systemctl per controllare Nginx tramite systemd, oppure invia segnali direttamente con nginx -s. Systemctl è lo standard sui sistemi Debian e Ubuntu moderni. I comandi nativi nginx -s comunicano direttamente con il processo master tramite il suo file PID. Entrambi funzionano. Systemctl è migliore per l'automazione e la persistenza all'avvio.
Mappatura segnali e comandi
| Azione | Comando systemctl | Equivalente nginx -s | Segnale Unix | Effetto sui worker |
|---|---|---|---|---|
| Avviare | sudo systemctl start nginx |
(non applicabile) | - | Il master si avvia e genera i worker |
| Arrestare (graceful) | sudo systemctl stop nginx |
sudo nginx -s quit |
SIGQUIT | I worker completano le richieste in corso, poi si arrestano |
| Arrestare (immediato) | sudo systemctl kill nginx |
sudo nginx -s stop |
SIGTERM | I worker interrompono le connessioni e si arrestano |
| Ricaricare la config | sudo systemctl reload nginx |
sudo nginx -s reload |
SIGHUP | Nuovi worker partono con la nuova config. I vecchi completano le richieste, poi si arrestano. Nessuna connessione persa. |
| Riaprire i log | (non integrato) | sudo nginx -s reopen |
SIGUSR1 | I worker riaprono i descrittori dei file di log. Da usare dopo la rotazione dei log. |
| Abilitare all'avvio + avviare ora | sudo systemctl enable --now nginx |
(non applicabile) | - | Crea il link simbolico per l'avvio, avvia immediatamente |
| Disabilitare + arrestare | sudo systemctl disable --now nginx |
(non applicabile) | - | Rimuove il link simbolico dell'avvio, arresta immediatamente |
enable --now fa sopravvivere Nginx ai riavvii e lo avvia immediatamente. Preferisci sempre questo comando a un semplice start.
Reload vs restart
reload invia SIGHUP. Il processo master legge la nuova config, genera nuovi worker e lascia che i vecchi completino le connessioni attive. Zero downtime.
restart invia SIGTERM (arresto), poi riavvia da zero. Tutte le connessioni attive vengono interrotte. Usa restart solo per cambiare le porte di ascolto, caricare nuovi moduli o aggiornare il binario Nginx.
Testa sempre prima di ricaricare:
sudo nginx -t && sudo systemctl reload nginx
Se nginx -t fallisce, il ricaricamento non viene eseguito. La config in produzione resta intatta.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Dopo il ricaricamento:
sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-03-20 10:15:32 UTC; 2s ago
L'enabled nella riga Loaded significa che si avvierà al boot. Installare Nginx su Debian 12 e Ubuntu 24.04 dal repository ufficiale
Come testo e verifico la configurazione Nginx?
Esegui nginx -t per validare la sintassi senza toccare il server in esecuzione. Esegui nginx -T per validare e visualizzare l'intera config analizzata su stdout. Esegui nginx -V per vedere i moduli e i flag di compilazione.
| Comando | Scopo |
|---|---|
sudo nginx -t |
Testare la sintassi della config, verificare che i file referenziati esistano |
sudo nginx -t -q |
Stesso test, sopprime l'output non-errore (utile negli script) |
sudo nginx -T |
Test + dump della config completa analizzata su stdout |
sudo nginx -V |
Mostra versione, compilatore, argomenti di configure, moduli integrati |
sudo nginx -v |
Mostra solo il numero di versione |
Visualizzare e cercare nella config attiva
sudo nginx -T 2>/dev/null | grep -A5 "server_name example.com"
Questo comando mostra la config completa (tutti i file inclusi uniti), poi filtra un blocco server specifico. Più veloce che aprire i file manualmente quando hai decine di include.
Verificare i moduli compilati
sudo nginx -V 2>&1 | tr ' ' '\n' | grep module
--with-http_ssl_module
--with-http_v2_module
--with-http_realip_module
--with-http_gzip_static_module
--with-http_stub_status_module
Non puoi usare una direttiva se il suo modulo non è compilato. È la prima cosa da controllare quando una direttiva causa l'errore "unknown directive".
Dove si trovano i file di configurazione e i log di Nginx?
Su Debian 12 e Ubuntu 24.04, il gestore dei pacchetti installa tutto sotto /etc/nginx/. I log vanno in /var/log/nginx/. Ecco la struttura completa.
| Percorso | Scopo |
|---|---|
/etc/nginx/nginx.conf |
Config principale. Imposta il numero di worker, events, blocco http, includes |
/etc/nginx/sites-available/ |
File dei blocchi server (disponibili ma non necessariamente attivi) |
/etc/nginx/sites-enabled/ |
Link simbolici a sites-available. Nginx carica questi. |
/etc/nginx/conf.d/ |
Frammenti di config aggiuntivi. Caricati dall'include predefinito in nginx.conf |
/etc/nginx/snippets/ |
Snippet di config riutilizzabili (parametri SSL, header di sicurezza) |
/etc/nginx/mime.types |
Mappatura dei tipi MIME |
/var/log/nginx/access.log |
Log delle richieste |
/var/log/nginx/error.log |
Log degli errori |
/run/nginx.pid |
File PID del processo master |
Per abilitare un sito:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Per disabilitare un sito:
sudo rm /etc/nginx/sites-enabled/example.com
sudo nginx -t && sudo systemctl reload nginx
Per un approfondimento sulla struttura delle directory, vedi Struttura dei file di configurazione Nginx.
Quali sono gli snippet di configurazione Nginx più comuni?
Ogni snippet qui sotto è un esempio minimale funzionante. Copia, adatta i valori, testa con nginx -t, ricarica. Per guide complete su ogni argomento, segui i link interni.
Come configuro un blocco server di base?
Un blocco server (virtual host) associa un dominio a una document root. Inserisci questo in /etc/nginx/sites-available/example.com.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
server_tokens off;
location / {
try_files $uri $uri/ =404;
}
}
server_tokens off nasconde la versione di Nginx dagli header di risposta. Rivelare la versione aiuta gli attaccanti a puntare vulnerabilità note.
Crea il link simbolico in sites-enabled e ricarica. Nginx Server Block: ospita più domini su un VPS
Come reindirizzo HTTP verso HTTPS?
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
return 301 è più veloce di rewrite per i redirect di URL completi. Nginx elabora return prima di toccare il filesystem.
Come configuro Nginx come reverse proxy?
Inoltra le richieste a un backend sulla porta 3000. Inserisci questo nel blocco server HTTPS.
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;
}
Lo slash finale conta. proxy_pass http://127.0.0.1:3000; (senza slash finale) passa l'URI originale completo. proxy_pass http://127.0.0.1:3000/; (con slash finale) rimuove il prefisso del location. Questa è la causa di molte configurazioni proxy non funzionanti.
Come configurare Nginx come reverse proxy
Come abilito la compressione gzip?
Aggiungi al blocco http {} in /etc/nginx/nginx.conf o a un file snippet:
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_min_length 1024;
gzip_comp_level 5;
gzip_types
text/plain
text/css
text/javascript
application/json
application/javascript
application/xml
image/svg+xml;
gzip_min_length 1024 salta i file sotto 1 KB. Comprimere file piccoli aggiunge overhead CPU senza una riduzione di dimensione significativa. gzip_comp_level 5 offre un buon equilibrio tra rapporto di compressione e costo CPU. Oltre 6, i benefici diminuiscono.
Ottimizzazione delle prestazioni di Nginx su un VPS
Come aggiungo il rate limiting?
Definisci una zona nel blocco http {}, poi applicala in un blocco location o server.
# In http {} block
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# In server or location block
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://127.0.0.1:8080;
}
$binary_remote_addr usa 4 byte per indirizzo IPv4. Una zona da 10 MB contiene circa 160.000 indirizzi. burst=20 consente picchi brevi. nodelay serve le richieste in burst immediatamente anziché metterle in coda.
Rate Limiting con Nginx e protezione DDoS
Come faccio il proxy delle connessioni WebSocket?
location /ws/ {
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_read_timeout 86400s;
}
proxy_http_version 1.1 è obbligatorio. HTTP/1.0 non supporta l'header Upgrade. proxy_read_timeout 86400s mantiene le connessioni WebSocket inattive aperte per 24 ore anziché i 60 secondi predefiniti.
Come configuro pagine di errore personalizzate?
server {
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /404.html {
root /var/www/errors;
internal;
}
location = /50x.html {
root /var/www/errors;
internal;
}
}
La direttiva internal impedisce l'accesso diretto alle URL delle pagine di errore. Senza di essa, gli utenti potrebbero navigare direttamente a /404.html.
Come aggiungo header di sicurezza?
Crea /etc/nginx/snippets/security-headers.conf:
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;
Includilo in qualsiasi blocco server:
include snippets/security-headers.conf;
Il parametro always aggiunge gli header anche nelle risposte di errore (4xx, 5xx). Senza di esso, Nginx li aggiunge solo sulle 2xx/3xx. Hardening della sicurezza di Nginx su Ubuntu e Debian
Blocco server TLS minimale
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
server_tokens off;
# ... location blocks
}
Non abilitare TLSv1 o TLSv1.1. Entrambi hanno vulnerabilità note e sono rifiutati dai browser moderni. Configurare Let's Encrypt SSL/TLS per Nginx su Debian 12 e Ubuntu 24.04
Come leggo e faccio il debug dei log Nginx?
Nginx scrive due log per impostazione predefinita: access.log per ogni richiesta e error.log per i problemi. Entrambi si trovano in /var/log/nginx/.
Seguire i log in tempo reale
sudo tail -f /var/log/nginx/error.log
Oppure tramite journald:
journalctl -u nginx -f
Livelli di severità del log degli errori
La direttiva error_log accetta un livello. Dal più al meno dettagliato:
debug > info > notice > warn > error > crit > alert > emerg
Il livello predefinito è error. Per abilitare temporaneamente il log di debug:
error_log /var/log/nginx/error.log debug;
Ricarica Nginx. Il log di debug è estremamente dettagliato. Disabilitalo dopo aver diagnosticato il problema, altrimenti riempirà il disco.
Formato JSON per il log di accesso
I log strutturati sono più facili da analizzare con strumenti come jq, Loki o OpenObserve.
log_format json_combined escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"method":"$request_method",'
'"uri":"$request_uri",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time",'
'"http_user_agent":"$http_user_agent"'
'}';
access_log /var/log/nginx/access.log json_combined;
Kit di strumenti per il debug
| Comando | Cosa fa |
|---|---|
curl -I https://example.com |
Mostra solo gli header di risposta. Controlla codice di stato, versione del server, header di cache. |
curl -v https://example.com 2>&1 | head -30 |
Output dettagliato: handshake TLS, header richiesta/risposta. |
sudo nginx -T 2>/dev/null | grep server_name |
Elenca tutti i server_name configurati in tutti i file di config. |
sudo ss -tlnp | grep nginx |
Mostra su quali porte/indirizzi Nginx è in ascolto. |
sudo ls -la /var/log/nginx/ |
Controlla dimensione e permessi dei file di log. |
Abilitare stub_status per il monitoraggio
location /nginx_status {
stub_status;
allow 127.0.0.1;
allow ::1;
deny all;
}
curl http://127.0.0.1/nginx_status
Active connections: 3
server accepts handled requests
1542 1542 4890
Reading: 0 Writing: 1 Waiting: 2
Limita stub_status a localhost o all'IP del tuo sistema di monitoraggio. Espone informazioni sul carico del server.
Cosa significano i codici di errore Nginx e come si risolvono?
Quando Nginx restituisce un errore HTTP, il file error.log indica cosa è successo. Ecco i codici più comuni, il loro significato e come risolverli.
| Codice | Nome | Messaggio tipico in error.log | Causa comune | Soluzione |
|---|---|---|---|---|
| 403 | Forbidden | directory index of "/var/www/html/" is forbidden |
File index mancante, permessi file errati, autoindex off (predefinito) |
Aggiungi un index.html, correggi i permessi (chmod 644 per i file, 755 per le directory), o abilita autoindex on |
| 404 | Not Found | open() "/var/www/html/page" failed (2: No such file or directory) |
Percorso root errato, try_files errato, il file non esiste |
Controlla la direttiva root, verifica il percorso del file su disco |
| 413 | Request Entity Too Large | client intended to send too large body |
L'upload supera client_max_body_size (predefinito: 1 MB) |
Imposta client_max_body_size 50m; nel blocco server o location |
| 502 | Bad Gateway | connect() failed (111: Connection refused) while connecting to upstream |
Backend non in esecuzione, porta/socket errata in proxy_pass |
Avvia il backend, verifica che la porta corrisponda a proxy_pass |
| 503 | Service Unavailable | no live upstreams while connecting to upstream |
Tutti i backend in un blocco upstream sono down |
Avvia almeno un backend, controlla la config degli health check |
| 504 | Gateway Timeout | upstream timed out (110: Connection timed out) while reading response header |
Il backend impiega troppo tempo a rispondere | Aumenta proxy_read_timeout, ottimizza il backend, controlla i log del backend |
Diagnosticare un 502
Il 502 è l'errore proxy più frequente. Procedi passo per passo:
# 1. Is the backend running?
sudo ss -tlnp | grep 3000
# 2. Can Nginx reach it?
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/
# 3. What does the error log say?
sudo tail -20 /var/log/nginx/error.log
Se ss non mostra nulla sulla porta 3000, il backend è fermo. Se curl restituisce una risposta ma Nginx restituisce 502, controlla i permessi dei socket (frequente con i socket Unix di PHP-FPM o Gunicorn).
Quali sono gli errori Nginx più comuni?
Questi causano la maggior parte dei momenti "ho modificato la config e ora è tutto rotto".
Punti e virgola mancanti
Ogni direttiva deve terminare con un punto e virgola. Nginx dà un errore chiaro:
nginx: [emerg] unexpected "}" in /etc/nginx/sites-enabled/example.com:12
L'errore punta alla riga dopo il punto e virgola mancante, non alla riga del problema. Guarda una riga sopra.
Confusione tra root e alias
# root: appends the location to the path
location /images/ {
root /var/www;
# serves /var/www/images/photo.jpg
}
# alias: replaces the location with the path
location /images/ {
alias /var/www/media/;
# serves /var/www/media/photo.jpg
}
Con alias, lo slash finale è obbligatorio sia nel location che nel percorso alias. Dimenticarlo causa 404 senza motivo apparente nel log degli errori.
Confusione sull'ordine di valutazione dei location
Nginx valuta i location in quest'ordine, indipendentemente da dove compaiono nel file di config:
= /exact- Corrispondenza esatta. Controllata per prima. Se corrisponde, si ferma immediatamente.^~ /prefix- Prefisso preferenziale. La corrispondenza più lunga vince. Se corrisponde, salta tutte le regex.~ regex- Regex case-sensitive. Valutata dall'alto verso il basso. La prima corrispondenza vince.~* regex- Regex case-insensitive. Stesso ordine dall'alto verso il basso./prefix- Prefisso standard. La corrispondenza più lunga vince. Usato solo se nessuna regex ha corrisposto.
Nei prefissi conta la lunghezza della corrispondenza, non l'ordine nel file. Nelle regex conta l'ordine nel file, non la lunghezza. Mescolarli senza capire questo crea routing imprevedibile.
Slash finale in proxy_pass
# No trailing slash: passes /app/foo to backend as /app/foo
location /app/ {
proxy_pass http://127.0.0.1:3000;
}
# Trailing slash: strips /app/ and passes /foo to backend
location /app/ {
proxy_pass http://127.0.0.1:3000/;
}
Scegli un approccio e mantieni la coerenza. La maggior parte dei backend si aspetta il percorso completo (nessuno slash finale su proxy_pass).
Dimenticare nginx -t prima del ricaricamento
Se ricarichi con una config errata, Nginx continua a funzionare con la vecchia config e registra un errore. Non va in crash. Ma ora hai una config su disco che non corrisponde alla config in esecuzione. Questo crea confusione in seguito.
Prendi l'abitudine: sudo nginx -t && sudo systemctl reload nginx. Il && assicura che il ricaricamento avvenga solo se il test ha successo.
Modificare sites-available senza creare il link simbolico
I file in /etc/nginx/sites-available/ non vengono caricati automaticamente. Devi creare un link simbolico verso /etc/nginx/sites-enabled/. Una copia diretta funziona ugualmente, ma i link simbolici mantengono un'unica fonte di verità.
Qualcosa non funziona?
Sequenza di diagnosi rapida quando Nginx si comporta in modo anomalo:
# Check if Nginx is running
sudo systemctl status nginx
# Test the config
sudo nginx -t
# Check which config is actually loaded
sudo nginx -T 2>/dev/null | head -50
# Check the last 30 error log entries
sudo tail -30 /var/log/nginx/error.log
# Check what ports Nginx is listening on
sudo ss -tlnp | grep nginx
# Check file permissions on the web root
sudo ls -la /var/www/example.com/html/
Se il servizio è in stato di errore, journalctl -u nginx --no-pager -n 50 fornisce la storia completa. Cerca le voci [emerg].