Nginx Cheatsheet - Nginx Configuration & Command Reference

For engineers debugging 502/504s, adjusting location routing, or setting up reverse proxies. The hard part of Nginx is not the sheer number of directives but the details — location matching rules, whether proxy_pass carries a trailing slash, and upstream timeout tuning — which fail silently and only surface as anomalies under traffic. By the end you will validate with nginx -t before reloading, trace upstream errors back to the backend from the error log, and tell apart 502 Bad Gateway from 504 Gateway Timeout.

Web Services·41 commands·Last updated 2026-09-10
nginxReverse ProxylocationConfiguration

Typical Use Case

Configure reverse proxy, load balancing, static file serving and TLS termination; troubleshoot 502/504 gateway errors, redirect loops, config syntax errors, and permission denied (13: Permission denied).

Commands & Testing 5

nginx -t
Test config syntax, always run before reload
nginx -s reload
Graceful reload without dropping connections
nginx -T
Print full effective config, debug include conflicts
systemctl restart nginx
Full restart (drops connections), prefer reload
nginx -V
Show compile flags and enabled modules

Location Matching Priority 5

location = /path
Exact match, highest priority
location ^~ /static/
Prefix match, skip regex check
location ~ \.php$
Case-sensitive regex match
location ~* \.(jpg|png)$
Case-insensitive regex match
location /path
Regular prefix match, lowest priority

Reverse Proxy Snippets 5

proxy_pass http://127.0.0.1:8080;
Forward to backend, trailing slash affects path
proxy_set_header Host $host;
Pass original Host header
proxy_set_header X-Real-IP $remote_addr;
Pass real client IP
proxy_read_timeout 60s;
Backend response timeout, increase for 502 on long requests
client_max_body_size 50m;
Max upload size, increase for 413 errors

Logs & Troubleshooting 4

tail -f /var/log/nginx/error.log
Follow error log, check here first for 502/504
tail -f /var/log/nginx/access.log
Follow access log
grep " 502 " /var/log/nginx/access.log
Filter 502 requests
curl -I http://localhost
View response headers only, quick service check

Process Control & Performance (REQ-02 add-on) 22

