# теория · шаг 1 из 4
Где живёт конфиг
Коротко
Конфиг nginx - это один файл nginx.conf, в который директивой include
подставляется текст остальных файлов.
include- буквально текстовая подстановка. Отсюда всё остальное: порядок вставки важен, а контекст директивы задаётся местомinclude, а не именем файла.- Маска
conf.d/*.confразворачивается в АЛФАВИТНОМ порядке. - Две традиции живут рядом:
conf.d/от самого nginx иsites-available+sites-enabledот Debian. Файл без симлинка не читается, и ошибки при этом нет никакой. nginx -Tпечатает результат сборки целиком - с него начинается разбор любого чужого сервера.
Если nginx -T уже привычка - листай до «Теперь сам».
Куда смотреть на незнакомом сервере
Открываешь чужой сервер, надо за пять минут понять, какие сайты на нём живут.
Первая мысль - открыть /etc/nginx/nginx.conf. Мысль правильная, но результата
не даст: там будет два десятка строк и пара include.
Обычная раскладка выглядит так:
/etc/nginx/
├── nginx.conf ← главный файл, всё начинается тут
├── conf.d/
│ └── *.conf ← подключается целиком, обычно сюда и пишут
├── sites-available/ ← только в сборках Debian и Ubuntu
├── sites-enabled/ ← симлинки на активные файлы из sites-available
├── mime.types ← соответствие расширений и Content-Type
└── snippets/ ← кусочки, которые включают в несколько мест
Файлов может быть пятнадцать, включений - три уровня, а где-то мог остаться забытый симлинк. Читать это глазами по одному файлу - худший из способов.
На что это похоже
include работает как цитата в документе, вставленная целиком.
Представь договор, в котором написано: «здесь вставить текст приложения 3». Приложение 3 при этом не отдельный документ со своими правилами - его текст буквально становится частью договора в этом самом месте. Пункт из приложения, попавший в раздел «Оплата», относится к оплате, даже если в самом приложении об оплате ни слова.
Ровно так же ведёт себя include: строки подключаемого файла оказываются в том
контексте, где стоит подстановка. Файл не «настраивает сайт» и не «настраивает
сервер» - он настраивает то место, куда его вставили.
Механизм: include - это подстановка текста
Никакой магии в include нет. nginx читает nginx.conf сверху вниз, доходит до
строки
include /etc/nginx/conf.d/*.conf;
и вставляет содержимое найденных файлов прямо сюда. Дальше он продолжает читать получившийся текст так, будто всё было написано в одном файле.
Из этого следуют три вещи, которые и создают почти все сюрпризы:
Контекст задаётся местом вставки. include внутри http вставляет в http,
внутри server - в server. Один и тот же файл-сниппет, подключённый в двух
местах, окажется в двух разных контекстах.
Порядок важен. Маска *.conf разворачивается по алфавиту, и там, где nginx
выбирает первое подходящее, выбор зависит от имён файлов.
Файл вне дерева не существует. Не подключён - значит его нет, и никакой ошибки не будет.
Правило
Один файл на один сайт, имя файла - имя домена.
/etc/nginx/conf.d/shop.local.conf
/etc/nginx/conf.d/admin.shop.local.conf
Через год, когда понадобится поправить один сайт, не придётся вычитывать шестисотстрочную портянку.
Любой разбор начинается с nginx -T. Заглавная T печатает собранный
конфиг целиком, строчная -t только проверяет синтаксис.
Разбор: алфавит решает, кто ответит
На сервере два файла:
server {
listen 80;
server_name shop.local;
root /var/www/shop;
}
server {
listen 80;
server_name old.local;
root /var/www/legacy;
}
Приходит запрос с Host: unknown.example - имя не совпало ни с одним. Кто
ответит?
Ответит первый по порядку блок на этом порту, то есть 01-shop.conf, потому
что маска развернулась по алфавиту и он оказался выше. Никакого
default_server тут нет, и правило «первый на порту» - это умолчание nginx.
Переименуй файлы - и на чужие запросы начнёт отвечать другой сайт. Это и есть причина, по которой имена файлов иногда начинают с чисел: не ради красоты, а чтобы порядок был явным.
Проверить, в каком порядке всё собралось, можно только одним способом:
nginx -T | grep -n "server_name\|listen"
41: listen 80;
42: server_name shop.local;
57: listen 80;
58: server_name old.local;
Номера строк - это строки СОБРАННОГО конфига, и по ним сразу видно, кто идёт первым.
Разбор: где наивное правило подводит
Наивное правило звучит так: «файл лежит в каталоге конфигов - значит работает». Вот два случая, где оно неверно, и оба встречаются постоянно.
Файл в sites-available без симлинка. В сборках Debian сам каталог
sites-available нигде не подключён; подключается sites-enabled, и туда
кладут символические ссылки. Файл, положенный в sites-available и забытый,
не читается вовсе - и nginx -t скажет syntax is ok, потому что синтаксис
действительно в порядке, просто этого текста в конфиге нет.
ls -l /etc/nginx/sites-enabled/
lrwxrwxrwx 1 root root 34 sep 2 21:03 shop -> /etc/nginx/sites-available/shop
Симлинк на удалённый файл. Обратная ситуация: файл из sites-available
удалили, ссылка осталась. Тут nginx как раз ругнётся:
nginx: [emerg] open() "/etc/nginx/sites-available/old" failed (2: No such file or directory)
Первый случай молчит, второй кричит, и молчащий опаснее. Отличать их глазами не надо - надо смотреть на собранный конфиг:
nginx -T | grep -c "server_name shop.local"
Ноль означает, что nginx твой блок не видит, каким бы правильным ни был файл.
Что ломается без этого
«Правлю конфиг, ничего не меняется». Файл вне дерева включений: лежит в
sites-available без ссылки, или имя не подошло под маску *.conf (частая
история с shop.conf.bak и shop.conf.save).
«После переименования файла сайт стал отвечать чужим содержимым». Изменился алфавитный порядок, а с ним - кто отвечает на неизвестные имена.
«Один и тот же сниппет ведёт себя по-разному в двух сайтах». Он подключён в разных контекстах, и директивы внутри действуют на разном уровне.
Зачем это в работе
Первое - приёмка чужого сервера. nginx -T | grep -n "server_name\|listen\|
proxy_pass" за секунду даёт карту: какие сайты объявлены, на каких портах и
куда что уходит. Это быстрее и надёжнее, чем читать пятнадцать файлов.
Второе - переписка с коллегой. К вопросу «почему не работает» всегда стоит
прикладывать вывод nginx -T, а не содержимое одного файла: половина ответов
находится именно в том, что в собранном конфиге этого файла нет.
Теперь сам
Коллега положил новый сайт в /etc/nginx/conf.d/shop.conf.new, сделал
nginx -t (получил syntax is ok), сделал reload и не понимает, почему
сайт не открывается. Что произошло и как это увидеть одной командой?
Ответ. Маска в nginx.conf - include /etc/nginx/conf.d/*.conf, а файл
называется shop.conf.new и под неё не подходит. nginx его не читает, поэтому
-t честно говорит, что синтаксис в порядке: он проверил конфиг, в котором
этого текста нет. Видно это командой nginx -T | grep -c server_name -
блока в собранном конфиге не окажется. Лечится переименованием в
shop.conf. Тот же класс ошибки дают .bak, .save и .orig, оставленные
рядом при правке.
Главное
Конфиг собирается из nginx.conf директивой include, а include - обычная
подстановка текста. Отсюда три следствия: контекст задаётся местом вставки,
маска разворачивается по алфавиту, а файл вне дерева не существует и ошибки не
даёт. Что получилось на самом деле, показывает только nginx -T.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий