Предисловие

Писать особо не о чем, а хочется, поэтому приходится вот такие тупые темы рассматривать. Но вдруг кому-то пригодится.

Зачем?

  1. Несколько стендов приложения. Тестовый, боевой, ещё какой-нибудь… Много их. И для всех нужен немного разный конфиг nginx.
  2. Я хочу держать конфиг nginx в git, потому что в 2k18 этот конфиг уже давно стал частью кода приложения, а не какой-то инфраструктурщиной. То есть нужен контроль версий, code-review и прочие практики.
  3. В то же время я не хочу держать по конфигу на каждый стенд, потому что нет совершенно никакого желания каждый раз при разворачивании стенда писать новый конфиг.
  4. Nginx сам (почти) не умеет в динамическую конфигурацию. Даже значения из ENV жрать не может.

Что делаем?

Пытаемся конфигурировать nginx динамически (ну, почти) с использованием ENV-переменных. Почему ENV? Потому что мне приходится работать с Openshift, в котором конфигурация через ENV является если не единственно возможной (есть ещё всякие config-map’ы), то одной из самых удобных и предсказуемых.

Как?

Очень просто. Шаблонизация.

Какая шаблонизация?

Я знаком с двумя более-менее подходящими шаблонизаторами: ERB и Jinja2. Есть ещё всякие EEX и куча других шаблонизаторов, но с ними было бы не так удобно.

Так как в python я понимаю примерно ничего, то от Jinja2 я отказался. Остался ERB.

Как это всё используем?

Идея простая: при старте nginx генерируем конфиг из шаблона.

Для этого нужно два скрипта: один умеет генерить конфиг из шаблона, второй — запускать первый скрипт перед nginx.

Генерим конфиг

С первой задачей справляется вот этот ruby-скрипт, хотя я уверен, что есть готовые и более элегантные решения. Мне было лень гуглить, поэтому я быстренько накатал своё.

Для примера конфиг с опциональной базовой аутентификацией:

server {
    listen 80 default_server;
    server_name <%= env['SERVER_NAME'] %>;

    <% if env['BASIC_AUTH_ENABLED'] %>
    auth_basic "Restricted Content";
    auth_basic_user_file /etc/nginx/auth/htpasswd;
    <% end %>

    root /public;
    location / {
        try_files $uri $uri/index.html;
    }
}

Стартуем nginx

Со второй задачей всё ещё проще — там справляется обычный bash в пару строк (ну или что там у вас используется для shell-скриптов):

#/bin/bash
/usr/bin/render-template /configs/default.conf.erb /etc/nginx/conf.d/default.conf

nginx -g "daemon off;"

Готово!

Вы восхитительны!

В результате

  1. Конфиг nginx находится в git (что позволяет хотя бы сделать git blame в случае полного провала).
  2. Этот конфиг полностью отвязан от стендов. Я, например, тот же конфиг даже при разработке использую.