Skip to main content

Regex

Regex location matching lets NGINX choose a location block using a regular expression applied to the request URI.

It is used when:

  • Paths follow patterns (file extensions, versions, IDs)
  • You need case-insensitive matching
  • Prefix matching is not flexible enough

Regex Location Modifiers

ModifierMeaning
~Case-sensitive regex match
~*Case-insensitive regex match
location ~ pattern {
...
}

location ~* pattern {
...
}
  • pattern is a PCRE regular expression
  • Applied to the URI only (query string ignored)
  • No quotes required

Case-Sensitive Regex (~)

location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
}

What it matches

URIMatch?
/index.phpYes
/test.phpYes
/TEST.PHPNo

Because matching is case-sensitive.

Case-Insensitive Regex (~*)

location ~* \.(jpg|jpeg|png|gif)$ {
expires 30d;
}

What it matches

URIMatch?
/img/a.jpgYes
/img/A.JPGYes
/img/b.PnGYes

Location Matching Order (Critical!)

NGINX evaluates locations in this order:

  1. Exact match (location =)
  2. Prefix match (longest match wins)
  3. Regex match (first match wins)
  4. Default (location /)

Regex locations are evaluated in the order they appear in the config.

Prefix vs Regex (Who Wins?)

location /images/ {
root /var/www/images;
}

location ~ \.jpg$ {
root /var/www/jpg;
}
  • Request: /images/photo.jpg
  • Result:
    • Prefix /images/ matches
    • Regex \.jpg$ also matches
    • Regex wins, because it’s checked after prefix

Prevent Regex Override with ^~

location ^~ /images/ {
root /var/www/images;
}
  • Prefix match is selected
  • Regex is skipped entirely

Regex Order Matters (First Match Wins)

location ~ \.php$ {
return 200 "Generic PHP";
}

location ~ /admin/.*\.php$ {
return 403;
}
  • Request: /admin/test.php
  • Result:
    • First regex matches
    • Access is allowed unintentionally

Correct order

location ~ /admin/.*\.php$ {
return 403;
}

location ~ \.php$ {
return 200 "Generic PHP";
}

Using Capture Groups in Regex Locations

location ~ ^/api/v(\d+)/ {
proxy_pass http://api_v$1_backend;
}
  • Request: /api/v2/users
    • $1 = 2
    • Proxied to api_v2_backend

Regex with rewrite

location ~ ^/old/(.*)$ {
rewrite ^/old/(.*)$ /new/$1 permanent;
}

Common Use Cases

  1. File extension handling
location ~* \.(css|js)$ {
expires 7d;
}
  1. Blocking sensitive files
location ~* \.(env|log|bak)$ {
deny all;
}
  1. Language or version routing
location ~ ^/(en|fr|de)/ {
root /var/www/lang;
}

Regex Matching Details You Must Know

  • Regex applies to normalized URI
  • Query string (?x=1) is ignored
  • Use ^ and $ for precision
  • Avoid overly complex patterns (performance)