Тестирование конфигурации Nginx: обеспечение плавных развертываний с помощью ключевых команд
Используйте nginx -t, nginx -T и безопасные привычки перезагрузки, чтобы выявить ошибки конфигурации Nginx до того, как они повлияют на трафик.
Тестирование конфигурации Nginx: обеспечение плавных развертываний с помощью ключевых команд
Тестирование конфигурации Nginx — это одна из тех привычек, которые кажутся слишком незначительными, пока не спасут вас от сломанной перезагрузки. Пропущенная точка с запятой, неправильный путь include или директива из модуля, которого у вас нет, могут помешать Nginx принять новую конфигурацию. На рабочем обратном прокси это не мелкая ошибка.
Основная команда проста:
sudo nginx -t
Запускайте её перед каждой перезагрузкой. Запускайте после редактирования server block. Запускайте в CI, если ваша команда хранит конфигурацию Nginx в Git. Команда анализирует конфигурацию и сообщает, корректен ли синтаксис. Она не доказывает, что ваша логика маршрутизации верна, ваш TLS-сертификат действителен для каждого имени хоста или ваше вышестоящее приложение здорово. Она выявляет класс ошибок, которые Nginx может обнаружить до применения конфигурации.
Что проверяет nginx -t
nginx -t указывает Nginx протестировать конфигурацию. Он читает основной конфигурационный файл, обрабатывает директивы include, анализирует директивы и блоки, а также проверяет многие проблемы с файлами/путями. Успешный запуск обычно выглядит так:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Неудачный запуск указывает на файл и номер строки:
nginx: [emerg] unexpected "}" in /etc/nginx/conf.d/api.conf:18
nginx: configuration file /etc/nginx/nginx.conf test failed
Номер строки — это место, где парсер заметил проблему, а не всегда то, где вы допустили ошибку. Если Nginx сообщает о неожиданной } на строке 18, проверьте строки выше на наличие пропущенной точки с запятой или незакрытого блока.
Используйте sudo, когда конфигурационные файлы, файлы сертификатов или включенные сниппеты доступны для чтения только root:
sudo nginx -t
Без правильных разрешений ваш тест может завершиться неудачей, даже если синтаксис в порядке.
Используйте nginx -T, когда include-файлы усложняют просмотр конфигурации
Многие настройки Nginx разделяют конфигурацию между /etc/nginx/nginx.conf, conf.d/*.conf, sites-enabled/* и общими сниппетами. Это хорошо для поддерживаемости, но может затруднить отладку.
nginx -T тестирует конфигурацию и выводит полную разобранную конфигурацию в stdout:
sudo nginx -T
Это полезно, когда вам нужно ответить на такие вопросы:
- Какой файл на самом деле определяет этот server block?
- Подхватил ли мой шаблон
includeрезервный файл? - Устанавливается ли эта директива на уровне
http,serverилиlocation? - Какой дублирующийся блок
server_nameпобеждает?
Будьте осторожны, делясь выводом nginx -T. Он может включать пути к сертификатам, внутренние имена хостов, имена вышестоящих серверов, заголовки или комментарии с конфиденциальным контекстом. Для тикета удалите конфиденциальную информацию перед вставкой.
Тестирование нестандартного конфигурационного файла с помощью -c
Если вы создаете конфигурацию в промежуточном пути, используйте -c:
sudo nginx -t -c /home/deploy/nginx-staging/nginx.conf
Это указывает Nginx, какой основной конфигурационный файл тестировать. Относительные пути внутри этой конфигурации могут вести себя по-разному в зависимости от настроек префикса, поэтому по возможности держите промежуточные тесты близко к рабочей структуре.
Вы также можете просмотреть пути времени компиляции и модули с помощью:
nginx -V
Вывод идет в stderr во многих системах, что удивляет людей при перенаправлении вывода. Он показывает версию Nginx и параметры сборки, включая поддержку модулей и пути по умолчанию. Это важно, когда конфигурация использует директивы из модулей, таких как http_v2, realip, stub_status или потоковое проксирование.
Перезагружайте, а не перезапускайте без необходимости
Как только тест пройден, перезагрузите Nginx:
sudo systemctl reload nginx
Перезагрузка просит главный процесс прочитать новую конфигурацию и запустить новые рабочие процессы, пока старые завершают существующие запросы. Это обычный путь для изменений конфигурации.
Перезапуск останавливает и запускает службу:
sudo systemctl restart nginx
Используйте перезапуск, когда он действительно нужен, например, после изменений пакетов или проблемы с состоянием службы. Для обычных правок конфигурации перезагрузка менее разрушительна.
Некоторые unit-файлы systemd запускают тест конфигурации как часть перезагрузки. Не полагайтесь на это как на единственную защиту. Запустите nginx -t самостоятельно, чтобы увидеть ошибку до того, как затронуть работающую службу.
Родная команда сигнала Nginx также распространена:
sudo nginx -s reload
На серверах, управляемых systemd, я обычно предпочитаю systemctl reload nginx, потому что это сохраняет состояние службы и журналы в одном слое управления.
Безопасный рабочий процесс редактирования
Для обычного изменения server block используйте такой ритм:
sudo cp /etc/nginx/conf.d/api.conf /etc/nginx/conf.d/api.conf.bak.$(date +%Y%m%d%H%M%S)
sudoedit /etc/nginx/conf.d/api.conf
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
Если ваша конфигурация находится в Git, зафиксируйте изменение вместо того, чтобы хранить случайные резервные файлы вечно. Команда резервного копирования выше полезна для небольших неуправляемых серверов, но не заменяет систему контроля версий.
После перезагрузки протестируйте фактический маршрут:
curl -I https://example.com/api/health
curl -I -H 'Host: example.com' http://127.0.0.1/
nginx -t может сказать вам, что конфигурация разбирается. curl говорит вам, ведет ли себя сайт так, как вы задумали.
Частые сообщения об ошибках и что они обычно означают
Пропущенная точка с запятой часто выглядит так:
nginx: [emerg] invalid number of arguments in "proxy_set_header" directive in /etc/nginx/conf.d/app.conf:22
Проверьте директиву в этой строке и строке перед ней. Директивы Nginx обычно заканчиваются на ;, а блоки заканчиваются на { ... }.
Неправильный путь include выглядит так:
nginx: [emerg] open() "/etc/nginx/snippets/security-headers.conf" failed (2: No such file or directory)
Либо путь к файлу неверен, сниппет не был развернут, либо шаблон include зависит от окружения.
Проблема с разрешениями может выглядеть так:
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": BIO_new_file() failed
Файл может отсутствовать, символическая ссылка может быть сломана, или пользователь, запускающий тест, не может его прочитать. Скрипты обновления и развертывания сертификатов — частые места, где это происходит.
Неизвестная директива означает одно из трех: опечатка, неправильный контекст или отсутствующий модуль.
nginx: [emerg] unknown directive "proxy_cache_purge"
Возможно, имя директивы неверно. Возможно, она принадлежит другому модулю. Возможно, ваша рабочая сборка Nginx не включает сторонний модуль, который был на промежуточном сервере. Проверьте nginx -V, прежде чем предполагать, что конфигурация переносима.
Дублирующееся или конфликтующее имя сервера может появиться как предупреждение, а не как жесткая ошибка:
nginx: [warn] conflicting server name "example.com" on 0.0.0.0:80, ignored
Не игнорируйте предупреждения только потому, что последняя строка говорит, что тест прошел успешно. Предупреждение может означать, что Nginx не будет использовать тот server block, который вы думаете.
Тестирование в CI
Если конфигурация Nginx хранится в репозитории, тестируйте ее перед развертыванием. Простая проверка на основе контейнера может смонтировать конфигурацию в образ Nginx и запустить:
nginx -t -c /etc/nginx/nginx.conf
Сложная часть — сопоставление рабочих путей. Если ваша конфигурация ссылается на /etc/letsencrypt, локальным тестам нужны файлы-заполнители или конфигурация, специфичная для теста. Если она ссылается на имена вышестоящих хостов, синтаксический тест не требует, чтобы вышестоящий сервер был жив, но включенные файлы и файлы сертификатов должны существовать.
Для команд с множеством сайтов добавьте шаг перед развертыванием, который запускает nginx -T и сохраняет очищенный вывод как артефакт. Когда перезагрузка ведет себя странно, вы можете сравнить отрисованную конфигурацию из последнего успешного развертывания с текущей.
Что тестирование конфигурации не может выявить
nginx -t не скажет вам, что ваш новый блок location затеняется другим блоком с регулярным выражением. Он не узнает, что ваше вышестоящее приложение возвращает 500. Он не докажет, что цепочка перенаправлений разумна или что правило кэширования безопасно.
Для этого добавьте проверки поведения:
curl -I https://example.com/
curl -I https://example.com/old-path
curl -sS https://example.com/api/health
Для изменений TLS проверьте сертификат с точки зрения клиента:
openssl s_client -connect example.com:443 -servername example.com </dev/null
Для изменений обратного прокси следите за журналами во время и после перезагрузки:
sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log
Тестирование конфигурации Nginx — это не полная стратегия развертывания, но это шлюз, который должна включать каждая стратегия. Используйте nginx -t для синтаксиса, nginx -T для отладки отрисованной конфигурации, nginx -V для деталей сборки и systemctl reload nginx для обычных изменений. Затем проверяйте поведение с помощью реальных запросов.