Технологии

Nginx без магии: как сервер понимает, какой сайт показать

Разбираем порты 80 и 443, server_name, web-root, редиректы и работу нескольких сервисов на одной машине.

Когда DNS уже сделал свою работу, браузер знает IP-адрес сервера. Кажется, что дальше всё просто: запрос пришёл на машину — машина показала сайт. Но на одном сервере могут одновременно жить несколько сайтов, API, панели управления и другие сервисы. Иногда все они используют один IP-адрес.

Возникает вполне разумный вопрос: как сервер понимает, какой именно сайт хочет открыть посетитель? Очень часто ответ — Nginx. Он принимает входящий запрос, смотрит, куда тот пришёл и для какого домена предназначен, выбирает подходящую конфигурацию и решает, что делать дальше: отдать готовый файл, перенаправить пользователя или передать запрос другому приложению.

Кот-диспетчер Nginx направляет запросы example.com, api.example.com и shop.example.com к разным сервисам

Запрос уже пришёл на сервер

В предыдущем материале мы остановились примерно на цепочке домен → DNS → IP-адрес. Теперь браузер знает, к какой машине нужно обращаться.

Дальше начинается новый участок пути:

IPпортNginxнужный сайтответ

Сам IP ещё не говорит серверу, какую страницу нужно показать. Он указывает только на машину. А на этой машине могут находиться основной сайт, поддомен, магазин, API и административная панель.

Сначала — порт

Когда браузер соединяется с сервером, он обращается не просто к IP-адресу, а к определённому порту. Для обычного веба чаще всего используются два: 80 для HTTP и 443 для HTTPS.

Можно представить сервер как большое здание с множеством дверей. IP-адрес приводит нас к зданию. Порт определяет дверь.

Адрес соединения
203.0.113.10:80
203.0.113.10:443

В обычной адресной строке браузера эти номера почти никогда не видны: для HTTP и HTTPS существуют стандартные значения. Когда мы вводим https://example.com, браузер обычно подразумевает порт 443.

Что означает listen

Один из самых простых серверных блоков Nginx может выглядеть так:

Nginx
server {
    listen 80;
}

Эта запись означает: принимай HTTP-запросы, приходящие на порт 80. Для HTTPS часто используется listen 443 ssl;.

Но одного порта недостаточно. Если на 80-м или 443-м порту живёт несколько сайтов, Nginx всё ещё нужно понять, какой из них требуется пользователю. Здесь появляется server_name.

server_name — имя сайта, который ждёт этот блок

Минимальная конфигурация
server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example;
    index index.html;
}

listen 80 говорит, где принимать запрос. server_name — для каких доменных имён предназначена конфигурация. root показывает, где лежат файлы сайта. index сообщает, какой файл считать основной страницей каталога.

Откуда Nginx знает домен

DNS уже превратил доменное имя в IP, но имя не исчезает. Когда браузер отправляет HTTP-запрос, он указывает, какой сайт хочет получить. Упрощённо запрос выглядит так:

HTTP-запрос
GET / HTTP/1.1
Host: example.com

Nginx видит Host: example.com и сравнивает это имя со своими server_name. Если находит подходящий блок, использует его. Поэтому один IP вполне способен обслуживать множество доменов.

Один сервер, один IP, много сайтов

Представим, что на одной машине находятся два сайта:

Два виртуальных хоста
server {
    listen 80;
    server_name cats.example;
    root /var/www/cats;
}

server {
    listen 80;
    server_name dogs.example;
    root /var/www/dogs;
}

У обоих сайтов может быть один и тот же IP. Но браузер сообщает имя сайта. Для cats.example Nginx выбирает первый блок, для dogs.example — второй.

Что такое root

После того как Nginx выбрал нужный сайт, ему нужно понять, где находятся его файлы. Для этого часто используется директива root.

Папка сайта
root /var/www/example;

Если браузер запрашивает https://example.com/about.html, в простой конфигурации Nginx может искать файл по адресу /var/www/example/about.html. Для /images/cat.jpg — в /var/www/example/images/cat.jpg.

Почему открывается index.html

Когда пользователь вводит только https://example.com/, конкретный файл не указан. Но сервер всё равно должен что-то показать.

Главная страница каталога
index index.html;

Если запрошен каталог, Nginx пробует найти внутри него index.html. Это одна из старейших привычек веба: главная страница сайта часто живёт именно в этом файле.

А если файл не найден

Если браузер просит /photo.jpg, а такого файла нет, Nginx не сможет его выдумать. В простом случае сервер ответит 404 Not Found.

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

Nginx может не хранить сайт вообще

Не каждый сайт состоит из готовых HTML-файлов. Современное приложение может работать на Node.js, Python, Go, PHP или другой платформе. Например, приложение слушает внутренний адрес 127.0.0.1:3000.

Reverse proxy
location / {
    proxy_pass http://127.0.0.1:3000;
}

Получается цепочка:

браузерNginxприложениеNginxбраузер

Приложение формирует ответ, Nginx получает его и возвращает браузеру. Такой режим называется reverse proxy — обратным прокси. Название звучит заметно страшнее самого принципа.

Зачем ставить Nginx перед приложением

Технически приложение иногда может принимать внешние запросы напрямую. Но отдельный веб-сервер даёт полезное разделение обязанностей.

🔒HTTPSпринимает TLS и работает с сертификатами
↪️Редиректыпереводит запросы на другой адрес или протокол
📁Файлыбыстро отдаёт HTML, CSS, JS и изображения
🧭Маршрутынаправляет домены и пути нужным сервисам
🛡️Границаскрывает внутренние порты приложений
⚖️Балансировкаможет распределять нагрузку между приложениями

Зачем нужен location

Внутри одного сайта запросы тоже можно разделять. Например, изображения отдавать с диска, а API передавать приложению.

