Open-Source Wikis

/

nginx

/

Systems

/

Configuration system

nginx/nginx

Configuration system

Active contributors: Sergey Kandaurov, Maxim Dounin, Aleksei Bavshin

Purpose

There are two different "configurations" in nginx:

  1. Build-time configurationauto/configure shell scripts, which decide which modules and OS features get compiled in.
  2. Runtime configurationnginx.conf parsed by ngx_conf_file.c, which sets up modules' typed config structs.

Both are wholly hand-rolled; nginx uses neither autotools nor a third-party config DSL.

Build-time: auto/configure

graph LR
    A[auto/configure] --> O[auto/options<br/>parse CLI flags]
    O --> CC[auto/cc<br/>pick compiler flags]
    CC --> OS[auto/os<br/>per-OS tweaks]
    OS --> LIB[auto/lib<br/>probe deps]
    LIB --> SRC[auto/sources<br/>which .c per subsystem]
    SRC --> M[auto/modules<br/>stitch module list]
    M --> MK[auto/make<br/>emit Makefile rules]
    MK --> SUM[auto/summary<br/>print summary]
    MK -.->|writes| OBJS[objs/Makefile<br/>objs/ngx_modules.c<br/>objs/ngx_auto_config.h]

Key files in auto/:

File Job
auto/configure Top-level orchestrator; sources each helper
auto/options All --with-* / --without-* / --add-module=... / path flags
auto/feature Reusable helper: try to compile a small C snippet to test for a feature
auto/have Append #define NGX_HAVE_X 1 to ngx_auto_config.h
auto/cc/* Per-compiler defaults: gcc, clang, icc, msvc, bcc, owc, sunc
auto/lib/* Per-dependency probes: openssl, pcre, zlib, libxslt, libgd, geoip
auto/os/* Per-OS tweaks: linux, freebsd, darwin, solaris, win32, hpux
auto/modules The module table — which static modules go into the binary
auto/sources Source-file lists per subsystem (CORE_DEPS, EVENT_DEPS, etc.)
auto/make Generates the objs/Makefile
auto/install Generates the install Makefile target

Configure produces three artifacts under objs/:

  • Makefile — the actual build file
  • ngx_modules.c — a generated .c listing every static module
  • ngx_auto_config.h#defines for every detected platform feature

nginx -V prints back the exact configure flags the binary was built with.

Runtime: nginx.conf

The conf parser is in src/core/ngx_conf_file.c. The parser is intentionally simple: it reads tokens, matches each non-block token against the current context's directive table, and dispatches to the directive's setter function.

Directives are module data

A directive is an entry in a module's commands table, of type ngx_command_t (src/core/ngx_conf_file.h):

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;          /* context flags + arg-count flags */
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;          /* which config to write into */
    ngx_uint_t            offset;        /* offset within that config */
    void                 *post;          /* extra arg for the setter */
};

The type mask combines:

  • Context: NGX_MAIN_CONF, NGX_HTTP_MAIN_CONF, NGX_HTTP_SRV_CONF, NGX_HTTP_LOC_CONF, etc.
  • Arity: NGX_CONF_NOARGS, NGX_CONF_TAKE1, NGX_CONF_TAKE2, ..., NGX_CONF_1MORE, NGX_CONF_ANY.
  • Block-ness: NGX_CONF_BLOCK if the directive opens a { ... }.

Common pre-built setters (defined in ngx_conf_file.c):

Setter Field type Example directive
ngx_conf_set_flag_slot ngx_flag_t daemon on;
ngx_conf_set_str_slot ngx_str_t pid /run/nginx.pid;
ngx_conf_set_num_slot ngx_int_t worker_rlimit_nofile 4096;
ngx_conf_set_size_slot size_t client_max_body_size 8m;
ngx_conf_set_msec_slot ngx_msec_t keepalive_timeout 60s;
ngx_conf_set_sec_slot time_t proxy_cache_valid 1h;
ngx_conf_set_enum_slot ngx_uint_t debug_points stop;
ngx_conf_set_bitmask_slot ngx_uint_t proxy_next_upstream error timeout;
ngx_conf_set_keyval_slot ngx_array_t of pairs proxy_set_header X Y;
ngx_conf_set_path_slot ngx_path_t * client_body_temp_path ...;

For directives whose semantics don't fit a slot, modules write a custom setter (e.g., ngx_set_user, ngx_set_cpu_affinity in src/core/nginx.c).

Module hooks per type

