Виртуальные хосты Nginx: Размещение нескольких сайтов на одном сервере
Раскройте возможности виртуальных хостов (server blocks) Nginx для эффективного размещения нескольких сайтов или поддоменов на одном сервере. Это руководство содержит пошаговое обучение: настройка директорий, создание конфигурационных файлов, включение серверных блоков и тестирование Nginx. Изучите лучшие практики для поддоменов, серверных блоков по умолчанию, интеграции HTTPS и выделенного логирования. Практические примеры и советы по устранению неполадок помогут освоить мультисайтовый хостинг Nginx, оптимизируя использование ресурсов и упрощая управление веб-сервером.
Виртуальные хосты Nginx: Размещение нескольких сайтов на одном сервере
Запуск нескольких небольших сайтов с одного сервера — обычная задача для Nginx. У вас может быть корпоративный сайт, сайт документации, промежуточное приложение и клиентский портал — все на одной машине. Nginx разделяет их с помощью блоков server. Пользователи Apache часто называют эту же идею виртуальными хостами, поэтому в руководствах и панелях хостинга вы встретите оба термина.
Важная часть проста: Nginx смотрит на порт, IP-адрес и заголовок Host, затем выбирает соответствующий блок server. Если загружается не тот сайт, проблема обычно не таинственна. Часто это отсутствующая DNS-запись, опечатка в server_name, сервер по умолчанию, перехватывающий запрос, или два файла, претендующих на одно и то же имя.
Понимание серверных блоков Nginx (виртуальных хостов)
По своей сути серверный блок Nginx — это директива конфигурации, определенная в файле конфигурации Nginx (nginx.conf или включенных файлах). Каждый блок server определяет конфигурацию для конкретного виртуального хоста, указывая, как Nginx должен отвечать на запросы для определенного домена или набора доменов. Nginx использует директиву listen для указания IP-адреса и порта, на которых он должен прослушивать, а директиву server_name — для идентификации доменных имен или имен хостов, на которые должен отвечать этот серверный блок.
Когда поступает запрос, Nginx проверяет заголовок Host HTTP-запроса и сравнивает его с директивами server_name настроенных серверных блоков. Затем он обслуживает контент, определенный в соответствующем серверном блоке. Если ни один server_name не совпадает, Nginx обычно использует серверный блок по умолчанию (первый блок server или блок, явно помеченный как default_server).
Предварительные требования
Перед началом убедитесь, что у вас есть следующее:
- Установленный Nginx: Nginx должен быть установлен и запущен на вашем сервере. Если нет, вы обычно можете установить его через менеджер пакетов вашей системы (например,
sudo apt update && sudo apt install nginxна Ubuntu/Debian,sudo yum install nginxна CentOS/RHEL). - Доменные имена: Вам нужно как минимум два доменных имени (например,
example1.comиexample2.com) или поддомена (например,blog.example.comиapp.example.com), которые вы хотите разместить. DNS-записи A/AAAA этих доменов должны указывать на публичный IP-адрес вашего сервера. - Базовая структура каталогов: План, где будут находиться файлы вашего сайта. Распространенная практика —
/var/www/yourdomain.com/html. - Привилегии sudo: Вам понадобится доступ
sudoдля изменения файлов конфигурации Nginx.
Пошаговое руководство по настройке
Давайте настроим два виртуальных хоста: example1.com и example2.com.
Шаг 1: Создание структуры каталогов для сайтов
Сначала создайте корневые каталоги для каждого из ваших сайтов. Здесь будут храниться их HTML, CSS, JavaScript и другие статические файлы. Распространенное расположение — /var/www/.
sudo mkdir -p /var/www/example1.com/html
sudo mkdir -p /var/www/example2.com/html
# Установите владельца как вашего пользователя (замените $USER на ваше имя пользователя), чтобы разрешить редактирование
sudo chown -R $USER:$USER /var/www/example1.com/html
sudo chown -R $USER:$USER /var/www/example2.com/html
# Установите права на чтение для веб-сервера
sudo chmod -R 755 /var/www
Затем создайте простой файл index.html в каждом каталоге для проверки настройки:
Для /var/www/example1.com/html/index.html:
<!-- /var/www/example1.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Добро пожаловать на Example1.com!</title>
</head>
<body>
<h1>Успех! Это Example1.com.</h1>
<p>Этот виртуальный хост работает корректно.</p>
</body>
</html>
Для /var/www/example2.com/html/index.html:
<!-- /var/www/example2.com/html/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Добро пожаловать на Example2.com!</title>
</head>
<body>
<h1>Успех! Это Example2.com.</h1>
<p>Этот виртуальный хост тоже работает!</p>
</body>
</html>
Шаг 2: Создание файлов конфигурации серверных блоков Nginx
Nginx обычно загружает конфигурации серверных блоков из файлов в каталоге /etc/nginx/sites-enabled/. Эти файлы обычно являются символическими ссылками на конфигурации, хранящиеся в /etc/nginx/sites-available/. Такое разделение позволяет хранить конфигурации, которые еще не активны, или легко включать/отключать сайты.
Создайте новый файл конфигурации для example1.com:
sudo nano /etc/nginx/sites-available/example1.com.conf
Добавьте следующее содержимое:
# /etc/nginx/sites-available/example1.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/example1.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example1.com www.example1.com;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example1.com_access.log;
error_log /var/log/nginx/example1.com_error.log;
}
Пояснение директив:
listen 80;: Nginx прослушивает порт 80 (стандартный HTTP).listen [::]:80;— для IPv6.root /var/www/example1.com/html;: Указывает корень документов для этого серверного блока. Nginx будет искать файлы в этом каталоге.index index.html ...;: Определяет файл по умолчанию, который Nginx должен обслуживать при запросе каталога (например, когда кто-то посещаетexample1.com/).server_name example1.com www.example1.com;: Это критически важно. Он сообщает Nginx, что нужно отвечать на запросы дляexample1.comилиwww.example1.com, используя конфигурацию этого серверного блока.location / { ... }: Блок, определяющий, как обрабатывать запросы для определенных URI.try_filesпытается обслужить файл напрямую ($uri), затем каталог ($uri/) и, наконец, возвращает ошибку404 Not Found.access_logиerror_log: Указывает отдельные файлы журналов для этого конкретного сайта, что является хорошей практикой для упрощения отладки и аналитики.
Теперь создайте аналогичный файл конфигурации для example2.com:
sudo nano /etc/nginx/sites-available/example2.com.conf
Добавьте следующее содержимое:
# /etc/nginx/sites-available/example2.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/example2.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example2.com www.example2.com;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example2.com_access.log;
error_log /var/log/nginx/example2.com_error.log;
}
Шаг 3: Включение серверных блоков
Чтобы включить эти конфигурации, создайте символические ссылки из каталога sites-available в каталог sites-enabled. Это сообщает Nginx, что нужно включать эти файлы при запуске.
sudo ln -s /etc/nginx/sites-available/example1.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/example2.com.conf /etc/nginx/sites-enabled/
Шаг 4: Тестирование конфигурации Nginx
Крайне важно проверить конфигурацию Nginx на наличие синтаксических ошибок перед перезагрузкой. Это предотвращает сбой перезапуска 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
Если вы видите какие-либо ошибки, исправьте их в соответствующих файлах конфигурации и повторно запустите sudo nginx -t, пока тест не будет пройден.
Шаг 5: Перезапуск Nginx
Примените новую конфигурацию, перезапустив или перезагрузив Nginx. reload обычно предпочтительнее, так как позволяет Nginx загрузить новые конфигурации без разрыва активных соединений.
sudo systemctl reload nginx
# Или, если перезагрузка не работает или для свежих установок:
sudo systemctl restart nginx
Шаг 6: Обновление DNS-записей
Убедитесь, что DNS-записи A для example1.com, www.example1.com, example2.com и www.example2.com указывают на IP-адрес вашего сервера Nginx. Без правильных DNS-записей ваш браузер не будет знать, где найти ваши сайты.
После завершения распространения DNS (что может занять от нескольких минут до нескольких часов) вы сможете посетить http://example1.com и http://example2.com в вашем веб-браузере и увидеть соответствующие страницы index.html.
Расширенные сценарии и лучшие практики
Размещение поддоменов
Размещение поддоменов (например, blog.example.com, shop.example.com) работает точно так же, как размещение отдельных доменов. Вам просто нужно определить новый серверный блок с поддоменом в качестве server_name.
Пример для blog.example.com:
# /etc/nginx/sites-available/blog.example.com.conf
server {
listen 80;
listen [::]:80;
root /var/www/blog.example.com/html;
index index.html;
server_name blog.example.com;
location / {
try_files $uri $uri/ =404;
}
}
Не забудьте создать каталог (/var/www/blog.example.com/html), создать index.html, создать символическую ссылку и перезагрузить Nginx.
Серверный блок по умолчанию
Хорошей практикой является наличие серверного блока по умолчанию, который перехватывает запросы для доменных имен, не соответствующих ни одной другой директиве server_name на вашем сервере. Это предотвращает обслуживание неизвестных запросов «первым» найденным виртуальным хостом Nginx или позволяет вам обслуживать общую страницу «сайт не найден».
Обычно первый блок server в вашем nginx.conf или sites-enabled неявно является блоком по умолчанию. Вы можете явно указать его с помощью default_server:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Символ подчеркивания `_` — это несуществующее доменное имя, которое никогда не совпадет с реальным запросом.
# Вы также можете использовать localhost.
root /var/www/default_site/html;
index index.html;
location / {
return 444; # Возвращает специфичную для Nginx ошибку 444 (без ответа) для неизвестных хостов
# Или обслуживайте общую целевую страницу:
# try_files $uri $uri/ =404;
}
}
Предупреждение: Если вы определяете блок default_server, убедитесь, что только один блок server на данном порту listen имеет флаг default_server, иначе Nginx запишет предупреждение.
Защита виртуальных хостов с помощью HTTPS (SSL/TLS)
Для производственных сайтов включение HTTPS необходимо. Это включает получение SSL/TLS-сертификата (например, через Let's Encrypt с помощью Certbot) и настройку Nginx на прослушивание порта 443 с сертификатом.
Типичный блок сервера HTTPS выглядит так (после получения сертификатов):
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example1.com www.example1.com;
root /var/www/example1.com/html;
index index.html;
ssl_certificate /etc/letsencrypt/live/example1.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example1.com/privkey.pem;
# Включите другие конфигурации SSL (шифры, протоколы и т.д.)
include /etc/nginx/snippets/ssl-params.conf;
location / {
try_files $uri $uri/ =404;
}
}
# Опционально: перенаправление HTTP на HTTPS для этого домена
server {
listen 80;
listen [::]:80;
server_name example1.com www.example1.com;
return 301 https://$host$request_uri;
}
Обычно иметь отдельный блок сервера HTTP, единственная цель которого — перенаправлять весь трафик на его аналог HTTPS.
Если вы используете Certbot, он может создать или отредактировать эти блоки за вас. Это удобно, но вам все равно следует прочитать результирующий файл. Автоматизированные инструменты для работы с сертификатами иногда добавляют логику перенаправления в место, которое вы бы не выбрали сами, а дублированные перенаправления могут усложнить устранение неполадок.
Ведение журнала для каждого сайта
Как показано в примерах, выделение отдельных файлов access_log и error_log для каждого виртуального хоста является лучшей практикой. Это значительно упрощает отладку проблем и анализ трафика для отдельных веб-сайтов без необходимости просматривать объединенные журналы.
Структура файлов конфигурации
Для более крупных развертываний рассмотрите возможность организации файлов конфигурации Nginx следующим образом:
nginx.conf: Основная конфигурация, включаетconf.d/*.confиsites-enabled/*.conf.d/: Общие настройки для всего сервера (например, Gzip, кэширование).snippets/: Многоразовые фрагменты конфигурации Nginx (например, параметры SSL, общие блокиlocation).sites-available/: Индивидуальные блокиserverдля каждого веб-сайта.sites-enabled/: Символические ссылки на активные конфигурации вsites-available/.
Устранение распространенных проблем
- Ошибка 403 Forbidden: Обычно это означает, что Nginx не имеет прав на чтение файлов или каталогов вашего сайта. Дважды проверьте права на файлы и каталоги (например,
sudo chmod -R 755 /var/www/yourdomain.com/htmlи убедитесь, что пользователь Nginx, обычноwww-dataилиnginx, может их читать). - Ошибка 404 Not Found: Убедитесь, что директива
rootв вашем серверном блоке указывает на правильный каталог и что ваш файлindex.htmlсуществует в этом месте. Также убедитесь, чтоtry_filesнастроен правильно. - Загружается не тот сайт: Это часто указывает на проблему с директивой
server_name. Убедитесь, чтоserver_nameточно соответствует доменному имени, к которому вы пытаетесь получить доступ (включаяwww.или поддомены). Также проверьте свои DNS-записи. - Nginx не запускается/перезагружается: Всегда используйте
sudo nginx -tдля проверки конфигурации перед попыткой перезагрузки или перезапуска Nginx. Сообщения об ошибках укажут строку и файл, где произошла синтаксическая ошибка. - Проблемы с DNS: Если вы можете получить доступ к своему сайту по IP-адресу, но не по доменному имени, это почти наверняка проблема с DNS. Используйте
digилиnslookup, чтобы убедиться, что A-записи вашего домена указывают на правильный IP-адрес сервера.
Тестирование до готовности DNS
Вам не нужно ждать публичного DNS для тестирования стороны Nginx. Вы можете отправить запрос с пользовательским заголовком Host:
curl -H "Host: example1.com" http://203.0.113.10/
curl -H "Host: example2.com" http://203.0.113.10/
Замените 203.0.113.10 на IP вашего сервера. Если каждая команда возвращает правильную тестовую страницу, сопоставление серверных блоков работает. Если обе команды возвращают одну и ту же страницу, проверьте, включены ли оба файла, правильный ли server_name и не перехватывает ли запрос блок по умолчанию.
Для HTTPS тест немного отличается, потому что TLS использует SNI до обработки HTTP-заголовка Host:
curl --resolve example1.com:443:203.0.113.10 https://example1.com/
Эта команда указывает curl подключиться к IP вашего сервера, все еще используя example1.com для TLS и HTTP. Это один из самых быстрых способов протестировать новый виртуальный хост HTTPS до изменения DNS.
Поддерживаемый шаблон для нескольких сайтов
Для нескольких статических сайтов приведенных выше примеров достаточно. Как только вы начнете размещать несколько приложений, повторяйте меньше и централизуйте только те части, которые действительно являются общими. Например, поместите общие заголовки безопасности, сжатие и параметры SSL в сниппеты, но оставьте root, server_name, upstream и журналы каждого сайта видимыми в его собственном файле.
Избегайте копирования большого производственного блока из одного домена в другой без чтения каждой строки. Именно так проникают ошибки server_name, неправильные пути к сертификатам и общие файлы журналов. Практический контрольный список для проверки короток:
- Включает ли
server_nameвсе имена хостов, которые будут вводить пользователи? - Указывает ли
rootилиproxy_passна этот сайт, а не на предыдущий? - Достаточно ли разделены журналы доступа и ошибок для отладки этого сайта по отдельности?
- Проходит ли
nginx -tперед перезагрузкой? - Возвращает ли
curl -H "Host: ..."илиcurl --resolveожидаемый сайт?
Заключительные замечания
Виртуальные хосты Nginx надежны, когда каждый сайт имеет четкий серверный блок, правильный server_name и предсказуемый запасной вариант по умолчанию. Держите файлы скучными. Тестируйте каждое изменение перед перезагрузкой. Используйте выделенные журналы, когда сайты важны. Большинство проблем с несколькими сайтами Nginx становятся легко решаемыми, как только вы можете доказать, какая часть вышла из строя: DNS, TLS/SNI или сопоставление серверных блоков.