Nginx Server Blocks: несколько доменов на одном VPS

8 мин чтения·Matthieu|

Подробное руководство по настройке Nginx server blocks на Debian 12 и Ubuntu 24.04. Два домена с нуля, безопасные defaults, логи на сайт и проверка на каждом шаге.

Один VPS может обслуживать десятки сайтов. Nginx использует server blocks для выбора нужного сайта по доменному имени запроса. Это руководство охватывает полную настройку: два домена с нуля, безопасные defaults, логи на каждый сайт и проверка на каждом шаге.

Руководство рассчитано на Debian 12 и Ubuntu 24.04. Оба дистрибутива используют одинаковый паттерн sites-available/sites-enabled. Команды работают идентично на обеих ОС.

Что такое Nginx server block?

Server block (серверный блок) — это блок конфигурации внутри Nginx, определяющий обработку запросов для конкретного домена. Это аналог virtual host в Apache. Каждый server block использует директиву listen для привязки к порту и директиву server_name для сопоставления доменного имени из заголовка Host запроса. Можно иметь сколько угодно server blocks, совместно использующих порт 80 или 443.

Предварительные требования

Перед началом нужно:

  • Установленный и работающий Nginx
  • Два доменных имени с DNS A-записями, указывающими на IP вашего сервера
  • Файрвол с открытыми портами 80 и 443
  • SSH-доступ от имени непривилегированного пользователя с sudo

Проверьте, что Nginx запущен:

sudo systemctl status nginx

В выводе должно быть active (running). Если нет, запустите и добавьте в автозапуск:

sudo systemctl enable --now nginx

Флаг enable добавляет Nginx в автозапуск после перезагрузки. Флаг --now запускает его немедленно.

Проверьте, что DNS-записи разрешаются в IP вашего сервера. Замените домены своими во всём руководстве:

dig +short site-one.com
dig +short site-two.com

Оба должны вернуть публичный IP-адрес вашего сервера.

Как создать server block для нового домена?

Процесс состоит из трёх частей: создать корневую директорию документов, настроить права доступа и написать конфигурационный файл server block. Настроим два домена: site-one.com и site-two.com.

Какую структуру директорий использовать?

Создайте отдельную корневую директорию для каждого сайта в /var/www/:

sudo mkdir -p /var/www/site-one.com/html
sudo mkdir -p /var/www/site-two.com/html

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

echo '<h1>Site One</h1>' | sudo tee /var/www/site-one.com/html/index.html
echo '<h1>Site Two</h1>' | sudo tee /var/www/site-two.com/html/index.html

Какие права нужны для веб-корня?

Nginx запускает рабочие процессы от имени пользователя www-data. Директории веб-корня должны быть читаемы этим пользователем.

sudo chown -R www-data:www-data /var/www/site-one.com
sudo chown -R www-data:www-data /var/www/site-two.com

Установите права 755 (владелец может читать/писать/выполнять, группа и остальные — читать и просматривать):

sudo chmod -R 755 /var/www/site-one.com
sudo chmod -R 755 /var/www/site-two.com

Проверьте владельца и права:

ls -la /var/www/

Ожидаемый вывод:

drwxr-xr-x  2 www-data www-data 4096 Mar 19 10:00 site-one.com
drwxr-xr-x  2 www-data www-data 4096 Mar 19 10:00 site-two.com

Почему www-data, а не ваш пользователь? В продакшене веб-сервер должен владеть статическими файлами. Если приложение пишет файлы (загрузки, кеши), пользователь веб-сервера нуждается в праве на запись. Использование вашего личного пользователя открывает путь от веб-уязвимости к вашему SSH-аккаунту.

Создание конфигурационных файлов server block

Nginx на Debian и Ubuntu использует паттерн двух директорий: конфиги хранятся в /etc/nginx/sites-available/ и активируются симлинком в /etc/nginx/sites-enabled/. Это позволяет отключить сайт без удаления конфига.

Создайте server block для первого домена:

sudo nano /etc/nginx/sites-available/site-one.com
server {
    listen 80;
    listen [::]:80;

    server_name site-one.com www.site-one.com;

    root /var/www/site-one.com/html;
    index index.html;

    access_log /var/log/nginx/site-one.com.access.log;
    error_log /var/log/nginx/site-one.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }
}

Что делает каждая директива:

  • listen 80 и listen [::]:80 привязываются к порту 80 на IPv4 и IPv6.
  • server_name перечисляет доменные имена для этого блока. Укажите оба варианта: без www и с www.
  • root указывает на корень документов для этого сайта.
  • access_log и error_log записывают логи для каждого сайта отдельно. Без них все сайты пишут в общий /var/log/nginx/access.log, что делает отладку болезненной.
  • try_files сначала ищет запрошенный файл, затем пробует его как директорию, затем возвращает 404.

