What I Wanted to Do
I needed to route different URLs to different handlers in nginx.
The goal was to forward only /api/ paths to a backend server while serving static files directly — but I kept getting the routing wrong because I didn’t understand location matching rules.
Types of location Directives
Exact Match (= modifier)
location = /favicon.ico {
log_not_found off;
access_log off;
}
- Only matches when the URL is exactly this string
- Highest priority of all location types
- Commonly used to suppress logs for favicon and robots.txt
Prefix Match (no modifier)
location /api/ {
proxy_pass http://localhost:3000;
}
- Matches any URL starting with
/api/ - Simplest form — good for most routing needs
Priority Prefix Match (^~ modifier)
location ^~ /static/ {
root /var/www;
}
- Once matched, nginx skips all regex location evaluation
- Use when static files must take priority over regex blocks
Regex Match (~ or ~* modifier)
# Case-sensitive
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
}
# Case-insensitive
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
access_log off;
}
~is case-sensitive,~*is case-insensitive- Often used for static file caching rules
Matching Priority Order
=exact match (highest priority)^~prefix match that skips regex~or~*regex (evaluated in definition order)- Plain prefix match (longest match wins)
Practical Configuration Examples
PHP App with API Routing
server {
listen 80;
server_name example.com;
root /var/www/html;
location = / {
index index.php;
}
location /api/ {
proxy_pass http://localhost:3000/;
proxy_set_header Host $host;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
}
}
Static File Caching
location ~* \.(jpg|jpeg|png|gif|ico|svg|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
Common Pitfalls
- The
=modifier requires an exact URL —/favicon.ico/with a trailing slash is a different path - Regex locations are evaluated in the order they appear, so put more specific patterns first
- A trailing slash in
proxy_passstrips the location prefix:/api/foobecomes/foo - When nesting locations,
aliasreplaces the matched path whilerootappends it — they behave differently - Always test config with
nginx -tbefore reloading:systemctl reload nginx
Related Articles
- nginx Basic Configuration File Structure
- nginx Reverse Proxy Setup for Node.js Apps
- How to Fix nginx 502 Bad Gateway Error
- Setting Up SSL with Let’s Encrypt and Certbot on nginx
- Enable gzip Compression in nginx for Faster Page Loads
Recommended Cloud Hosting
Looking for reliable cloud infrastructure? Check out these developer-friendly services.
- Cherry Servers - High-performance VPS and dedicated servers
- Cloudways - Managed cloud hosting for developers