Обновлено:

Nginx location priority

Если Nginx отдаёт не тот файл, не те headers или не тот cache policy, часто причина в том, что сработал не тот location.

Важно понимать порядок выбора.

Основные типы location

location = /exact { ... }
location ^~ /assets/ { ... }
location /prefix/ { ... }
location ~ \.php$ { ... }
location / { ... }

Упрощённый порядок выбора

  1. location = /exact — точное совпадение.
  2. Самый длинный prefix match.
  3. Если prefix был ^~, regex уже не проверяются.
  4. Regex locations ~ и ~*.
  5. Обычный 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.

Хороший порядок:

  1. exact служебные файлы;
  2. assets;
  3. специальные статические paths;
  4. общий 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 работает правильно.