Event Block Optimization
events {
worker_connections 4096;
use epoll;
accept_mutex on;
multi_accept on;
}
The worker_connections parameter sets the upper limit of simultaneous connections each worker process handles. The theoretical maximum client capacity equals worker_processes × worker_connections, though actual limits depend on system file descriptor limits and available memory. When operating as a reverse proxy, divide this number by two since each connection requires both upstream and downstream sockets.
Using epoll on Linux kernels provides scalable I/O event notification. The accept_mutex directive mitigates the thundering herd problem by serializing accept() calls among workers, preventing all sleeping processes from waking simultaneously when a new connection arrives. Enabling multi_accept allows a worker process to dequeue all pending connections in a single accept cycle rather than processing them sequentially.
HTTP Context Fundamentals
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
server {
listen 80 default_server;
server_name _;
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
}
}
Virtual Host Deployment Patterns
Name-Based Virtual Hosting
Configure distinct server blocks for different domains within /etc/nginx/conf.d/:
# /etc/nginx/conf.d/desktop.conf
server {
listen 80;
server_name www.desktop.example;
root /var/www/desktop;
index index.html;
}
# /etc/nginx/conf.d/mobile.conf
server {
listen 80;
server_name m.desktop.example;
root /var/www/mobile;
index index.html;
}
Clients must resolve both hostnames to the server IP via DNS or local /etc/hosts entries.
IP and Port-Based Virtual Hosting
server {
listen 192.168.1.50:80;
root /var/www/ip-specific;
}
server {
listen 8080;
root /var/www/port-specific;
}
Root vs Alias Path Resolution
The root directive concatenates the location prefix with the root path:
location /documentation {
root /usr/share/web;
# URI /manual.txt maps to /usr/share/web/documentation/manual.txt
}
The alias directive substitutes the location match entirely:
location /static {
alias /opt/assets/public;
# URI /static/image.png maps to /opt/assets/public/image.png
}
When using alias with regular expression locations, capture groups reference the replacement path:
location ~ ^/resources/(.*)$ {
alias /var/cache/assets/$1;
}
Location Matching Precedence
Nginx evaluates location blocks using a deterministic priority algorithm. When processing a request URI, the engine checks patterns in this sequence:
- Exact match (
=) - URI must match precisely; search terminates immediately - Preferential prefix (
^~) - Prefix match with higher priority than regex; if matched, skips regex testing - Case-sensitive regex (
~) - Regular expression match - Case-insensitive regex (
~*) - Regular expression match ignoring case - Literal prefix (no modifier) - Longest prefix match wins if no regex matches
Priority Demonstration
server {
listen 80;
server_name lab.local;
location = /api/status {
return 200 "Exact match handler\n";
}
location ^~ /api/ {
return 200 "Prefix match - regex bypassed\n";
}
location ~* \.(json|xml)$ {
return 200 "Case-insensitive regex\n";
}
location ~ \.JSON$ {
return 200 "Case-sensitive regex\n";
}
location / {
return 200 "Default fallback\n";
}
}
Request routing examples:
GET /api/status→ Exact match (configuration A)GET /api/users→^~prefix (configuration B); regex.jsonnever testedGET /data.JSON→ Case-sensitive regex~(configuration D) because defined before~*GET /page.html→ Default prefix (configuration E)
Filesytsem Case Sensitivity
While ~* performs case-insensitive URI matching, the underlying filesystem typically remains case-sensitive:
location ~* /assets/.*\.(jpg|jpeg|png)$ {
root /var/www/static;
}
A request for /assets/BANNER.JPG matches this location block, but Nginx returns 404 unless /var/www/static/assets/BANNER.JPG exists exactly. Consider using a map directive or renaming files to lowercase for consistency.
Production Configuration Patterns
server {
# Accelerate root path processing
location = / {
root /var/www/fastpath;
}
# Cache-busted static assets
location ^~ /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
root /var/www;
}
# Dynamic application routes
location ~* ^/(app|api)/ {
proxy_pass http://backend_cluster;
proxy_set_header Host $host;
}
# Legacy file extensions
location ~* \.(gif|ico|css|js)$ {
root /var/www/legacy;
}
}
Access Control Implementation
The access module provides layer-7 IP-based filtering:
location /management {
root /var/www/secure;
deny 10.0.0.1;
allow 10.0.0.0/24;
allow 192.168.1.0/24;
deny all;
}
Directives evaluate sequentially; the first match determines access. Verify module inclusion:
nginx -V 2>&1 | grep -- '--with-http_access_module'
# Or during compilation:
./configure --help | grep access
Basic Authentication
Protect sensitive endpoints using ngx_http_auth_basic_module:
# Install apache2-utils or httpd-tools for htpasswd
htpasswd -c /etc/nginx/.passwd admin
htpasswd /etc/nginx/.passwd developer
location /private {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.passwd;
root /var/www/confidential;
}
For microservices architectures, offload authentication to upstream identity providers rather than managing .htpasswd files across multiple instances.