Nginx va in crash-loop dopo il riavvio del contenitore: l'immagine base include brotli_static in discourse.conf ma non carica mai il modulo (direttiva sconosciuta)

Riepilogo
Dopo un normale riavvio del contenitore (riavvio dell’host / docker restart), nginx non riesce ad avviarsi all’interno del contenitore app con il seguente errore:

nginx: [emerg] unknown directive "brotli_static" in /etc/nginx/conf.d/discourse.conf:172

Questo porta l’intero sito offline (nessun fallback — nginx non si lega mai alle porte 80/443) fino a quando non viene applicata una patch manuale.

Ambiente

  • Immagine base: discourse/base:2.0.20260812-0036
  • nginx: 1.26.3-3+deb13u7 (pacchetto Debian 13/trixie, non compilato su misura)
  • Sono installati libnginx-mod-http-brotli-static/-filter 1.0.0~rc-6 e i symlink in /etc/nginx/mods-enabled/*.conf (con le righe load_module corrette) esistono e puntano a file .so validi.

Causa principale
/etc/nginx/nginx.conf (di proprietà del pacchetto nginx-common, non modificato) non contiene la direttiva include /etc/nginx/modules-enabled/*.conf;, quindi i moduli Brotli installati non vengono mai caricati — mentre discourse.conf (generato dai template di Discourse) continua a emettere brotli_static on; dando per scontato che lo siano.

Perché non fallisce immediatamente
La configurazione viene rielaborata solo quando nginx si (ri)avvia effettivamente. Un contenitore appena ricostruito può funzionare correttamente per giorni/settimane fino a quando qualcosa non riavvia nginx (riavvio dell’host, docker restart, OOM, ecc.), a quel punto inizia a entrare in crash-loop in modo silenzioso (~1×/sec) senza alcun recupero automatico.

Soluzione temporanea
Aggiungere include /etc/nginx/modules-enabled/*.conf; come prima riga di /etc/nginx/nginx.conf (contesto principale, prima di events {}). Confermato che questo ripristina il successo di nginx -t e il funzionamento normale.

Richiesta
L’immagine base potrebbe (a) aggiungere questo include al suo nginx.conf, oppure (b) rimuovere brotli_static/brotli dal template discourse.conf fornito se la build del pacchetto nginx della distribuzione non include più il supporto Brotli in modo predefinito?

2 Mi Piace

Correggo il mio stesso report: l’immagine base è a posto. La causa era locale alla nostra installazione.

Cosa è successo in realtà

Un job cron locale sul nostro host copia file di configurazione nginx obsoleti, mantenuti manualmente, all’interno del container in esecuzione. Uno di questi precede la direttiva include /etc/nginx/modules-enabled/*.conf;, un altro imposta ancora brotli_static on;. Insieme, producono l’errore unknown directive "brotli_static" e nginx rifiuta di avviarsi.

Perché ho fatto una diagnosi errata

Ho ispezionato /etc/nginx/nginx.conf all’interno del container in esecuzione e ho notato la mancanza dell’include modules-enabled. Quel file era già stato sovrascritto localmente, quindi il container in esecuzione non rifletteva mai ciò che Discourse genera effettivamente. Controllare l’immagine costruita rende la situazione ovvia. L’include è presente:

docker create --name check local_discourse/app
docker cp check:/etc/nginx/nginx.conf ./
docker rm check

Perché il problema è emerso con ritardo

Questa potrebbe essere la parte utile per gli altri. Il job termina con nginx -s reload e scarta il suo output. Quando la configurazione è corrotta, il reload fallisce silenziosamente e il nginx in esecuzione continua a servire richieste dalla configurazione già caricata. Tutto sembra funzionare correttamente. Il guasto diventa visibile solo al successivo avvio reale di nginx, che nel nostro caso è stato un riavvio del host causato da un aggiornamento non presidiato del kernel, avvenuto giorni dopo.

Quindi, se un container Discourse stava servendo traffico senza problemi e poi si blocca durante un riavvio non correlato, controlla se qualcosa ha sovrascritto la sua configurazione nginx nel frattempo.

Mi scuso per il disturbo e grazie a chiunque abbia dedicato del tempo a esaminare questo problema.

1 Mi Piace