Типичные ошибки конфигурирования Nginx

nginx logo

Следующей шаг при поиске неполадок – разобраться, достигает ли конфигурация поставленных перед ней целей. Интернет вот уже много лет пестрит конфигурациями для NGINX. Зачастую они бы-ли написаны для прежних версий и решали какую-то конкретную задачу. Увы, эти конфигурации копируют бездумно, не понимая, для чего они предназначены. Иногда существует более правильный способ решить ту же задачу, воспользовавшись более современными средствами.


Использование if вместо try_files
Рассмотрим, к примеру, случай, когда требуется доставить пользо-вателю статический файл, если он есть в файловой системе, а в про-тивном случае передать запрос FastCGI-серверу:

server {
root /var/www/html;
location / {
if (!-f $request_filename) {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
break;
}
}
}

Так обычно решалась эта задача до появления директивы trу_ files в версии NGINX 0.7.27. Сейчас такая конфигурация считает-ся ошибкой, потому что if используется внутри location. В разделе «Преобразование конфигурации с ‘if’ в более современную форму» из главы А было объяснено, почему это может иметь неожиданные последствия и даже стать причиной аварийного завершения про-граммы. Правильное решение выглядит так:

server {
root /var/www/html;
location / {
try_files $uri $uri/ @fastcgi;
}
location @fastcgi {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
}
}

Директива try_files смотрит, существует ли файл, и, если нет, передает запрос FastCGI-серверу. Никакие if при этом не нужны.

Использование if для ветвления по имени хоста
Не счесть примеров конфигураций, в которых if используется для переадресации запросов на основе HTTP-заголовка Host. В этом случае конфигурация работает как селектор, вычисляемый для каж-дого запроса:

server {
server_name .example.com;
root /var/www/html;
if ($host ~* ^example\.com) {
rewrite ^/(.*)$ http://www.example.com/$1 redirect;
}
}

Вместо того чтобы тратить ресурсы на вычисление if для каждого запроса, не проще ли воспользоваться обычной процедурой NGINX маршрутизации запросов к подходящему виртуальному серверу? Тогда переадресацию можно поместить туда, где ей место и притом без всякого rewrite:

server {
server_name example.com;
return 301 $scheme://www.example.com;
}
server {
server_name www.example.com;
root /var/www/html;
location / {
…
}
}

Неоптимальное использование контекста server
Еще одно место, где некритичное копирование фрагментов ча-сто приводит к некорректной конфигурации, – это контекст server. В нем описывается виртуальный сервер (все, что адресуется с по-мощью имени, указанного в директиве server_name). Но эта идея в ко-пируемых фрагментах не находит должного отражения.
Часто приходится видеть директивы root и index в каждой секции location:

server {
server_name www.example.com;
location / {
root /var/www/html;
index index.php index.html index.htm;
}
location /ftp{
root /var/www/html;
index index.php index.html index.htm;
}
}

Это может стать причиной ошибок при добавлении нового место-положения, если забыть скопировать туда эти директивы или ско-пировать их неправильно. Смысл директив root и index заключается соответственно в том, чтобы указать корень документов для вир-туального сервера и файлы, которые следует поискать, когда в URI- адресе указан только каталог. Любая секция location наследует эти значения от контекста server.

server {
server_name www.example.com;
root /var/www/html;
index index.php index.html index.htm;
location / {
...
}
location /ftp{
...
}
}

Здесь мы указали, что все файлы находятся в каталоге /var/www/ html и его подкаталогах, и в любом местоположении следует искать файлы index.php, index.html и index.htm именно в таком порядке.

Ошибки написаны на основе горького опыта при разработке сайта remont-komputerov-reutov.ru.