Разные пути — разные действия
location /images/ {
    root /var/www/example;
}

location /api/ {
    proxy_pass http://127.0.0.1:3000;
}

Nginx постепенно уточняет маршрут: на какой порт пришёл запрос → для какого домена → с каким путём → что с ним делать.

Почему существуют порты 80 и 443 одновременно

У большинства современных сайтов конечная точка — HTTPS. Но порт 80 всё равно часто остаётся открытым: он принимает обычный HTTP-запрос и отправляет пользователя на защищённую версию.

HTTP → HTTPS
server {
    listen 80;
    server_name example.com;

    return 301 https://example.com$request_uri;
}

Браузер получает ответ с новым адресом и делает следующий запрос уже через порт 443.

Что происходит на 443-м порту

HTTPS добавляет ещё один слой. Перед обычным HTTP-запросом нужно установить защищённое соединение, а сервер должен предъявить сертификат для нужного домена.

HTTPS-сервер
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/certificate.pem;
    ssl_certificate_key /path/to/private-key.pem;

    root /var/www/example;
}

Поэтому ситуация «DNS работает, но сайт показывает ошибку сертификата» вполне нормальна с точки зрения диагностики. DNS уже выполнил свою часть задачи. Ошибка появилась на следующем уровне.

Как HTTPS выбирает сайт до HTTP-запроса

У HTTPS есть интересная деталь: сначала нужно выбрать сертификат и установить защищённый канал, а заголовок Host появится уже внутри него. Для этого современные браузеры передают имя нужного сайта ещё во время TLS-соединения. Механизм называется SNI — Server Name Indication.

Упрощённо браузер говорит: «Я подключаюсь к этому IP, но хочу сайт example.com». Nginx получает имя достаточно рано, чтобы подобрать подходящую HTTPS-конфигурацию и сертификат.

А если подходящего server_name нет

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

Сервер по умолчанию
listen 80 default_server;

Поэтому прямое открытие IP иногда показывает другой сайт, заглушку Nginx или ошибку. Это не обязательно означает неисправность: сайт может быть настроен исключительно для конкретного домена.

Почему после настройки DNS всё ещё может открываться не тот сайт

Представим: DNS уже возвращает новый IP, запрос точно приходит на нужный сервер, но пользователь видит чужой проект или стандартную страницу Nginx. Значит, проблему уже почти наверняка нужно искать не в DNS.

Проверяем server_name, активность нужной конфигурации, порт, root и то, не перехватывает ли запрос другой default_server.

Не начинайте чинить DNS снова

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

DNS ✓IP ✓портTLSNginxсайт

Как проверить конфигурацию до применения

У Nginx есть полезная привычка: конфигурацию можно проверить прежде, чем применять.

Проверка
nginx -t

Если тест успешен, конфигурацию можно перечитать:

Применение без полного перезапуска
systemctl reload nginx

reload просит уже работающий Nginx принять новую конфигурацию. Для обычных изменений сайта это часто лучше полного restart.

изменитьсохранитьnginx -treloadпроверитьготово

Где обычно живёт конфигурация

Конкретные пути зависят от системы и способа установки. На Linux часто встречается основной файл /etc/nginx/nginx.conf, а конфигурации сайтов — в каталогах /etc/nginx/sites-available/, /etc/nginx/sites-enabled/ или /etc/nginx/conf.d/.

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

Почему конфиг может существовать, но не работать

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

Поэтому вопрос «файл существует?» не равен вопросу «Nginx действительно его читает?». При диагностике нужно проверять именно активную конфигурацию.

Редирект — это не перенос файла

Когда Nginx выполняет return 301, он не берёт страницу с другого адреса и не передаёт её сам. Он отвечает браузеру: «иди по другому адресу». Браузер получает новый URL и делает новый запрос.

Это принципиально отличается от проксирования.

браузерNginxновый адресбраузерновый запрос
браузерNginxсервисNginxбраузер

Несколько сервисов на одной машине

Теперь можно собрать схему, похожую на нашу обложку. На одном сервере находятся основной сайт, API и магазин. DNS всех трёх имён указывает на один IP, а Nginx разделяет запросы.

example.comSITE
api.example.comAPI :3000
shop.example.comSHOP :4000

Для пользователя это три разных сервиса. Для Nginx — три правила маршрутизации. В этом и состоит одна из его главных задач.

Nginx не знает, что вы «имели в виду»

Сервер работает буквально. Если в DNS указан один домен, а в server_name другой, он не догадается, что это почти одно и то же. Если приложение работает на порту 3000, а proxy_pass отправляет на 3001, запрос туда и уйдёт.

Эта строгость иногда раздражает при настройке, но именно она делает поведение сервера предсказуемым. Компьютер не вредничает — он очень последовательно делает не то, что вы хотели, а то, что написали.

Хорошая диагностика идёт по цепочке

Когда сайт не открывается, вместо случайной смены настроек полезнее пройти весь путь запроса.

DNSIPпортTLSNginxмаршрутприложение

Каждый успешно проверенный этап исключает целый класс проблем. Если DNS возвращает правильный IP — идём дальше. Если TLS устанавливается — не возвращаемся к DNS. Если Nginx выбрал правильный блок — проверяем уже файл или приложение.

Как выглядит обычный сайт целиком

Собираем вместе
server {
    listen 80;
    server_name example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/certificate.pem;
    ssl_certificate_key /path/to/private-key.pem;

    root /var/www/example;
    index index.html;

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

Первая часть принимает HTTP и отправляет его на HTTPS. Вторая принимает защищённое соединение. server_name определяет домен, сертификат отвечает за TLS, root указывает папку сайта, а location — правило обработки пути.

Nginx хорош именно потому, что он скучный

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

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