# Nginx crash-loops after container restart: base image ships brotli\_static in discourse.conf but never loads the module (unknown directive)

**URL:** https://meta.discourse.org/t/nginx-crash-loops-after-container-restart-base-image-ships-brotli-static-in-discourse-conf-but-never-loads-the-module-unknown-directive/410530
**Category:** Bug
**Tags:** nginx
**Created:** [August 20, 2026, 1:57pm UTC](https://meta.discourse.org/t/nginx-crash-loops-after-container-restart-base-image-ships-brotli-static-in-discourse-conf-but-never-loads-the-module-unknown-directive/410530 "2026-08-20T13:57:21Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![oxFilla](https://avatars.discourse-cdn.com/v4/letter/o/c68b51/32.png) [@oxFilla](https://meta.discourse.org/u/oxFilla)
#### Post date: [August 20, 2026, 1:57pm UTC](https://meta.discourse.org/t/nginx-crash-loops-after-container-restart-base-image-ships-brotli-static-in-discourse-conf-but-never-loads-the-module-unknown-directive/410530/1 "2026-08-20T13:57:22Z")

</div>

**Summary**  
After a routine container restart (host reboot / `docker restart`), nginx fails to start inside the `app` container with:

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

```

This puts the whole site down (no fallback — nginx never binds to 80/443) until manually patched.

**Environment**

- Base image: `discourse/base:2.0.20260812-0036`
- nginx: `1.26.3-3+deb13u7` (Debian 13/trixie package, not custom-compiled)
- `libnginx-mod-http-brotli-static`/`-filter` 1.0.0~rc-6 are installed, and `/etc/nginx/mods-enabled/*.conf` symlinks (with correct `load_module` lines) exist and point to valid `.so` files.

**Root cause**  
`/etc/nginx/nginx.conf` (owned by the `nginx-common` package, unmodified) has no `include /etc/nginx/modules-enabled/*.conf;` directive, so the installed Brotli modules are never loaded — while `discourse.conf` (generated by the Discourse templates) still emits `brotli_static on;` assuming they are.

**Why it doesn’t fail immediately**  
The config only gets re-parsed when nginx actually (re)starts. A freshly rebuilt container can run fine for days/weeks until something restarts nginx (host reboot, `docker restart`, OOM, etc.), at which point it silently starts crash-looping (~1×/sec) with no automatic recovery.

**Workaround**  
Add `include /etc/nginx/modules-enabled/*.conf;` as the first line of `/etc/nginx/nginx.conf` (main context, before `events {}`). Confirmed this restores `nginx -t` success and normal operation.

**Ask**  
Could the base image either (a) add this include to its `nginx.conf`, or (b) drop `brotli_static`/`brotli` from the shipped `discourse.conf` template if the distro nginx package build no longer bundles Brotli support by default?

---

<div class="post-metadata">

### Author: ![oxFilla](https://avatars.discourse-cdn.com/v4/letter/o/c68b51/32.png) [@oxFilla](https://meta.discourse.org/u/oxFilla)
#### Post date: [September 7, 2026, 7:47pm UTC](https://meta.discourse.org/t/nginx-crash-loops-after-container-restart-base-image-ships-brotli-static-in-discourse-conf-but-never-loads-the-module-unknown-directive/410530/2 "2026-09-07T19:47:52Z")

</div>

Correcting my own report: the base image is fine. The cause was local to our installation.

**What actually happened**

A local cron job on our host copies outdated, manually maintained nginx config files into the running container. One of them predates `include /etc/nginx/modules-enabled/*.conf;`, another still sets `brotli_static on;`. Together they produce `unknown directive "brotli_static"`, and nginx refuses to start.

**Why I misdiagnosed it**

I inspected `/etc/nginx/nginx.conf` inside the running container and found the `modules-enabled` include missing. That file had already been overwritten locally, so the running container never reflected what Discourse actually generates. Checking the built image instead makes it obvious. The include is there:

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

```

**Why it surfaced with a delay**

This may be the useful part for others. The job ends with `nginx -s reload` and discards its output. When the config is broken, the reload fails silently and the running nginx keeps serving from its already loaded config. Everything looks healthy. The breakage only becomes visible at the next real nginx start, which for us was an unattended kernel upgrade rebooting the host days later.

So if a Discourse container has been serving traffic fine and then dies on an unrelated reboot, check whether something overwrote its nginx config in the meantime.

Apologies for the noise, and thanks to anyone who spent time looking at this.
