Hai appena pubblicato una nuova release dietro Nginx. Il sito risponde, ma questo non basta. In produzione contano header corretti, cache prevedibile, TLS pulito e timeout che non tagliano le richieste lente nel momento sbagliato.
Questa mini checklist post-deploy serve proprio a quello. Non è una guida teorica. È una sequenza di verifiche rapide per scoprire subito se Nginx sta lavorando bene con upstream, CDN, applicazione e certificati.
Il focus è pratico: limiti, header, cache, TLS, upstream e timeout in carico reale. L’obiettivo è semplice. Prima del traffico vero, vuoi vedere errori, redirect e latenze con i tuoi occhi.
Prerequisiti
- Accesso shell al server Nginx.
- Permessi sudo o root.
- Un dominio già puntato al server.
- Un upstream attivo, per esempio PHP-FPM, Node.js o un backend su porta locale.
- curl installato sul nodo di test.
Note: se usi un bilanciatore o una CDN, esegui i test sia dall’esterno sia dal server stesso. Il comportamento può cambiare per cache, header aggiunti e TLS terminato a monte.
Step 1: verificare la configurazione prima di toccare il traffico
Il primo controllo è banale, ma salva tempo. Se la sintassi è rotta, gli altri test non contano. In più, un reload fatto male può lasciare in giro una config vecchia e una nuova solo in parte attiva.
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager -l# Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Active: active (running)Perché funziona: Nginx valida il parsing prima del reload e ti blocca gli errori di sintassi più costosi.
Nota cross-distro: su alcune distro il file può stare in /usr/local/nginx/conf/nginx.conf oppure sotto /etc/nginx. Il comando resta uguale.
Step 2: controllare header e redirect con una singola richiesta HTTP
Dopo il reload, guarda cosa vede davvero il client. Non fidarti della configurazione letta a occhio. Devi controllare status, location, HSTS, cache-control e server header.
curl -I https://example.com/
curl -svo /dev/null https://example.com/ 2>&1 | sed -n '1,25p'# Output:
HTTP/2 200
strict-transport-security: max-age=31536000; includeSubDomains
cache-control: public, max-age=60
x-content-type-options: nosniffPerché funziona: gli header mostrano il comportamento effettivo del layer HTTP, non quello che pensi di aver configurato.
Warning: se vedi HTTP/1.1 301 in un punto inatteso, potrebbe esserci un redirect doppio tra applicazione, Nginx e CDN. Questo rompe i tempi di risposta e confonde i crawler.
Controllo rapido degli header più importanti
- Strict-Transport-Security: presente solo se sei certo di voler forzare HTTPS.
- Cache-Control: coerente con contenuto statico o dinamico.
- Vary: necessario quando la risposta cambia per encoding o lingua.
- X-Frame-Options e Content-Security-Policy: utili se gestisci sicurezza dal reverse proxy.
Step 3: misurare la cache senza credere al marketing della CDN
Se hai una cache lato Nginx, devi capire se sta davvero servendo HIT. Una cache mal configurata sembra veloce nei test brevi, ma collassa quando aumenta la concorrenza o quando il backend va in crisi.
curl -I https://example.com/static/app.css
curl -I https://example.com/page-dinamica# Output:
X-Cache-Status: HIT
X-Cache-Status: MISSPerché funziona: separi il traffico statico da quello dinamico e vedi subito se le regole di caching sono coerenti.
Se usi proxy_cache, controlla anche i file di stato e i lock. Un backend lento può generare molti MISS consecutivi se proxy_cache_lock è assente.
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=sitecache:100m inactive=10m max_size=5g;
proxy_cache_lock on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;# Output:
proxy_cache configurata per ridurre i colpi simultanei al backendNote: su server con poco disco, la cache può sembrare attiva ma saturare I/O e inode. Se la macchina è piccola, misura sempre spazio e latenza disco dopo il deploy.
Step 4: testare TLS e catena certificati come farebbe un client reale
Il certificato “valido” non basta. Devi controllare protocollo, catena, SNI e ciphers. Un errore qui rompe browser, webhook e API client in modi diversi.
openssl s_client -connect example.com:443 -servername example.com -brief < /dev/null
curl --tlsv1.2 -I https://example.com/# Output:
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Verification: OKPerché funziona: openssl s_client verifica il handshake reale, mentre curl prova il percorso applicativo completo.
Se usi Certbot, controlla anche il rinnovo automatico. Il file può essere corretto oggi e scadere senza avviso tra settimane.
sudo certbot renew --dry-run# Output:
Congratulations, all simulated renewals succeededNota cross-distro: su systemd recenti il timer di Certbot può chiamarsi in modo diverso rispetto ai vecchi cron job. Non dare per scontato il percorso.
Step 5: verificare upstream, keepalive e timeout sotto carico realistico
Qui si gioca quasi tutto. Nginx è spesso veloce, ma il collo di bottiglia è l’upstream. Se il backend risponde piano, il proxy deve gestire bene attese, riuso connessioni e fallback.
upstream app_backend {
server 127.0.0.1:3000 max_fails=3 fail_timeout=10s;
keepalive 32;
}
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 2s;
proxy_send_timeout 15s;
proxy_read_timeout 15s;
}# Output:
upstream configurato con keepalive e timeout coerentiPerché funziona: riduci il costo delle nuove connessioni e dai al backend un margine realistico per rispondere.
Adesso fai una prova semplice dal server o da un nodo vicino. Non serve uno stress test completo per scovare i primi problemi.
time curl -s -o /dev/null -w 'code=%{http_code} total=%{time_total} connect=%{time_connect} starttransfer=%{time_starttransfer}
' https://example.com/# Output:
code=200 total=0.184 connect=0.006 starttransfer=0.121Se il time_starttransfer sale molto più del normale, il problema è spesso nel backend o nella cache, non nel TLS.
Warning: se vedi upstream timed out nei log ma il backend sembra sano, controlla anche saturazione di worker, query lente e limiti di connessioni simultanee sull’applicazione.
Step 6: controllare limiti di connessioni e code prima del picco
Un deploy può essere corretto ma non dimensionato. Se il traffico aumenta, i limiti di connessione e i backlog diventano visibili subito. Questa è la parte che spesso manca nelle checklist veloci.
events {
worker_connections 4096;
}
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 20;
keepalive_timeout 15s;
}# Output:
limiti attivi su connessioni per IP e timeout keepalive ridottoPerché funziona: eviti che pochi client lenti consumino tutte le risorse del worker.
Se la tua applicazione è dietro PHP-FPM, verifica anche il numero di processi disponibili. Un Nginx perfetto non salva un pool esaurito.
systemctl status php-fpm --no-pager -l
ss -ltnp | grep -E 'php-fpm|:9000|:3000'# Output:
LISTEN 0 4096 127.0.0.1:9000Note: su Debian e Ubuntu il servizio può essere php8.2-fpm o simile. Su RHEL e derivate il nome cambia con la versione installata.
Verifica finale
Prima di considerare il deploy chiuso, fai una sequenza breve e ripetibile. Non deve durare più di pochi minuti.
- nginx -t senza errori.
- reload riuscito e processo attivo.
- Header corretti con curl -I.
- HIT/MISS cache coerenti con il tipo di contenuto.
- TLS valido con openssl s_client.
- Tempo di risposta stabile con curl -w.
- Nessun errore upstream nei log dopo almeno 5 richieste consecutive.
Un controllo utile in più è leggere i log con filtro serrato. Cerca errori recenti, non tutto il rumore storico.
sudo journalctl -u nginx -n 50 --no-pager
sudo tail -n 50 /var/log/nginx/error.log# Output:
no critical errors in the last 50 linesTroubleshooting
1) nginx: [emerg] host not found in upstream "app_backend"
Causa: il nome del blocco upstream o del DNS interno non è risolvibile al reload.
Fix:
sudo nginx -T | grep -n "upstream app_backend" -A5 -B2
sudo systemd-resolve --status 2>/dev/null || resolvectl status# Output:
upstream definition found
DNS resolution checked2) upstream timed out (110: Connection timed out) while reading response header from upstream
Causa: il backend risponde oltre proxy_read_timeout o si blocca su query, code o lock.
Fix:
sudo grep -R "proxy_read_timeout\|proxy_connect_timeout" /etc/nginx
sudo ss -antp | grep ':3000\|:9000'# Output:
timeout values verified
upstream sockets under inspection3) SSL_do_handshake() failed (SSL: error:0A00018E:SSL routines::ca md too weak)
Causa: catena certificati o parametri TLS deboli non compatibili con il client o con la CA.
Fix:
openssl x509 -in /etc/ssl/certs/example.crt -text -noout | sed -n '1,40p'
sudo nginx -s reload# Output:
certificate chain reviewed
reload requested after fixConclusione
Un deploy su Nginx non è davvero pronto finché non hai verificato header, cache, TLS e upstream con comandi reali. La differenza tra “online” e “stabile” sta quasi sempre in questi controlli.
Il prossimo passo concreto è trasformare questa checklist in uno script di post-deploy eseguito da CI o da un timer systemd. Così ogni release passa gli stessi test, senza affidarsi alla memoria di chi è di turno.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.