Создайте второй server block:

sudo nano /etc/nginx/sites-available/site-two.com
server {
    listen 80;
    listen [::]:80;

    server_name site-two.com www.site-two.com;

    root /var/www/site-two.com/html;
    index index.html;

    access_log /var/log/nginx/site-two.com.access.log;
    error_log /var/log/nginx/site-two.com.error.log;

    location / {
        try_files $uri $uri/ =404;
    }
}

Как включать и отключать server blocks?

Server blocks в sites-available/ неактивны, пока не созданы симлинки в sites-enabled/.

Включение сайта

Создайте симлинки для обоих доменов:

sudo ln -s /etc/nginx/sites-available/site-one.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/site-two.com /etc/nginx/sites-enabled/

Удалите дефолтный server block, поставляемый с Nginx. Он конфликтует с вашими новыми блоками и показывает страницу "Welcome to Nginx":

sudo rm /etc/nginx/sites-enabled/default

Удаляется только симлинк. Исходный файл остаётся в sites-available/ на случай необходимости.

Тестирование конфига перед применением

Всегда проверяйте конфиг Nginx перед перезагрузкой. Синтаксическая ошибка в одном файле роняет все сайты:

sudo nginx -t

Ожидаемый вывод:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Чтобы увидеть полный итоговый конфиг (все includes раскрыты в один вывод), используйте:

sudo nginx -T

Это лучший инструмент для отладки проблем с server block. Показывает именно то, что загрузит Nginx, включая порядок server blocks.

Reload, а не restart

Примените новый конфиг:

sudo systemctl reload nginx

Почему reload, а не restart? Reload посылает сигнал Nginx на перечитывание конфигурационных файлов. Текущие соединения завершают обработку в штатном режиме. Restart убивает процесс и запускает новый, обрывая все активные соединения. В продакшене всегда используйте reload.

Проверьте успешность reload:

sudo systemctl status nginx

Внимательно смотрите: должно быть active (running), а метка времени на строке "Main PID" не должна измениться (это подтверждает reload, а не restart).

Отключение сайта

Чтобы снять сайт без удаления конфига:

sudo rm /etc/nginx/sites-enabled/site-two.com
sudo nginx -t && sudo systemctl reload nginx

Конфигурационный файл остаётся в sites-available/. Снова активируйте его в любой момент, создав симлинк заново.

Как проверить работу server blocks?

Не открывайте браузер. На headless VPS используйте curl с заголовком Host для симуляции запросов от каждого домена:

curl -H "Host: site-one.com" http://localhost

Ожидаемый вывод:

<h1>Site One</h1>
curl -H "Host: site-two.com" http://localhost

Ожидаемый вывод:

<h1>Site Two</h1>

Это работает даже до распространения DNS, так как вы напрямую указываете Nginx нужный домен через заголовок Host.

После распространения DNS проверьте с локальной машины (не с сервера):

curl http://site-one.com
curl http://site-two.com

Каждый должен вернуть правильную тестовую страницу.

Как Nginx решает, какой server block обрабатывает запрос?

Nginx сопоставляет входящие запросы с server blocks в определённом порядке. При получении запроса Nginx сначала фильтрует server blocks по директиве listen (IP и порт), затем сопоставляет заголовок Host со значениями server_name.

Каков порядок сопоставления server_name?

Порядок сопоставления фиксирован и не изменяется порядком конфигурационных файлов:

Приоритет Тип шаблона Пример Когда используется
1 (высший) Точное имя site-one.com Проверяется первым. Быстрее всего (поиск по хешу).
2 Наидлиннейший wildcard-префикс *.site-one.com Совпадает с www.site-one.com, api.site-one.com
3 Наидлиннейший wildcard-суффикс mail.* Совпадает с mail.site-one.com, mail.site-two.com
4 Первый совпавший regex ~^www\d+\.example\.com$ Проверяется в порядке конфигурационных файлов. Побеждает первое совпадение.
5 (низший) default_server N/A Резервный вариант, когда ничего не совпало.

Ключевые моменты:

  • Точные имена всегда проверяются первыми, независимо от позиции server block в конфиге.
  • Wildcard-имена могут содержать * только в начале или конце, на границе точки. w*.example.com — невалидно.
  • Regex-шаблоны начинаются с ~ и проверяются в порядке их появления в конфигурационных файлах. Побеждает первое совпадение. Используйте их редко: это самый медленный тип сопоставления.
  • Если ничего не совпало и default_server не задан, Nginx использует первый server block в порядке конфигурационных файлов как дефолтный. Это распространённый источник путаницы.

