notes blog about

Nginx is a multitool: web server, load balancer, reverse proxy, WAF

Key files and directories

Config file structure

Full example config

See NGINXConfig for generating config files.


NGINX consists of modules which are controlled by directives in the config file.

In version 1.9.11 (2016) Nginx added support for dynamic modules similar to Dynamic Shared Objects (DSO) of Apache HTTP server. Before that you needed to recompile Nginx if you updated a module. Now you can load/unload a module into NGINX at runtime.

To load a dynamic module:

load_module "modules/";



The if directive






http {
    # ...
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    server {
        # ...
        location / {
            # ...
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;

Reverse proxy

Request headers

In proxied requests (proxy_pass) NGINX by default eliminates the header fields whose values are empty strings and redefines two header fields:


Response headers

You might want to use the proxy_redirect directive to change response “Location” header (used in 3xx redirects). E.g.:

# change host (fqdn) in response "Location" header
proxy_redirect ~*https?://[^/]+/(.+)$ https://$host/$1;


domain names statically configured in config file are only looked up once on startup (or configuration reload)

Traffic limiting

See also

Limiting connections

limit_conn module limits the number of connections per the defined key, in particular, the number of connections from a single IP address

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;


    server {


        location /download/ {
            limit_conn addr 1;

Limiting rate

limit_req module is used to limit the request processing rate per a defined key, in particular, the processing rate of requests coming from a single IP address. The limitation is done using the “leaky bucket” method.

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;


    server {


        location /search/ {
            limit_req zone=one burst=20 nodelay;


Limiting bandwidth

location /download/ {
    limit_rate_after 10m; # After 10 megabytes are dowloaded
    limit_rate 1m;        # limit rate to 1 megabyte per second.

Tips and tricks

Useful commands:

nginx -t # test configuration
nginx -T # test configurtation and print it
nginx -s <signal> # stop (immediately)
                  # quit (wait to finish processing requests)
                  # reload (configuration gracefully, i.e. without dropping packets!)
                  # reopen (log files) 

Verify installation (works also inside a container):

nginx -v
ps -ef | grep nginx
curl localhost -I

Get values of variables (debugging):

# /etc/nginx/nginx.conf
add_header X-mine "$upstream_addr";

curl localhost -v # look for X-mine header in response