Come Diagnosticare e Risolvere gli Errori Nginx 502 Bad Gateway
Risolvi gli errori Nginx 502 controllando i log degli errori, lo stato dell'upstream, i permessi dei socket, le impostazioni del proxy, i timeout e i firewall.
Come Diagnosticare e Risolvere gli Errori Nginx 502 Bad Gateway
Nginx è un potente e popolare server web e proxy inverso, spesso utilizzato per servire contenuti statici, bilanciare il traffico e inoltrare richieste a vari server applicativi upstream come PHP-FPM, Node.js, Python Gunicorn o Apache Tomcat. Quando Nginx incontra un problema di comunicazione con uno di questi server upstream, di solito risponde con un errore "502 Bad Gateway".
Inizia con il log degli errori di Nginx, poi verifica se il processo upstream è in esecuzione, raggiungibile e autorizzato a rispondere.
Comprendere l'Errore Nginx 502 Bad Gateway
Un errore 502 Bad Gateway indica che Nginx, agendo come proxy inverso, ha ricevuto una risposta non valida da un server upstream. Significa che Nginx si è connesso con successo a un server upstream ma ha ricevuto nessuna risposta, una risposta incompleta o una risposta che non poteva comprendere. Fondamentalmente, il problema non è con Nginx stesso, ma con il servizio con cui Nginx sta cercando di comunicare.
I server upstream comuni includono:
- PHP-FPM: Per applicazioni PHP (es. WordPress, Laravel).
- Gunicorn/uWSGI: Per applicazioni Python (es. Django, Flask).
- Node.js: Per applicazioni JavaScript.
- Apache Tomcat: Per applicazioni Java.
- Altri server web: Come Apache HTTP Server che serve contenuti specifici.
L'errore 502 è un indicatore cruciale che il backend della tua applicazione non funziona correttamente o è inaccessibile a Nginx.
Diagnosi Passo dopo Passo
La chiave per risolvere un errore 502 è una diagnosi sistematica. Inizia con i colpevoli più probabili e procedi progressivamente.
1. Controlla Prima i Log degli Errori di Nginx
I log degli errori di Nginx sono la fonte primaria di informazioni. Spesso contengono dettagli specifici sul motivo per cui Nginx non è riuscito a comunicare con il server upstream.
- Posizione: Tipicamente si trovano in
/var/log/nginx/error.log. - Comando: Usa
tail -fper monitorare i log in tempo reale mentre provi a riprodurre l'errore.
tail -f /var/log/nginx/error.log
Cosa cercare:
connect() failed (111: Connection refused): Indica che il server upstream non è in ascolto sull'indirizzo/porta specificati o che un firewall blocca la connessione.upstream timed out: Il server upstream ha impiegato troppo tempo per rispondere.upstream prematurely closed connection: Il server upstream ha chiuso la connessione prima di inviare una risposta completa.no live upstreams while connecting to upstream: Nginx non è riuscito a trovare alcun server upstream disponibile configurato.
2. Verifica lo Stato del Server Upstream
Una volta ottenuti indizi dai log degli errori di Nginx, controlla lo stato del tuo server applicativo upstream.
Per PHP-FPM:
sudo systemctl status php8.2-fpmPer Node.js/Python/Altre App Personalizzate: Controlla se il processo è in esecuzione.
ps aux | grep node ps aux | grep gunicornSe usi un gestore di processi come PM2 (Node.js) o Supervisor (generale), controlla il suo stato.
pm2 status sudo supervisorctl status
Se il servizio non è in esecuzione, prova ad avviarlo e controlla i suoi log per errori.
sudo systemctl start php8.2-fpm
3. Controlla la Connettività di Rete all'Upstream
Assicurati che Nginx possa raggiungere il server upstream sulla porta o sul percorso del socket configurato.
Per connessioni TCP/IP (es.
127.0.0.1:8000): Usatelnetonc(netcat) per testare la connettività della porta dal server Nginx.telnet 127.0.0.1 8000 nc -vz 127.0.0.1 8000Una connessione riuscita dovrebbe mostrare
Connected to 127.0.0.1.osucceeded!. Se si blocca o mostraConnection refused, il servizio upstream non è in ascolto o un firewall lo blocca.Per socket Unix (es.
unix:/run/php/phpX.X-fpm.sock): Verifica che il file del socket esista e abbia i permessi corretti.ls -l /run/php/phpX.X-fpm.sockNginx dovrebbe avere permessi di lettura/scrittura su questo file socket. L'utente Nginx (es.
www-data) deve far parte del gruppo che possiede il socket (es.www-dataophp-fpm).
Cause Comuni e Soluzioni
Basandoti sui tuoi passaggi diagnostici, ecco le cause più frequenti degli errori 502 e come risolverli.
1. Server Upstream Non in Esecuzione o Bloccato
Causa: L'applicazione a cui Nginx sta cercando di fare da proxy (es. PHP-FPM, Gunicorn, app Node.js) non è in esecuzione o si è bloccata.
Soluzione: Avvia o riavvia il servizio upstream.
# Esempio per PHP-FPM
sudo systemctl start php8.2-fpm
# Se è già in esecuzione e sospetti un crash, riavvialo:
sudo systemctl restart php8.2-fpm
# Per applicazioni personalizzate, usa i loro comandi specifici di avvio/riavvio
Consiglio: Assicurati che i tuoi servizi upstream siano configurati per avviarsi automaticamente all'avvio del sistema. Per i servizi systemd, usa systemctl enable phpX.X-fpm.
2. Sovraccarico del Server Upstream / Esaurimento delle Risorse
Causa: Il server upstream è sovraccarico, sta esaurendo la memoria, la CPU o raggiungendo i limiti dei processi, causando la cessazione delle risposte o il rifiuto di nuove connessioni.
Sintomi: I log degli errori di Nginx potrebbero mostrare connection refused o upstream timed out in modo intermittente, specialmente sotto carico. Gli strumenti di monitoraggio del sistema (top, htop, free -h) mostrano un uso elevato delle risorse.
Soluzioni:
Per PHP-FPM: Regola le impostazioni del pool PHP-FPM nel suo file di configurazione (es.
/etc/php/X.X/fpm/pool.d/www.conf).pm.max_children: Il numero massimo di figli che possono essere vivi contemporaneamente.pm.start_servers: Il numero di figli creati all'avvio.pm.min_spare_servers,pm.max_spare_servers: Controllano quanti figli inattivi vengono mantenuti.
; Esempio per la gestione dinamica dei processi pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20- Aumenta
memory_limitinphp.inise gli script esauriscono la memoria.
Per altre applicazioni: Aumenta il numero di processi worker, thread o alloca più memoria se possibile. Monitora le metriche specifiche della tua applicazione.
Timeout di Nginx: Aumenta le direttive
proxy_connect_timeout,proxy_send_timeouteproxy_read_timeoutdi Nginx nella tua configurazione Nginx, ma comprendi che questo ritarda semplicemente l'errore se il backend è veramente in difficoltà.http { ... proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; ... }
3. Configurazione Upstream Errata in Nginx
Causa: Nginx è configurato per connettersi all'indirizzo IP, alla porta o al percorso del socket Unix sbagliato per il server upstream.
Sintomi: I log degli errori di Nginx mostrano connect() failed (111: Connection refused) immediatamente dopo una richiesta.
Soluzione: Rivedi attentamente la configurazione del blocco server di Nginx (/etc/nginx/sites-available/your_site.conf).
Per upstream HTTP/HTTPS:
location /app { proxy_pass http://127.0.0.1:8000; # Assicurati che IP e porta siano corretti proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }Per PHP-FPM tramite socket Unix:
location ~ \.php$ { fastcgi_pass unix:/run/php/phpX.X-fpm.sock; # Verifica che questo percorso corrisponda esattamente alla configurazione PHP-FPM fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }Per PHP-FPM tramite TCP/IP:
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; # Verifica IP e porta fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
Dopo aver apportato modifiche, testa sempre la configurazione di Nginx e ricarica/riavvia Nginx:
nginx -t
systemctl reload nginx # O riavvia se -t indica una necessità
4. Superamento del request_terminate_timeout di PHP-FPM
Causa: Uno script PHP impiega più tempo per essere eseguito rispetto all'impostazione request_terminate_timeout in PHP-FPM. Nginx attende la risposta, ma PHP-FPM termina lo script, causando la ricezione di una risposta incompleta da parte di Nginx.
Sintomi: I log degli errori di Nginx potrebbero mostrare upstream timed out o script timed out. I log di PHP-FPM potrebbero mostrare child XX exited on signal 9 (SIGKILL).
Soluzione:
Aumenta
request_terminate_timeout: Nella configurazione del pool PHP-FPM (www.conf), trova e regola questa direttiva. Impostarla a0disabilita il timeout, ma generalmente non è raccomandato poiché script a lunga esecuzione possono bloccare le risorse.request_terminate_timeout = 300 # Aumenta a 5 minuti (300 secondi)Aumenta
fastcgi_read_timeoutin Nginx: Questo timeout di Nginx dovrebbe essere uguale o maggiore direquest_terminate_timeout.location ~ \.php$ { ... fastcgi_read_timeout 300s; # Deve essere >= request_terminate_timeout di PHP-FPM ... }
Avvertenza: Sebbene aumentare i timeout possa risolvere l'errore 502, potrebbe mascherare problemi di performance sottostanti. La migliore soluzione a lungo termine è ottimizzare lo script PHP lento.
5. Problemi di Firewall
Causa: Un firewall (sul server Nginx o sul server upstream se sono separati) sta bloccando le connessioni alla porta o al socket upstream.
Soluzione:
Controlla lo stato del firewall:
sudo ufw status # Per UFW (Ubuntu/Debian) sudo firewall-cmd --list-all # Per firewalld (CentOS/RHEL) sudo iptables -L # Per iptablesApri le porte necessarie: Assicurati che la porta che Nginx usa per connettersi all'upstream (es. 9000 per PHP-FPM tramite TCP/IP) sia aperta.
sudo ufw allow from 127.0.0.1 to any port 9000 # Consenti a localhost di connettersi alla porta 9000 sudo firewall-cmd --permanent --add-port=9000/tcp # Per firewalld sudo firewall-cmd --reloadDisabilita temporaneamente il firewall per scopi di test solo in un ambiente controllato, poi riattivalo e configuralo correttamente.
6. Interferenza di SELinux o AppArmor
Causa: Miglioramenti della sicurezza come SELinux (su RHEL/CentOS) o AppArmor (su Ubuntu/Debian) potrebbero impedire a Nginx di accedere al socket upstream o di effettuare connessioni di rete, anche se i permessi dei file e i firewall sono configurati correttamente.
Sintomi: I log potrebbero mostrare permission denied o messaggi simili, specialmente in /var/log/audit/audit.log (per SELinux).
Soluzione:
Controlla
audit.log:sudo grep nginx /var/log/audit/audit.logImposta temporaneamente SELinux in modalità permissiva:
sudo setenforce 0. Se l'errore si risolve, SELinux è il colpevole. Dovrai quindi generare e applicare le politiche SELinux appropriate (es.audit2allow). Ricorda di riportarlo in modalità enforcing (sudo setenforce 1).Controlla lo stato di AppArmor:
sudo aa-status. Se AppArmor è attivo, potresti dover regolare il profilo di Nginx.
7. Corpi di Richiesta/Risposta Grandi (Proxy Buffering)
Causa: Le impostazioni predefinite del proxy buffering di Nginx potrebbero essere troppo piccole per corpi di richiesta o risposta molto grandi, portando a una chiusura prematura della connessione.
Sintomi: I log degli errori di Nginx potrebbero mostrare upstream prematurely closed connection while reading response header from upstream o upstream prematurely closed connection while reading response body from upstream.
Soluzione: Regola le direttive del proxy buffering di Nginx nel tuo blocco http, server o location.
http {
...
proxy_buffer_size 128k; # Dimensione del buffer per la prima parte della risposta
proxy_buffers 4 256k; # Numero e dimensione dei buffer per il resto della risposta
proxy_busy_buffers_size 256k; # Dimensione massima dei buffer occupati
proxy_temp_file_write_size 256k; # Dimensione per la scrittura su file temporanei se il buffering va in overflow
...
}
Nota: Queste impostazioni consumano più memoria. Regolale con cautela in base alle risorse del tuo server e alla dimensione tipica delle risposte della tua applicazione.
Suggerimenti Generali per la Risoluzione dei Problemi
- Rivedi tutti i log pertinenti: Oltre ai log degli errori di Nginx, controlla anche i log di accesso di Nginx, i log dell'applicazione upstream (PHP-FPM, Gunicorn, log dell'app Node.js) e i log di sistema (
/var/log/syslog,dmesg). - Riavvia Nginx: Dopo qualsiasi modifica alla configurazione, riavvia sempre Nginx per assicurarti che abbiano effetto:
systemctl restart nginx. - Testa la Configurazione di Nginx: Prima di riavviare, convalida la sintassi della configurazione di Nginx:
nginx -t. - Isola il Problema: Prova a bypassare Nginx e ad accedere direttamente all'applicazione upstream. Ad esempio, se la tua app Node.js è su
localhost:3000, usacurl http://localhost:3000dalla riga di comando del server. Se anche questo fallisce, il problema è sicuramente con la tua applicazione, non con Nginx. - Controlla lo Spazio su Disco: Un disco pieno può impedire alle applicazioni di scrivere file temporanei o log, portando a crash o guasti. Usa
df -hper controllare l'utilizzo del disco.
Conclusione
Inizia con /var/log/nginx/error.log, poi verifica che l'upstream sia in esecuzione e raggiungibile dall'host Nginx. Una volta che sai se il guasto è connessione rifiutata, timeout, permesso negato o chiusura prematura, la soluzione è di solito nel servizio upstream, nei permessi del socket, nelle impostazioni di timeout o nella regola del firewall.