Что делает директива default_server?

Параметр default_server в директиве listen сообщает Nginx, какой server block обрабатывает запросы, когда ни один server_name не совпал. Без него Nginx молча выбирает первый server block, загруженный для этого порта. Это означает, что некорректно настроенный домен или бот, сканирующий ваш IP, получит один из ваших реальных сайтов.

Создайте catch-all (перехватчик по умолчанию) server block, отбрасывающий несовпавшие запросы:

sudo nano /etc/nginx/sites-available/00-catch-all
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    return 444;
}

Что это делает:

  • default_server отмечает этот блок как резервный для порта 80.
  • server_name _ — соглашение для "нет валидного имени". Нижнее подчёркивание не имеет особого смысла для Nginx; оно просто никогда не совпадает с реальным hostname.
  • return 444 — нестандартный код Nginx, закрывающий соединение без отправки какого-либо ответа. Боты, сканирующие ваш IP, не получат ничего: ни заголовков, ни тела, ни информации о вашем ПО.

Активируйте и примените:

sudo ln -s /etc/nginx/sites-available/00-catch-all /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Имя файла начинается с 00-, чтобы он сортировался первым в листинге директории. На поведение Nginx это не влияет (выбором управляет директива default_server, а не порядок файлов), но делает конфиг удобнее для просмотра.

Проверьте catch-all запросом к домену, не совпадающему ни с одним server block:

curl -v -H "Host: not-my-domain.com" http://localhost

Вы должны увидеть Empty reply from server, так как Nginx закрыл соединение без ответа.

Как настроить логи на каждый сайт?

Каждый server block в этом руководстве уже включает директивы логов на сайт. Раздельные логи позволяют отлаживать один сайт, не просматривая трафик всех остальных доменов. Пути логов задаются в каждом server block:

access_log /var/log/nginx/site-one.com.access.log;
error_log /var/log/nginx/site-one.com.error.log;

Просматривайте логи в реальном времени:

sudo tail -f /var/log/nginx/site-one.com.access.log

Или используйте journalctl для логов основного процесса Nginx (ошибки запуска, сбои reload):

journalctl -u nginx -f

Nginx автоматически управляет ротацией логов через /etc/logrotate.d/nginx. Политика по умолчанию ротирует логи ежедневно и хранит 14 дней. Дополнительная настройка не нужна.

Типичные проблемы и решения

Симптом Причина Решение
Для всех доменов показывается "Welcome to Nginx" Симлинк default всё ещё в sites-enabled/ sudo rm /etc/nginx/sites-enabled/default && sudo systemctl reload nginx
Для домена открывается не тот сайт Дублирующийся server_name в разных блоках или не найдено точное совпадение Запустите `sudo nginx -T
Ошибка could not build server_names_hash Доменные имена слишком длинные для дефолтного размера хеш-бакета Добавьте server_names_hash_bucket_size 128; внутрь блока http {} в /etc/nginx/nginx.conf
После редактирования конфига изменения не применяются Забыли сделать reload sudo nginx -t && sudo systemctl reload nginx
bind() to 0.0.0.0:80 failed Другой процесс (Apache, старый Nginx) использует порт 80 `sudo ss -tlnp
Симлинк создан, но сайт не загружается Симлинк указывает на неверный путь (относительный вместо абсолютного) Удалите и пересоздайте: sudo ln -sf /etc/nginx/sites-available/site-one.com /etc/nginx/sites-enabled/

Отладка с помощью nginx -T

Когда сайт ведёт себя не так, как ожидается, выведите полный итоговый конфиг:

sudo nginx -T 2>&1 | grep -A 5 "server_name"

Это показывает каждый server block с его значением server_name, позволяя точно видеть, что загрузил Nginx и в каком порядке. Все директивы include раскрываются, поэтому вы видите реальный конфиг, а не просто файлы на диске.

Что дальше?

Ваши server blocks теперь обслуживают несколько доменов по HTTP. Следующий шаг — добавить TLS-сертификаты для работы сайтов по HTTPS.

Для общего обзора управления Nginx на VPS смотрите родительское руководство.


Copyright 2026 Virtua.Cloud. Vse prava zashchishcheny.

Готовы попробовать?

Разверните свой сервер за секунды. Linux, Windows или FreeBSD.

Смотреть тарифы VPS