Структура конфигурации: контексты и директивы
Конфиг Nginx — это вложенные «коробки» (контексты), и настройка из внешней коробки наследуется во внутренние, пока её не переопределят.
«Понял контексты и наследование — понял 80% конфигурации Nginx. Остальное — это словарь директив.»
Вся настройка Nginx живёт в текстовых файлах, главный из которых — nginx.conf. Синтаксис простой и состоит из двух вещей: директивы (одна строка с точкой с запятой) и блоки (директива с фигурными скобками, открывающая контекст).
Директивы и блоки
Простая директива — это имя и значение: worker_processes auto;. Блочная директива открывает контекст и содержит внутри другие директивы:
worker_processes auto; # простая директива (main-контекст)
events { # блок -> контекст events
worker_connections 1024;
}
http { # контекст http
server { # контекст server (виртуальный хост)
listen 80;
server_name example.com;
location / { # контекст location
root /var/www/html;
}
}
}
Иерархия контекстов
Контексты вложены строго: main (самый верх, без скобок) содержит events и http; http содержит server-блоки; server содержит location-блоки. Визуально:
main
|-- events { ... }
|-- http {
| |-- server { (один сайт)
| | |-- location / { ... }
| | +-- location /api/ { ... }
| +-- server { ... } (другой сайт)
| }
Как работает под капотом: наследование
Многие директивы наследуются вниз: если ты задал gzip on; в контексте http, он действует во всех server и location внутри — пока какой-нибудь вложенный контекст не переопределит его своим значением. Это как переменные с областью видимости: внутренний контекст «перебивает» внешний. Поэтому общие настройки кладут повыше (в http), а частные — пониже (в конкретный location).
Важная тонкость: наследование работает по принципу «всё или ничего» для директив-массивов (например, add_header). Если ты добавил add_header в location, то заголовки из родительского контекста не подмешиваются — действуют только заголовки этого location. Это частый источник пропавших заголовков.
Частые ошибки
- Забыть точку с запятой. Каждая простая директива заканчивается
;. Nginx не запустится и скажет, на какой строке проблема. - Ждать наследования
add_headerтам, где его нет. Объявил add_header в location — родительские заголовки пропали. Дублируй явно. - Класть директиву не в тот контекст.
worker_connectionsработает только вevents, аroot— в http/server/location, но не в events.
Best practices
- Общие настройки — в
http, специфичные — ниже. Меньше дублирования. - Разбивай конфиг на файлы и подключай через
include /etc/nginx/conf.d/*.conf;. - Комментируй директивы через
#— будущий ты скажет спасибо.
Как не утонуть в большом конфиге
Реальные конфигурации разрастаются: десятки сайтов, общие ssl-параметры, повторяющиеся блоки proxy_set_header. Чтобы не копировать одно и то же, Nginx даёт директиву include: общие куски выносят в отдельные файлы (например, snippets/ssl.conf или snippets/proxy.conf) и подключают одной строкой в нужных местах. Это и DRY, и единая точка правки: поменял параметры TLS в одном snippet — они применились ко всем сайтам.
Ещё одна вещь, экономящая часы, — переменные Nginx. Значения вроде $host, $request_uri, $remote_addr, $scheme доступны прямо в директивах и наполняются для каждого запроса. Именно из них собирают редиректы (return 301 https://$host$request_uri;) и заголовки для бэкенда. Понимание контекстов и переменных вместе даёт мысленную модель: «где объявить директиву, чтобы она подействовала там, где нужно, и нигде лишнего». Когда конфиг ведёт себя неожиданно, почти всегда дело в одном из двух: либо директива стоит не в том контексте, либо сработало (или не сработало) наследование. Держа в голове иерархию контекстов, ты диагностируешь такие случаи за секунды, а не методом проб и ошибок.
Итоги
Конфигурация Nginx — это вложенные контексты (main, events, http, server, location) с директивами внутри. Настройки наследуются сверху вниз и переопределяются в более глубоких контекстах. Особое внимание — к add_header, который наследование «обнуляет». Дальше разберём, где физически лежат эти файлы и как организовать их по-человечески.