Nginx location priority
Если Nginx отдаёт не тот файл, не те headers или не тот cache policy, часто причина в том, что сработал не тот location.
Важно понимать порядок выбора.
Основные типы location
location = /exact { ... }
location ^~ /assets/ { ... }
location /prefix/ { ... }
location ~ \.php$ { ... }
location / { ... }
Упрощённый порядок выбора
location = /exact— точное совпадение.- Самый длинный prefix match.
- Если prefix был
^~, regex уже не проверяются. - Regex locations
~и~*. - Обычный prefix fallback, например
location /.
Exact match
location = /404.html {
internal;
}
Exact location подходит для конкретного файла или endpoint.
Он сработает только для точного пути:
/404.html
Prefix match
location /assets/ {
...
}
Сработает для:
/assets/app.js
/assets/style.css
^~ prefix
location ^~ /assets/ {
...
}
Означает: если путь начинается с /assets/, выбрать этот location и не проверять regex.
Это полезно, когда вы точно хотите, чтобы assets не перехватывались regex-правилами.
Regex location
location ~* \.(css|js)$ {
...
}
Regex location гибкий, но может неожиданно перехватить файлы.
Для простого статического сайта часто лучше использовать явные prefix locations.
Типовая схема для статики
location ^~ /assets/ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable" always;
}
location = /404.html {
internal;
}
location / {
try_files $uri $uri/ =404;
add_header Cache-Control "public, must-revalidate" always;
}
Почему /assets/ лучше ставить выше
Даже если порядок не всегда решает всё, читать конфиг проще, когда специфичные правила выше общего fallback.
Хороший порядок:
- exact служебные файлы;
- assets;
- специальные статические paths;
- общий
location /.
Как понять, какой location сработал
Самый простой способ — добавить временный debug header в нужный location:
add_header X-Debug-Location "assets" always;
Потом проверить:
curl -kI https://getsrv.app/assets/example.js | grep -i x-debug-location
После проверки debug header надо убрать.
Частые ошибки
Ошибка 1. Regex перехватывает assets
Например:
location ~* \.(js|css|html)$ {
add_header Cache-Control "public, must-revalidate" always;
}
Так JS/CSS могут получить HTML cache policy вместо immutable.
Ошибка 2. Общий location слишком умный
location / {
try_files $uri /index.html;
}
Это может скрывать реальные 404.
Ошибка 3. add_header не наследуется
Если внутри location есть свой add_header, родительские add_header могут не примениться.
Поэтому security headers лучше либо задавать единообразно, либо проверять каждый важный location через curl -I.
Ошибка 4. Несколько server blocks на один server_name
Проверка:
sudo grep -RIn "server_name getsrv.app" /etc/nginx/sites-enabled /etc/nginx/conf.d
Если один домен описан в нескольких местах, можно долго смотреть не тот config.
Минимальная проверка
curl -kI https://getsrv.app/
curl -kI https://getsrv.app/ru/docs/
curl -kI https://getsrv.app/no-such-page
ASSET="$(find /var/www/getsrv.app/assets -maxdepth 1 -type f | head -n 1 | sed 's#^/var/www/getsrv.app##')"
curl -kI "https://getsrv.app$ASSET"
Проверьте:
- status code;
content-type;cache-control;- security headers.
Если для HTML и assets заголовки разные и ожидаемые, location routing работает правильно.