NGINX Cheat Sheet

NGINX directives and commands for server blocks, locations, reverse proxying, TLS, headers, rate limits, and reloads.

Web & Network
nginx
web-server
reverse-proxy

NGINX selects a virtual server, chooses a location for the request URI, and then serves content or passes the request to an upstream. Directive context matters: server blocks belong in http, and some controls are valid only at http, server, or location scope.

Server blocks and static files

A server block matches an address and Host value. root joins the configured directory with the request URI, while index names files considered for directory requests.

nginx
server {
    listen 80;
    server_name example.com www.example.com;

    root /srv/www/example;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
Table
DirectiveRole
listen 80Accept HTTP connections on port 80.
server_name example.comMatch the request host against this virtual server.
root /srv/www/exampleSet the filesystem base for URI lookup.
index index.htmlSelect an index file for a directory URI.
try_filesTest candidate files in order and use the final fallback.

For a client-routed application, a fallback such as try_files $uri $uri/ /index.html; internally sends unknown paths to the application entry point. Use =404 instead when nonexistent static paths must stay missing.

Location matching and precedence

NGINX first checks exact and prefix locations, then may evaluate regular expressions. Regular-expression locations are tested in configuration order, not by the length of their pattern.

Table
FormMatch behavior
location = /healthExact URI match; selected immediately.
location ^~ /assets/Prefix match that suppresses regular-expression checks when it is the longest prefix.
location ~ \.php$Case-sensitive regular expression.
`location ~* .(pngjpg)$`
location /Ordinary prefix and common fallback.

The practical order is exact =, the longest prefix, regular expressions unless that prefix uses ^~, and finally the remembered longest ordinary prefix.

nginx
location = /health {
    return 200 "ok\n";
}

location ^~ /assets/ {
    try_files $uri =404;
}

location ~* \.(css|js|png|jpg)$ {
    expires 1h;
}

Reverse proxy and request variables

A reverse proxy should preserve the requested host and carry the original client and scheme information in conventional forwarding headers.

nginx
location /api/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

With proxy_pass http://127.0.0.1:3000;, the original request URI is forwarded. In this prefix location, adding a URI slash as proxy_pass http://127.0.0.1:3000/; replaces the matched /api/ prefix, so /api/users is sent upstream as /users.

Table
VariableValue
$hostNormalized request host, with a configured server name as fallback.
$request_uriOriginal request URI, including its query string.
$schemeRequest scheme, usually http or https.
$remote_addrAddress of the direct client connected to NGINX.
$proxy_add_x_forwarded_forExisting forwarded-for chain plus $remote_addr.

Only trust incoming forwarding headers when the network path and real-IP configuration make their source trustworthy.

Redirects and rewrites

Use return for a fixed redirect because it is direct and easy to audit. A 301 is permanent and may be cached aggressively; a 302 is temporary.

nginx
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

location = /maintenance {
    return 302 /status.html;
}

location /old/ {
    rewrite ^/old/(.*)$ /new/$1 permanent;
}
Table
SyntaxResult
return 301 URLPermanent redirect.
return 302 URLTemporary redirect.
rewrite REGEX REPLACEMENT permanentRewrite and return 301.
rewrite REGEX REPLACEMENT redirectRewrite and return 302.
rewrite REGEX REPLACEMENT lastRestart location processing with the rewritten URI.

TLS and HTTP/2

Certificates and private keys are configured in the TLS server block. Protect key files with restrictive filesystem permissions and use complete certificate chains supplied by the certificate issuer.

nginx
server {
    listen 443 ssl;
    http2 on;
    server_name example.com www.example.com;

    ssl_certificate /etc/ssl/example/fullchain.pem;
    ssl_certificate_key /etc/ssl/example/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    root /srv/www/example;
    index index.html;
}

http2 on; is the current syntax and was introduced in NGINX 1.25.1. Older releases enable HTTP/2 with listen 443 ssl http2;; on 1.25.1 and later, the http2 parameter on listen is deprecated in favor of the separate directive. Confirm that the installed build includes the HTTP/2 module before enabling it.

Headers, body size, and rate limiting

limit_req_zone belongs in http; limit_req applies the named zone in a server or location. The zone stores request state keyed here by the binary client address.

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

    server {
        listen 443 ssl;
        server_name api.example.com;

        ssl_certificate /etc/ssl/example/fullchain.pem;
        ssl_certificate_key /etc/ssl/example/privkey.pem;
        client_max_body_size 20m;
        add_header Strict-Transport-Security "max-age=31536000" always;
        add_header X-Frame-Options "SAMEORIGIN" always;

        location /api/ {
            limit_req zone=api_per_ip burst=20 nodelay;
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}
Table
DirectiveEffect
add_header ... alwaysAdd the header across response status codes supported by the module.
Strict-Transport-SecurityTell browsers to use HTTPS for future requests; send it only over HTTPS.
X-Frame-Options SAMEORIGINRestrict framing to the same origin in supporting browsers.
client_max_body_size 20mReject larger request bodies, normally with status 413.
rate=10r/sSet the sustained request rate for a limit zone.
burst=20 nodelayAdmit a bounded burst without delaying accepted excess requests.

Enable HSTS only after HTTPS is dependable for the intended host scope. Rate limiting controls request arrival, not concurrent upstream work.

Validate and reload

Test the full configuration before signaling the master process. A successful reload starts workers with the new configuration and lets old workers finish active requests gracefully.

bash
sudo nginx -t
sudo nginx -T
sudo nginx -s reload
Table
CommandUse
nginx -tCheck syntax and referenced files.
nginx -TTest and print the expanded configuration.
nginx -s reloadAsk the running master process to reload.
systemctl reload nginxReload through systemd on installations that provide the service.

Do not reload after a failed nginx -t; correct the reported file and line first.

References