luminare.infra_edge · v0.2.1
0013. nginx.conf owned by the role and checked on every run instead of a conf.d file and per-file checks
- Status: accepted
- Date: 2026-10-21
Context
The nginx role needs settings at the http level (version hidden, client address from the
connector, JSON access log, gzip, security headers, websocket map) and, for relays, a stream
block, which must be in the main context of /etc/nginx/nginx.conf. The nginx.conf of the
Debian 13 and Ubuntu 24.04 packages already sets gzip on and an access_log in the combined
format at the http level and includes conf.d/*.conf and sites-enabled/* there; the Ubuntu
file also still allows TLS 1.0 and 1.1. A second gzip in a conf.d file is a duplicate
directive (nginx refuses to start), and a second access_log adds a second log instead of
replacing the first. Single files cannot be checked on their own: nginx -t -c <file> only works
for a complete main configuration. systemctl reload nginx fails on a configuration that nginx
cannot parse, but an error that only shows when nginx applies it (for example a port that another
process holds) is written to the error log while the reload reports success.
Considered options
- The role writes the whole
nginx.conf(Debian’s layout kept:modules-enabled,conf.d,sites-availableandsites-enabled), writes every file first, runsnginx -tas a task on every run and reloads in a handler. - A
conf.d/00-hardening.conffile plus line edits of the package’snginx.conf, withnginx -tin a handler before the reload. - A
validate:check on each template.
Decision
Option 1. The check is a task, not a handler, because a failed handler (a check or a reload) loses its notification: the next run would see no change, skip the check and pass with the broken files still on disk. As a task it runs on every run, so the play keeps failing until the input is fixed, and the reload handler only runs after a check that passed. The check is skipped in check mode, where no file is written.
Option 2 has to edit a file that the package also changes, and the result differs between Debian and Ubuntu. Option 3 cannot work for files that are only pieces of the configuration.
Consequences
- Good: Debian 13 and Ubuntu 24.04 get the same main configuration, and the Molecule scenario
checks it with
nginx -tandnginx -Ton both. - Good: a broken input never reaches a running nginx through this role.
- Bad: local changes to
nginx.confare overwritten; extrahttpsettings go into/etc/nginx/conf.d/*.conf. When a package update changesnginx.conf, dpkg asks which version to keep: a manualapt upgradeshows the question, and unattended-upgrades holds that update back until someone installs it by hand. - Bad: after a failed check the new files stay on disk until the next run fixes them. If nginx is
restarted in that window (for example by a reboot), it does not start, because the unit runs
nginx -tbefore the start; the runbook covers it.
docs/adr/0013-nginx-conf-owned-by-the-role-and-checked-every-run.md on GitHub
Licensed under Apache-2.0. Source: luminare-dev/ansible-collection-infra_edge at v0.2.1.