A few NGINX tricks I keep coming back to. NGINX is basically a config language — it runs by directive priority, not top to bottom.
Rewrite with last
Use rewrite with last to stop the current rewrite chain and start a fresh internal request with the new URL:
if ($allow != 1) {
rewrite ^ /__auth_beta$uri last;
}
auth_request Before try_files
auth_request runs before try_files. Since try_files accepts named locations, you can use a fallback location when earlier directives don’t rewrite:
location /__auth_beta {
internal;
auth_request /api/beta/verify-invitation-code;
error_page 401 @coming_soon;
try_files /index.html =404;
}
location @auth_success {
set $allow 1;
rewrite ^ $request_uri last;
}
Conditional Variables with map
map creates variables based on conditions. Handy for flags:
map $http_user_agent $is_bot {
default 0;
~*bot 1;
}
server {
if ($is_bot) {
return 403;
}
}
Rate Limiting
limit_req prevents abuse:
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
server {
location / {
limit_req zone=mylimit burst=5 nodelay;
proxy_pass http://backend;
}
}
}
Geo-based Rules
geo sets variables by client IP. Useful for geo-blocking:
geo $country {
default ZZ;
127.0.0.1 US;
192.168.1.0/24 RU;
}
server {
if ($country = RU) {
return 403;
}
}
Load Balancing
upstream distributes requests across backends:
upstream backend {
server backend1.example.com;
server backend2.example.com;
}
server {
location / {
proxy_pass http://backend;
}
}
Custom Log Format
log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
access_log /var/log/nginx/access.log custom;
}
DNS Resolver for Dynamic Upstreams
If you proxy to a domain name, NGINX resolves it at config load and caches the IP. For dynamic upstreams, set a resolver:
http {
resolver 8.8.8.8 8.8.4.4;
server {
location / {
proxy_pass http://example.com;
}
}
}