Each module type adds its own hook table under the module's ctx pointer:

Type Hook table type Hooks
NGX_CORE_MODULE ngx_core_module_t create_conf, init_conf
NGX_EVENT_MODULE ngx_event_module_t create_conf, init_conf + the ngx_event_actions_t for backends
NGX_HTTP_MODULE ngx_http_module_t preconfiguration, postconfiguration, create_main_conf, init_main_conf, create_srv_conf, merge_srv_conf, create_loc_conf, merge_loc_conf
NGX_MAIL_MODULE ngx_mail_module_t create_main_conf, init_main_conf, create_srv_conf, merge_srv_conf, protocol
NGX_STREAM_MODULE ngx_stream_module_t preconfiguration, postconfiguration, create_main_conf, init_main_conf, create_srv_conf, merge_srv_conf

The HTTP, Mail, and Stream meta-modules (ngx_http_module, ngx_mail_module, ngx_stream_module — all NGX_CORE_MODULEs) handle the http { }, mail { }, stream { } block-opening directives. Inside those blocks, the parser switches the directive table to the corresponding type's modules.

How nginx.conf becomes C state

sequenceDiagram
    participant N as ngx_init_cycle
    participant Mods as ngx_modules[]
    participant CP as ngx_conf_parse
    participant Setter as cmd->set()
    participant Conf as cycle->conf_ctx

    N->>Mods: each module->create_conf
    Mods->>Conf: store new struct ptrs
    N->>CP: open nginx.conf
    loop for each token
        CP->>CP: tokenize
        CP->>CP: match cmd in current ctx
        CP->>Setter: call setter(cf, cmd, conf)
        Setter->>Conf: write into struct via cmd->offset
    end
    CP-->>N: done
    N->>Mods: each module->init_conf (merge defaults)
    N->>Mods: each module->postconfiguration (register phase handlers)

ngx_init_cycle() (src/core/ngx_cycle.c) walks ngx_modules[], invokes each module's create_conf, parses nginx.conf, then calls init_conf/merge_conf to fill in defaults from the parent context. The result is cycle->conf_ctx, a void **** indexed by module type and module index — that's why HTTP modules access their config via ngx_http_get_module_loc_conf(r, ngx_http_my_module) macros.

Variables

Inside HTTP and Stream contexts, directives can include $variable placeholders. Variables come from two sources:

  • Built-in: defined by core modules at preconfiguration time (ngx_http_core_module's ngx_http_core_variables[] registers $uri, $args, $http_<header>, $remote_addr, etc.)
  • User-defined: created via set $name value;, map $foo $bar { ... }, geo $x { ... }, or by third-party modules calling ngx_http_add_variable()

Variables are stored as ngx_http_variable_t keyed in a hash. At request time, looking up $x either calls a get_handler (lazy) or reads a cached value. See src/http/ngx_http_variables.c.

For directives that take "a string with variables" as an argument — proxy_pass http://$backend, log_format ..., return 301 /$args — the parser uses ngx_http_compile_complex_value() to precompile the script. At runtime, ngx_http_complex_value(r, &cv, &out_str) walks the script bytecode to produce the final string. Bytecode lives in src/http/ngx_http_script.c.

include and if and set

  • include is its own module (ngx_conf_module) — it's literally one directive. Lets you split config across files.
  • if (in ngx_http_rewrite_module) is implemented by the rewrite engine, not the conf parser. The infamous "if is evil" docs page exists because if runs at request time inside the rewrite phase, not at config parse time.
  • set (set $x value;) installs a setter into the rewrite-phase script that runs per-request.

Integration points

  • Modules declare commands[] and the per-type hooks.
  • The cycle owns the parsed config (cycle->conf_ctx) and the listening sockets derived from it.
  • The master invokes ngx_init_cycle() on startup and on SIGHUP. The cycle pattern is what makes graceful reloads work.
  • Build system (auto/configure) decides which modules end up in ngx_modules[]. Dynamic modules add themselves at runtime via load_module.

Entry points for modification

Adding a directive: add an entry to the module's commands[] table, add the field to the module's config struct, write a setter (or use one of the slot helpers), update the docs in docs/xml/. Adding a directive that has variable interpolation: use ngx_http_compile_complex_value at config time, ngx_http_complex_value at request time. Adding a new directive context (a new block type): you almost certainly want a new module of an appropriate type rather than to extend the parser; the parser itself rarely needs changes.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Configuration system – nginx wiki | Factory