Skip to content

Chapter 8 of 8

Advanced Routing, Variables, and Security Headers

Some patterns require more than straightforward location matching. For single-page applications using HTML5 history-mode routing, every request should fall through to the application's bootstrap file: location / { try_files $uri $uri/ /index.html; }. The canonical Vue or React snippet then adds a parallel location for fingerprinted assets with long-lived caching: location ~* \.(?:js|css|woff2?|png|jpg|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; }. WebSockets are another special case: the proxy needs HTTP/1.1 with the Upgrade handshake preserved, which is achieved by proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; and a generous proxy_read_timeout 86400; so idle sockets are not closed at the default 60-second mark.

For more flexible conditionals, the if directive is powerful but famously tricky: the official wiki warns that if is "evil" when used outside a location block or when checking request headers. The safe pattern is to test only on built-in variables such as $http_x_custom, or to lift the logic out of if altogether using map and geo. The map directive builds a new variable by matching an input against patterns and is evaluated once per request: map $http_accept_language $lang { default en; ~^fr fr; }. The geo directive does the same thing keyed on the client IP, ideal for geolocation and coarse-grained allow/deny lists. When upstream hostnames must be resolved dynamically (for example, when targeting Consul- or Kubernetes-style service discovery), declare a resolver directive — resolver 1.1.1.1 8.8.8.8 valid=300s; — because nginx does not inherit the system resolver otherwise.

Two related features handle request-handling logic that should never be exposed to clients. A location marked internal; can be reached only via internal redirects (X-Accel-Redirect headers from upstream, error_page handlers, or rewrite ... last), and direct client requests return 404. The X-Accel-Redirect pattern is the canonical way to delegate access-controlled downloads to nginx: the upstream decides whether the user is authorised and returns X-Accel-Redirect: /protected/file.pdf, which nginx then serves from an internal location that enforces its own checks. For streaming large responses such as video or Server-Sent Events, disable buffering explicitly with proxy_buffering off; proxy_cache off; add_header X-Accel-Buffering no; chunked_transfer_encoding on; so nginx does not hold the whole response in memory before forwarding.

Security headers and minor hardening round out a production configuration. The standard set is X-Frame-Options (clickjacking protection, for example SAMEORIGIN or DENY), X-Content-Type-Options: nosniff (stops MIME sniffing), a Referrer-Policy such as strict-origin-when-cross-origin, a Content-Security-Policy appropriate to your application, and a Permissions-Policy. Always pass the always parameter so the headers are added to error responses too. Hidden files should never be reachable: location ~ /\. { deny all; return 404; } blocks /.git, /.env, and similar paths. To strip identifying headers from upstream responses, use proxy_hide_header X-Powered-By;, and to hide the nginx version itself use server_tokens off;. The headers-more module adds more_clear_headers, but it is not part of open-source nginx — the equivalent in vanilla nginx is proxy_hide_header per header name.

All chapters
  1. 1Nginx Fundamentals and Process Model
  2. 2Core Configuration Directives and Performance Knobs
  3. 3HTTP Routing: Servers, Locations, and Rewrites
  4. 4Reverse Proxying, Upstreams, and Backend Protocols
  5. 5Caching and Compression
  6. 6TLS, SSL, and Connection Hardening
  7. 7Access Control, Rate Limiting, and Logging
  8. 8Advanced Routing, Variables, and Security Headers

Drill it

Reading is not remembering. These come from the Nginx Configuration Essentials deck:

Q

What does nginx stand for?

engine x — a high-performance open-source HTTP server, reverse proxy, and IMAP/POP3 mail proxy originally written by Igor Sysoev and first released in 2004...

Q

What is nginx's primary process model?

A single master process that reads configuration, manages sockets, and spawns worker processes (default count = CPU cores). Workers handle all incoming connecti...

Q

How do you reload nginx configuration without dropping connections?

Send SIGHUP to the master process (or run nginx -s reload). The master re-reads config, spawns new workers with the new config, and gracefully shuts down old wo...

Q

What is the difference between <code>nginx -s stop</code> and <code>nginx -s quit</code>?

stop sends SIGTERM to workers and forces them to exit immediately, closing open connections. quit sends SIGQUIT, which lets workers finish serving current reque...