The config grammar
Scope: the small grammar every nginx config is written in — directives, blocks, contexts — and the inheritance rules that decide which setting wins.
Directives and blocks
A directive is one instruction ending in a semicolon:
root /var/www/example;
index index.html;
A block is a directive whose value is a set of braces containing more directives:
server {
listen 127.0.0.1:8080;
server_name localhost;
root /home/you/nginx-lab/www/main;
}
Blocks nest, and where a directive sits is its context. The contexts you will actually use:
| Context | Lives in | Holds |
|---|---|---|
main |
the file's top level | user, worker_processes, pid, error_log |
events |
main | how workers take connections (worker_connections) |
http |
main | everything about serving: global logs, mime types, and the servers |
server |
http | one virtual host: a listen port plus a name |
location |
server (or location) | what happens for one slice of the URL space |
upstream |
http | a named pool of backends for proxying |
Comments start with #. Whitespace is free. A missing
semicolon is the most common typo in the wild, and
nginx -t names the line when you make it.
Inheritance
Settings flow downward: a directive set in http is
the default for every server, and a server's
settings are the default for its locations — until a
closer context sets its own, which replaces (never
merges with) the outer one for that directive.
Two consequences:
- Put genuinely global things in
httponce:access_log,include mime.types, thelimit_req_zone. The lab config's whole top half is exactly that. - Array-style directives replace wholesale. The
classic surprise is
proxy_set_header: if alocationsets anyproxy_set_header, it inherits none of the ones from the enclosingserver. This bites real configs; chapter 7 sets the full header block inside the location for this reason.
Seeing the config nginx sees
Files include other files; symlinks decide what's live. When you're unsure what nginx is actually working from, ask it to print the fully expanded configuration:
$ nginx -T
# configuration file /home/you/nginx-lab/nginx.conf:
# Lab nginx for "nginx for Mere Mortals".
...
user root;
pid /home/you/nginx-lab/prefix/nginx.pid;
nginx -T is nginx -t (test) plus the dump — every
include inlined, in order. It is the ground truth, and
the first thing to reach for when a running nginx
behaves as if your edit doesn't exist: usually it
doesn't, because the file you edited isn't the file
being loaded (an unlinked site, an unsaved buffer, a
second config tree).
Check: take any config on a machine you administer
and predict, for one location, which root and which
access_log apply — then confirm with nginx -T.
Being wrong about this is normal the first time;
inheritance is the whole lesson.