Last Updated: May 1, 2025
Configuration Structure
/etc/nginx/nginx.confMain configuration file — worker_processes, events, includes
/etc/nginx/sites-available/Store site configs here (create them)
/etc/nginx/sites-enabled/Symlink from sites-available to enable a site
http { ... }HTTP-level settings: gzip, keepalive, include mime.types
server { ... }Define a virtual host (domain-based or port-based)
location { ... }Match request URI and define behavior within server block
nginx -tTest configuration syntax (always run before reload!)
nginx -s reloadGracefully reload configuration (zero downtime)
Server Blocks (Virtual Hosts)
| Item | Description |
|---|---|
listen 80; | Listen on HTTP port 80 (default_server makes it default) |
listen 443 ssl; | Listen on HTTPS with SSL/TLS |
server_name example.com; | Match requests for this domain |
server_name *.example.com; | Wildcard — match all subdomains |
server_name ~^(www\.)?(.+)$; | Regex server name matching |
return 301 https://$host$request_uri; | Redirect all HTTP to HTTPS |
Reverse Proxy
proxy_pass http://backend:3000;Forward requests to backend server
proxy_set_header Host $host;Pass original Host header to backend
proxy_set_header X-Real-IP $remote_addr;Pass client's real IP address
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;Pass full proxy chain IPs
proxy_set_header X-Forwarded-Proto $scheme;Pass original protocol (http/https)
proxy_read_timeout 60s;Timeout for reading backend response
proxy_buffering off;Disable buffering for streaming/long-polling
Location Block Matching
| Item | Description |
|---|---|
location = /exact | Exact match — highest priority (= prefix) |
location ^~ /prefix/ | Prefix match — stop searching regexes after match |
location ~ \.php$ | Case-sensitive regex match (~ prefix) |
location ~* \.(jpg|png)$ | Case-insensitive regex match (~* prefix) |
location / | General prefix match — lowest priority (catch-all) |
Pro Tip: Use `nginx -t` to test config before reloading. Add `proxy_set_header Host $host` when proxying — without it, apps see localhost instead of real hostname.