Nginx basics cheatsheet.
Install
# Debian/Ubuntu
apt install nginx
# Alpine
apk add nginx
# Docker
docker run -d -p 80:80 nginx
CLI
nginx # start
nginx -t # test config
nginx -T # test + print full config
nginx -s reload # reload
nginx -s stop # stop gracefully (quit)
nginx -s quit # graceful (waits for connections)
nginx -s reopen # reopen log files
nginx -v / nginx -V # version, build info
Config structure
/etc/nginx/
├── nginx.conf # main
├── conf.d/ # included http blocks
│ └── *.conf
├── sites-available/ # Debian: define site configs
├── sites-enabled/ # Debian: enabled (symlinked)
├── mime.types
└── ssl/
nginx.conf skeleton
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
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;
error_log /var/log/nginx/error.log warn;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Server block (virtual host)
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Listen variations
listen 80; # IPv4 all
listen 80 default_server; # default for unmatched
listen [::]:80; # IPv6 all
listen 443 ssl http2;
listen 127.0.0.1:8080;
listen unix:/run/nginx.sock; # unix socket
Locations
location / { ... } # everything (lowest priority)
location = /exact { ... } # exact match (highest)
location /prefix { ... } # prefix match
location ^~ /prefix { ... } # prefix, skip regex
location ~ \.php$ { ... } # case-sensitive regex
location ~* \.(jpg|png)$ { ... } # case-insensitive regex
Match order:
= /exact^~ /prefix(longest)~ regex(first match)- Prefix (longest)
try_files
location / {
try_files $uri $uri/ /index.html; # SPA fallback
try_files $uri @backend; # fall through to upstream
}
location @backend {
proxy_pass http://app;
}
return / rewrite
return 301 https://$host$request_uri;
return 404 "Not Found";
return 200 "OK" application/json;
rewrite ^/old(.*)$ /new$1 permanent;
rewrite ^/api/(.*)$ /v1/$1 last;
Static file serving
server {
listen 80;
server_name static.example.com;
root /var/www/static;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(jpg|jpeg|png|gif|webp|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
Auto-index (directory listing)
location /downloads/ {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /5xx.html;
location = /404.html { internal; root /var/www/errors; }
location = /5xx.html { internal; root /var/www/errors; }
Reload safely
nginx -t && systemctl reload nginx
Reload is graceful: spawns new workers, drains old ones.
Logs
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
Per-server logs:
server {
access_log /var/log/nginx/example.com.access.log main;
error_log /var/log/nginx/example.com.error.log warn;
}
Disable access log:
location = /health {
access_log off;
return 200 "ok";
}
Includes
include /etc/nginx/snippets/ssl.conf;
include /etc/nginx/conf.d/*.conf;
Reuse snippets.
Variables
$host # Host header
$request_uri # /foo?bar=1
$uri # /foo
$remote_addr # client IP
$scheme # http or https
$args # query string
$arg_NAME # specific query arg
$cookie_NAME # cookie
$http_HEADER # request header (e.g. $http_user_agent)
$server_name
$request_method
$request_id
conf reload test workflow
nginx -t # validate
nginx -s reload # apply
systemctl reload nginx # alternative
If invalid: old config stays. No downtime.
Common mistakes
- Forgetting
nginx -tbefore reload. - Wrong
server_nameorder —default_servermatters. - Mixing
try_filesandproxy_passin same location wrong. - Missing
;at end of directive. returnafterrewrite— both not reached.
Read this next
If you want my Nginx config templates, they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .