# теория · шаг 2 из 4
Контексты: http, server, location
Коротко
Контекст - это блок, внутри которого директива имеет право стоять. У каждой директивы свой список, и он написан в её карточке в документации.
- Вложенность: главный контекст →
eventsиhttp→server→location. Каждый следующий сужает область действия. - Правило выбора: ставь директиву в самый узкий контекст, где она разрешена.
directive is not allowed here- самая честная ошибка nginx: она называет и директиву, и строку.nginx -tумеет сказать «syntax is ok» и тут же провалиться: синтаксис и смысл проверяются разными этапами.
Если разница между http и server очевидна - листай до «Теперь сам».
Сначала ответь сам
Лимит на размер загружаемого файла нужен только админке на /admin/. Куда
поставить client_max_body_size 100m;?
Три места выглядят рабочими: http, server и location /admin/. Все три
пройдут nginx -t. Разница появится через год, и её стоит увидеть заранее.
На что это похоже
Контексты - это уровни правил в здании.
Есть правила всего здания («после девяти тихо»), правила этажа («на третьем не курят»), правила комнаты («тут не есть»). Правило действует на всё, что внутри, и уточняется на уровне ниже. Вывесить «тут не есть» на входной двери можно - табличка повесится, - но это правило всего здания, и однажды на него наткнётся человек из соседней комнаты, который ничего такого не подписывал.
Nginx устроен так же, с одной поправкой: уровень определяет не смысл
правила, а область его действия. Одна и та же строка в http и в location
делает одно и то же, но с разным охватом.
Механизм: шесть контекстов и что каждый значит
# главный контекст: всё, что вне блоков - про процесс целиком
user www-data;
worker_processes auto;
events { # как принимать соединения
worker_connections 4096;
}
http { # всё, что касается HTTP
include mime.types;
gzip on;
server { # один сайт
listen 80;
server_name shop.local;
location /images/ { # одна группа адресов внутри сайта
root /var/www;
}
}
}
stream { } # то же самое, но для TCP и UDP
Это образец целого nginx.conf, класть его вместо своего не надо: он показывает,
как вложены блоки. Три строки в нём новые. worker_connections 4096 - сколько
соединений (открытых каналов между клиентом и nginx) один воркер держит
одновременно; число подбирают под нагрузку, умолчание - 512. include mime.types
подключает файл, лежащий рядом с nginx.conf, - таблицу «расширение файла →
тип содержимого»; путь без каталога nginx считает от /etc/nginx. А
location /images/ отбирает адреса, которые начинаются с /images/; другие
формы записи - в разделе про locationРазбирается в разделе 4, глава «Как выбирается location»: Пять форм записи location.
stream стоит рядом с http, а не внутри: это отдельный мир для TCP и UDP -
способов передачи данных, поверх которых едет и сам HTTP. Там нет ни URL, ни
заголовков, ни location. Пустой stream { } проверку проходит, так что
пример безвреден, а сам stream разобран в отдельном разделеРазбирается в разделе 14, глава «stream: TCP и UDP»: Что такое stream и чем он не HTTP.
Где ты этого не увидишь
В /etc/nginx/conf.d/*.conf блока http обычно нет - и это не ошибка. Файлы
оттуда подключаются директивой include изнутри http в главном
nginx.conf. Server-блок в таком файле уже находится внутри http, просто
открывающая скобка написана в другом файле.
Правило
Ставь директиву в самый узкий контекст, где она разрешена. Каждая строка, поднятая выше необходимого, - это настройка, о которой однажды споткнётся человек, добавивший на сервер новый сайт.
Вернёмся к вопросу из начала урока. Правильный ответ - location /admin/.
В http лимит применится ко всем сайтам сервера, включая будущие; в server -
ко всем страницам этого сайта, в том числе к форме загрузки аватарки, где сто
мегабайт не нужны и вредны.
Разбор: что говорит nginx, когда директива не там
server {
listen 80;
worker_connections 512;
}
nginx: [emerg] "worker_connections" directive is not allowed here in /etc/nginx/conf.d/shop.conf:3
nginx: configuration file /etc/nginx/nginx.conf test failed
Это самая приятная ошибка nginx: названа директива, названа строка, и строка на
этот раз правильная. worker_connections живёт в events - она про то, как
процесс принимает соединения, а не про конкретный сайт.
Обратная сторона: ошибку выдаёт только по-настоящему запрещённое место.
gzip_types разрешена в http, server и location, поэтому написанная в
server она возражений не вызовет - и не должна.
Разбор: где наивное правило подводит
Наивное правило: «прошёл nginx -t - значит, конфиг разобран и понят».
http {
server { listen 80; }
}
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] no "events" section in configuration
nginx: configuration file /etc/nginx/nginx.conf test failed
Две строки подряд говорят противоположное. Так и есть: синтаксис и смысл
проверяются разными этапами. Сначала разбор текста - тут всё в порядке, обе
конструкции языка на месте. Потом модули - части nginx, каждая со своими
директивами, - смотрят на то, что получилось, и
блок events оказывается обязательным.
Практический вывод: читать надо последнюю строку nginx -t, а не первую.
syntax is ok в середине вывода ничего не обещает.
Второе, что ломает наивное правило: не всякая директива разрешена там, где
хочется. set работает в server, location и if (блок-условие внутри
server или location, со своими подвохамиРазбирается в разделе 13, глава «map вместо if»: Чем опасен if),
но не в http. Вот что говорит nginx -t, если поставить set прямо в http:
nginx: [emerg] "set" directive is not allowed here in /etc/nginx/nginx.conf:3
Причина не в прихоти: set выполняется при обработке запроса, а в http
обработки ещё нет - там только настройка. Задать значение на уровне http
можно директивой map, и именно поэтому она существует. Разберём её в уроке
про переменные.
Что ломается без этого
- Настройка расползлась на чужие сайты. Симптом: год спустя на сервере
появился второй сайт, и у него внезапно чужой лимит на тело запроса или чужой
add_header. Ищи вhttpто, что должно было лежать вserver. directive is not allowed hereна директиве, которая точно нужна. Значит, выбран не тот уровень. Открой документацию на https://nginx.org/en/docs/ - у каждой директивы там карточка из строкSyntax:,Default:иContext:, и последняя перечисляет блоки, где директива разрешена. Это нормальный повод открыть документацию, а не признак незнания.- Настройка не действует, хотя написана. Проверь, не лежит ли она в файле,
который подключается не туда, куда ты думаешь:
includeвставляет текст в то место, где стоит сам.
Зачем это в работе
Разбирать чужой сервер приходится чаще, чем настраивать свой. Первый вопрос при этом всегда один: «эта строка про весь сервер или про один сайт?»
Ответ читается по отступу, и это единственное, ради чего в конфиге нужны
отступы: nginx на них не смотрит вообще. nginx -T печатает собранный конфиг с
сохранением вложенности - по нему за минуту видно, какие настройки общие для
всех сайтов, а какие местные.
Теперь сам
Три директивы и три места. Где каждой правильное?
1. gzip on; - сжимать ответы нужно на всех сайтах сервера.
В http. Это как раз тот случай, когда широкий контекст выбран осознанно:
настройка касается всего HTTP-трафика и не создаёт сюрпризов.
2. ssl_certificate /etc/letsencrypt/live/shop.local/fullchain.pem;
В server. СертификатРазбирается в разделе 9, глава «Сертификат, цепочка и ключ»: Что лежит в двух файлах - файл, которым сайт
доказывает браузеру, что он настоящий, - выдан на конкретное имя, и другому
сайту он не подходит.
В http его поставить можно, и это работает как значение по умолчанию, - но
получится сервер, где новый сайт по умолчанию отдаёт чужой сертификат.
3. expires 30d; - кеширование на месяц для картинок и шрифтов.
В location, отобранном по расширению:
location ~* \.(png|jpg|woff2)$ {
expires 30d;
}
~* означает регулярку без учёта регистра, как читать такие шаблоны - в
разделе про locationРазбирается в разделе 4, глава «Как выбирается location»: Пять форм записи location. В server строка expires
велела бы браузеру месяц держать в кеше и главную страницу, и корзину.
Главное
Контексты вложены: главный → http → server → location, и каждый сужает
область действия директивы. Ставь настройку в самый узкий контекст, где она
разрешена; поднятая выше нужного, она однажды удивит человека, который добавит
на сервер новый сайт.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий