Имена сервера

Имена с масками
Имена, заданные регулярными выражениями
Прочие имена
Интернационализованные имена
Выбор виртуального сервера
Оптимизация
Совместимость

Имена сервера задаются с помощью директивы server_name и определяют, в каком блоке server будет обрабатываться тот или иной запрос. См. также “Как nginx обрабатывает запросы”. Имена могут быть заданы точно, с помощью маски или регулярного выражения:

server {
    listen       80;
    server_name  example.org  www.example.org;
    ...
}

server {
    listen       80;
    server_name  *.example.org;
    ...
}

server {
    listen       80;
    server_name  mail.*;
    ...
}

server {
    listen       80;
    server_name  ~^(?<user>.+)\.example\.net$;
    ...
}

При поиске виртуального сервера по имени, если имени соответствует несколько из указанных вариантов, например, одновременно подходят и имя с маской, и регулярное выражение, будет выбран первый подходящий вариант в следующем порядке приоритета:

  1. точное имя
  2. самое длинное имя с маской в начале, например “*.example.org
  3. самое длинное имя с маской в конце, например “mail.*
  4. первое подходящее регулярное выражение (в порядке следования в конфигурационном файле)

Имена с масками

Имя с маской может содержать звёздочку (“*”) только в начале или в конце имени, и только на границе, определяемой точкой. Имена “www.*.example.org” и “w*.example.org” являются некорректными, но их можно задать с помощью регулярных выражений, например, “~^www\..+\.example\.org$” и “~^w.*\.example\.org$”. Звёздочка может соответствовать нескольким частям имени. Имени с маской “*.example.org” соответствует не только www.example.org, но и www.sub.example.org.

Специальное имя с маской вида “.example.org” соответствует как точному имени “example.org”, так и маске “*.example.org”.

Имена, заданные регулярными выражениями

Регулярные выражения, используемые в nginx, совместимы с используемыми в языке программирования Perl (PCRE). Имя сервера, заданное регулярным выражением, должно начинаться с символа тильды:

server_name  ~^www\d+\.example\.net$;

в противном случае оно будет рассматриваться как точное, или же, если выражение содержит звёздочку (“*”), то как имя с маской (и, скорее всего, некорректное). Не забывайте ставить специальные символы начала (“^”) и конца (“$”) строки. По синтаксису они не требуются, но логически они могут быть нужны. Также заметьте, что все точки в доменных именах должны быть экранированы символом обратной косой черты. Регулярное выражение, содержащее символы “{” и “}”, необходимо экранировать:

server_name  "~^(?<name>\w\d{1,3}+)\.example\.net$";

иначе nginx откажется запускаться и выдаст сообщение об ошибке:

directive "server_name" is not terminated by ";" in ...

К именованному выделению в регулярном выражении можно впоследствии обратиться через переменную:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;

    location / {
        root   /sites/$domain;
    }
}

Библиотека PCRE поддерживает именованные выделения, используя следующий синтаксис:

?<name> Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0
?'name' Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0
?P<name> Python-совместимый синтаксис, поддерживается начиная с PCRE-4.0
Если nginx отказывается запускаться и выдаёт сообщение об ошибке:

pcre_compile() failed: unrecognized character after (?< in ...

то это значит, что используется старая версия библиотеки PCRE и следует вместо этого попробовать синтаксис “?P<name>”. Также можно использовать нумерованные выделения:

server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/$2;
    }
}

Однако такое использование должно ограничиваться простыми случаями как в примере выше, поскольку нумерованные выделения легко могут быть перезаписаны.

Прочие имена

Некоторые имена имеют специальное значение.

Если необходимо обрабатывать запросы без поля “Host” в заголовке в блоке server, который не является сервером по умолчанию, следует указать пустое имя:

server {
    listen       80;
    server_name  example.org  www.example.org  "";
    ...
}

Если директива server_name не задана в блоке server, то nginx будет использовать пустое имя в качестве имени сервера.

Версии nginx вплоть до 0.8.48 в этом случае использовали имя хоста (hostname) машины в качестве имени сервера.

Если имя сервера задано как “$hostname” (0.9.4), то используется имя хоста (hostname) машины.

Если в запросе вместо имени сервера указан IP-адрес, то поле “Host” заголовка запроса будет содержать IP-адрес, и запрос можно обработать, используя IP-адрес как имя сервера:

server {
    listen       80;
    server_name  example.org
                 www.example.org
                 ""
                 192.168.1.1
                 ;
    ...
}

В примерах конфигурации серверов, обрабатывающих все запросы, встречается странное имя “_”:

server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

Оно не является каким-то особенным, это просто одно из множества некорректных доменных имён, которые никогда не пересекутся ни с одним из реальных имён. С тем же успехом можно использовать имена типа “--” и “!@#”.

Версии nginx вплоть до 0.6.25 поддерживали специальное имя “*”, которое многими неверно воспринималось как имя сервера для обработки всех запросов. Оно никогда так не работало, и не работало как имя с маской. Это имя действовало так же, как сейчас действует директива server_name_in_redirect. Специальное имя “*” объявлено устаревшим, а вместо него следует использовать директиву server_name_in_redirect. Заметьте, что с помощью директивы server_name нельзя задать ни имя сервера для обработки всех запросов, ни сервер по умолчанию. Это является свойством директивы listen, а не server_name. См. также “Как nginx обрабатывает запросы”. Можно настроить серверы, слушающие на портах *:80 и *:8080, и указать, что один из них будет сервером по умолчанию для порта *:8080, а другой — для порта *:80:

server {
    listen       80;
    listen       8080  default_server;
    server_name  example.net;
    ...
}

server {
    listen       80  default_server;
    listen       8080;
    server_name  example.org;
    ...
}

Интернационализованные имена

Для указания интернационализированных доменных имён (IDNs) в директиве server_name следует указывать Punycode-представление имени:

server {
    listen       80;
    server_name  xn--e1afmkfd.xn--80akhbyknj4f;  # пример.испытание
    ...
}

Выбор виртуального сервера

Сначала соединение создаётся в контесте сервера по умолчанию. Затем имя сервера может быть определено на следующих стадиях обработки запроса, каждая из которых участвует в выборе конфигурации:

На каждой из этих стадий могут применяться различные конфигурации сервера. Таким образом, некоторые директивы следует указывать с осторожностью:

Оптимизация

Точные имена, имена с масками, начинающиеся со звёздочки, и имена с масками, заканчивающиеся на звёздочку, хранятся в трёх хэш-таблицах, привязанных к слушающим портам. Размеры хэш-таблиц оптимизируются на фазе конфигурации таким образом, что имя может быть найдено с минимальным числом непопаданий в кэш процессора. Подробнее настройка хэш-таблиц обсуждается в отдельном документе.

В первую очередь имя ищется в хэш-таблице точных имён. Если имя не было найдено, то имя ищется в хэш-таблице имён с масками, начинающихся со звёздочки. Если и там поиск не дал результата, то имя ищется в хэш-таблице имён с масками, оканчивающихся на звёздочку.

Поиск в хэш-таблице имён с масками медленнее, чем поиск в хэш-таблице точных имён, поскольку имена сравниваются по доменным частям. Заметьте, что специальное имя с маской вида “.example.org” хранится в хэш-таблице имён с масками, а не в хэш-таблице точных имён.

Регулярные выражения проверяются последовательно, а значит являются самым медленным и плохо масштабируемым методом.

По вышеизложенным причинам предпочтительнее использовать точные имена, где это только возможно. Например, если к серверу наиболее часто обращаются по именам example.org и www.example.org, то эффективнее будет указать их явно:

server {
    listen       80;
    server_name  example.org  www.example.org  *.example.org;
    ...
}

нежели чем использовать упрощённую форму:

server {
    listen       80;
    server_name  .example.org;
    ...
}

Если задано большое число имён серверов, либо заданы необычно длинные имена, возможно потребуется скорректировать значения директив server_names_hash_max_size и server_names_hash_bucket_size на уровне http. Значение по умолчанию директивы server_names_hash_bucket_size может быть равно 32, 64, либо другой величине, в зависимости от размера строки кэша процессора. Если значение по умолчанию равно 32 и имя сервера задано как “too.long.server.name.example.org”, то nginx откажется запускаться и выдаст сообщение об ошибке:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32

В этом случае следует увеличить значение директивы до следующей степени двойки:

http {
    server_names_hash_bucket_size  64;
    ...

Если задано большое число имён серверов, то будет выдано другое сообщение об ошибке:

could not build the server_names_hash,
you should increase either server_names_hash_max_size: 512
or server_names_hash_bucket_size: 32

В таком случае сначала следует попробовать установить server_names_hash_max_size в величину, близкую к числу имён серверов, и только если это не поможет или время запуска nginx станет неприемлемо большим, следует попытаться увеличить server_names_hash_bucket_size.

Если сервер является единственным сервером для слушающего порта, то nginx не будет проверять имена сервера вообще (а также не будет строить хэш-таблицы для слушающего порта). За одним исключением: если имя сервера задано регулярным выражением с выделениями, то nginx’у придётся выполнить это выражение, чтобы получить значения выделений.

Совместимость

автор: Игорь Сысоев
редактор: Brian Mercer