nginx -g "daemon off;"
Run in foreground, common way to start nginx in containers
nginx -p /usr/local/nginx -c conf/nginx.conf
Specify prefix directory and config file
kill -s QUIT $(cat /var/run/nginx.pid)
Graceful stop by PID file (same as -s quit)
ps -ax | grep nginx
List nginx master and worker processes
nginx -e /var/log/nginx/error.log
Set error log path at startup
include /etc/nginx/conf.d/*.conf;
Include split-out config files
error_log /var/log/nginx/error.log warn;
Set error log path and severity level
pid /var/run/nginx.pid;
Specify master process PID file path
user nginx;
Set the user that worker processes run as
sendfile on;
Enable zero-copy sending for static files
tcp_nopush on;
Work with sendfile to reduce packets and raise throughput
keepalive_timeout 65;
Set keep-alive connection timeout
server_tokens off;
Hide version number to reduce info leakage
root /data/www;
Set the site root directory
index index.html index.htm;
Specify default index file order
location /images/ { root /data; }
Prefix-match a static directory with its own root
location ~ \.(gif|jpg|png)$ { root /data/images; }
Regex-match image extensions to a directory
fastcgi_pass localhost:9000;
Forward requests to a FastCGI backend
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Set the FastCGI script path parameter
proxy_redirect off;
Disable rewriting of proxied redirect responses
proxy_connect_timeout 60s;
Timeout for establishing a connection to backend
stub_status;
Enable status page for connection and request stats

Parameter matrix

ParameterEffectExample
-tTest the configuration syntax only, without starting anythingnginx -t
-s reloadReload the configuration smoothly without dropping connectionsnginx -s reload
-s stopShut down immediatelynginx -s stop
-cPoint at a specific configuration filenginx -c /etc/nginx/nginx.conf
-gInject global directives at startupnginx -g 'daemon off;'
worker_processesNumber of worker processes, normally set to autoworker_processes auto;
proxy_passForward the request to an upstream serviceproxy_pass http://127.0.0.1:3000;
upstreamDefine a pool of backend servers for load balancingupstream app { server 10.0.0.1; }
try_filesTry each path in order and fall back to the last onetry_files $uri $uri/ /index.html;
return 301Emit a redirect responsereturn 301 https://$host$request_uri;

Common pitfalls

SymptomA configuration change has no effect, or old and new settings mix.

CauseThe file was edited but never reloaded, or the running worker was changed in memory.

FixValidate with nginx -t then apply with nginx -s reload each time; never kill workers, since that severs live connections.

SymptomThe site returns 502 Bad Gateway.

CauseThe upstream behind proxy_pass is down, the port is wrong, or a firewall blocks the connection.

Fixcurl the upstream directly from the nginx host, verify the address, port and backend listener, and look for connect() failed in error.log.

SymptomThe site returns 504 Gateway Timeout.

CauseThe upstream took longer than proxy_read_timeout, which defaults to 60s.

FixRaise proxy_read_timeout and proxy_send_timeout, or shorten the upstream work itself; first rule out an upstream deadlock.

SymptomStatic files return 403 Forbidden and the log shows 13: Permission denied.

CauseThe nginx worker user (typically www-data) cannot read the directory or file, or SELinux blocks it.

FixMake sure directories carry o+x and files carry o+r; with SELinux enabled, allow it via setsebool -P httpd_read_user_content 1.

SymptomHTTP redirects to HTTPS in an endless loop.

CauseTLS is already terminated at the CDN or load balancer layer, and nginx redirects a second time.

FixRedirect at exactly one layer; if the CDN already handles TLS, do not add return 301 https on the nginx side.

Symptomnginx -t reports unknown directive.

CauseThe directive belongs to a module that was not compiled into this binary, such as stub_status or lua.

FixRun nginx -V to list compiled modules; if one is missing, install a package that includes it or rebuild, and stop referencing absent directives.

Troubleshooting

  1. 1Validate the configuration syntax first

    nginx -t

    Mandatory before going live: a bad reload can leave the whole service unable to start.

  2. 2Smoothly reload the new configuration

    nginx -s reload

    Existing connections survive; if an old worker is stuck, use -s quit to let it finish gracefully.

  3. 3Follow the error log to find gateway failures

    tail -f /var/log/nginx/error.log

    502s, 504s and permission problems all leave connect() or permission traces here.

  4. 4Hit the upstream directly from the nginx host

    curl -I http://127.0.0.1:3000/health

    This separates an upstream outage from an nginx configuration mistake.

Command Examples

Validate the config, then reload gracefully

nginx -t nginx -s reload

nginx -t fully parses every include and reports the line number of the first error. A plain restart also takes effect, but nginx -T is the only reliable source of truth when include conflicts are suspected.

Output

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Dump the fully merged config to catch include overrides

nginx -T

When config is split across conf.d files and the same server_name is defined twice, the copy you edited may never have been read. nginx -T prints the final merged result segmented by source file, making overrides obvious at a glance.

Output

# configuration file /etc/nginx/nginx.conf:
...
# configuration file /etc/nginx/conf.d/default.conf:

The trailing slash on proxy_pass decides path concatenation

location /api/ { proxy_pass http://127.0.0.1:8080/; } location /api/ { proxy_pass http://127.0.0.1:8080; }

With the trailing slash, /api/users is rewritten to /users; without it, the path stays /api/users. Which form is correct depends on how the backend routes, and a missing slash shows up as blanket 404s.

Separate connection failures from read timeouts on 502

tail -f /var/log/nginx/error.log nginx -s reload curl -I http://localhost

connect() failed (111: Connection refused) in error.log means the backend is down or the port is wrong, while upstream timed out means it is merely slow and needs a larger proxy_read_timeout in that location.

Debug location matching precedence

location = /exact {} location ^~ /static/ {} location ~* \.(gif|jpg|png)$ {} location / {} nginx -t nginx -s reload

Precedence runs: exact = first, then ^~ prefix, then the ~ and ~* regexes, with plain prefixes last. A regex hit steals paths that ^~ would not have stopped, so "I changed the static rule and nothing happened" usually means this ordering.

Common Pitfalls

  • systemctl restart nginx is a full restart that drops every keepalive connection and fails in-flight requests; use nginx -s reload in production.
  • Whether proxy_pass ends with a slash changes the forwarded path outright, and mixing both styles in one server is notoriously hard to debug — the diff often looks like a single character.
  • client_max_body_size defaults to 1m, so any moderately sized upload returns 413 and the frontend just reports "upload failed" with no actionable message.
  • Placing a directive such as client_max_body_size or proxy_read_timeout outside a server block makes nginx -t fail outright, and the same happens when an included file sits in the wrong scope.
  • nginx -s reload only asks the master to re-read the config; if the syntax is valid but an include path points at the wrong file, the reload "succeeds" while behaviour is completely unchanged.
  • access_log records request lines, not bodies, so putting tokens or passwords in query strings writes them in plaintext into /var/log/nginx/access.log.

Tips

  • Trailing slash in proxy_pass changes semantics: with / replaces location prefix, without it appends.
  • Always run nginx -t before reload — a syntax error won't break the running process but reload won't apply.
  • For 502: check error.log — "connection refused" means backend is down, "timeout" means backend is too slow.

FAQ

How does Nginx decide the order of location matching?

Priority from highest to lowest: exact match with =, then the ^~ prefix (which stops without checking regexes), then regex ~/~* (the first matching regex wins, in config order), and finally plain longest-prefix matching. Both = and ^~ short-circuit immediately, while regex matching waits until all prefix locations have been tried.

When I get a 404, how do I tell whether the location did not match or the backend really returned 404?

Check the error log. If the request never reached the backend, you will only see an access entry, and the proxy_pass target server receives no request; if the backend returned 404, the log shows the upstream response to the backend request. You can also temporarily add a try_files rule or directly curl the backend port to compare.

What is the difference between proxy_pass with and without a trailing slash?

The key difference is path handling. When proxy_pass includes a URI such as http://upstream/api/, the part of the request that matched the location is appended to that path; when it has no URI (http://upstream or http://upstream/), the original request URI is passed through unchanged. Adding a path is how you rewrite /foo to a backend prefix like /api/... .

How do I troubleshoot a 502 Bad Gateway vs a 504 Gateway Timeout?

A 502 means Nginx could not get a valid response from the backend: first confirm the process is alive, the port is listening, and firewall and proxy_pass address are correct. A 504 means the backend exceeded the configured timeout, so check backend processing time first, then raise proxy_read_timeout/proxy_connect_timeout. Always cross-reference the upstream section of the error log in both cases.

Should I restart or reload after changing Nginx config?

Prefer nginx -s reload or systemctl reload nginx: it reloads gracefully without dropping existing connections and validates the config first. Only fall back to systemctl restart when the change touches parameters that cannot be hot-reloaded, such as listen sockets or worker counts, or when reload keeps failing. Always run nginx -t first.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Sep 10, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us