Nginx Guide
Nginx (pronounced "engine-ex") is a fast, efficient web server that handles lots of concurrent connections without eating your RAM. It's used for serving sites, routing traffic, and load balancing.
Root vs Alias
This trips up a lot of people at first.
root - Adds the request path to your root directory:
location /admin/ {
root /var/www/locked;
}
Request for /admin/secret.html looks at /var/www/locked/admin/secret.html. Notice it kept the /admin/ part.
alias - Replaces the matched location:
location /admin/ {
alias /var/www/locked/;
}
Same request now looks at /var/www/locked/secret.html. The /admin/ got swapped out.
Always add the trailing slash with alias or things break.
Use root when your URL structure matches your files. Use alias when you want different paths.
Index Files
When someone visits a directory like /admin/, Nginx needs to know what file to show:
server {
root /var/www/html;
index index.html index.htm;
}
It tries each file in order and uses the first one it finds.
Error Pages
Basic setup:
server {
error_page 404 /errors/not_found.html;
error_page 500 502 503 504 /errors/server_error.html;
location ^~ /errors/ {
internal;
}
}
The internal directive prevents direct access to error pages.
For single-page apps, redirect all 404s to index.html:
error_page 404 =200 /index.html;
The =200 changes the status code so your app can handle routing.
Try Files
try_files lets you define fallbacks:
location / {
try_files $uri $uri.html $uri/ /index.html;
}
For /about it tries: exact file, then .html extension, then directory, finally fallback to index.
Great for static-first setups with API fallback:
location / {
try_files $uri @backend;
}
location @backend {
proxy_pass http://127.0.0.1:8080;
}
Request Body Handling
Control how much stays in memory:
client_body_buffer_size 16k;
Anything larger gets written to disk. Bump it up for file uploads:
location /upload/ {
client_body_buffer_size 128k;
client_max_body_size 5G;
}
Specify temp file location:
client_body_temp_path /mnt/ssd/nginx-temp 1 2;
The numbers create nested directories to avoid too many files in one folder.
Method Restrictions
limit_except lists allowed methods, then restricts everything else:
location /admin/ {
limit_except GET {
allow 192.168.1.0/24;
deny all;
}
}
Everyone can GET. Only local IPs can POST/PUT/DELETE.
Make an API read-only:
location /api/ {
limit_except GET HEAD OPTIONS {
deny all;
}
}
Rate Limiting
Limit bandwidth per connection:
location /downloads/ {
limit_rate 500k;
}
Let the first chunk download fast, then throttle:
location /videos/ {
limit_rate_after 10m;
limit_rate 500k;
}
Limit requests per second:
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api/ {
limit_req zone=api burst=20 nodelay;
}
Complete Example
http {
limit_req_zone $binary_remote_addr zone=general:10m rate=50r/s;
server {
listen 80;
server_name example.com;
root /var/www/html;
client_max_body_size 100m;
location / {
limit_req zone=general burst=100 nodelay;
try_files $uri $uri/ /index.html;
}
location /api/ {
limit_rate 2m;
limit_except GET POST {
deny all;
}
proxy_pass http://api_backend;
}
location /admin/ {
limit_except GET {
allow 192.168.1.0/24;
deny all;
}
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
alias /var/www/admin/;
}
error_page 404 /errors/404.html;
error_page 500 502 503 504 /errors/500.html;
location ^~ /errors/ {
internal;
}
}
}
Quick Tips
- Test configs with
nginx -tbefore reloading - Use HTTPS in production
- Watch your logs
- Start simple, add complexity as needed
- Comment your configs
- Check the official docs when stuck
Size Units
- No unit = bytes
korK= kilobytesmorM= megabytesgorG= gigabytes