Как настроить Nginx для прослушивания нескольких портов
Nginx может одновременно прослушивать несколько портов, добавляя несколько директив `listen` внутри одного или нескольких блоков `server` в своей конфигурации. Каждая директива `listen` привязывает Nginx к определённой комбинации IP/порт, позволяя одному экземпляру сервера обрабатывать HTTP, HTTPS и трафик пользовательских приложений на отдельных портах без запуска отдельных процессов.
Эта возможность необходима для мультитенантных сред, разделения портов staging/production, архитектур обратного прокси и маршрутизации микросервисов — всё это с одного экземпляра VPS Хостинга.
Предварительные требования
Перед началом убедитесь в следующем:
- Nginx установлен и служба активна (`systemctl status nginx`)
- У вас есть привилегии `root` или `sudo` на сервере
- Вы понимаете разницу между `/etc/nginx/nginx.conf` (глобальная конфигурация) и `/etc/nginx/sites-available/` (блоки конфигурации для отдельных сайтов)
- Правила брандмауэра (`ufw`, `iptables` или облачная группа безопасности) разрешают трафик на портах, которые вы намерены открыть
- Действительные SSL-сертификаты доступны при настройке HTTPS-портов (самоподписанные или выданные CA)
Архитектура конфигурации Nginx: что нужно знать прежде всего
Nginx использует иерархическую модель конфигурации: контекст `http` содержит один или несколько блоков `server`, каждый из которых может содержать одну или несколько директив `listen`. Понимание этой иерархии позволяет избежать наиболее распространённых ошибок конфигурации.
Ключевые задействованные директивы:
- `listen [address:]port [ssl] [http2] [default_server]` — привязывает блок сервера к определённому порту и необязательному IP
- `server_name` — сопоставляет заголовок `Host` для маршрутизации запросов к правильному блоку
- `default_server` — определяет, какой блок сервера обрабатывает запросы, не соответствующие ни одному другому `server_name`
Расположение файлов конфигурации по дистрибутивам:
| Дистрибутив | Основной конфиг | Конфиги сайтов |
|---|
| — | — | — |
|---|
| Ubuntu / Debian | `/etc/nginx/nginx.conf` | `/etc/nginx/sites-available/` |
|---|
| CentOS / RHEL / AlmaLinux | `/etc/nginx/nginx.conf` | `/etc/nginx/conf.d/` |
|---|
| Arch Linux | `/etc/nginx/nginx.conf` | `/etc/nginx/sites-available/` |
|---|
| Docker (официальный образ) | `/etc/nginx/nginx.conf` | `/etc/nginx/conf.d/` |
|---|
В системах на основе Debian файлы в `sites-available/` должны быть символически связаны с `sites-enabled/` для вступления в силу:
“`bash
sudo ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled/
“`
Шаг 1: Откройте файл конфигурации Nginx
Для глобального изменения, затрагивающего все виртуальные хосты:
“`bash
sudo nano /etc/nginx/nginx.conf
“`
Для конфигурации конкретного сайта (рекомендуется для production):
“`bash
sudo nano /etc/nginx/sites-available/example.conf
“`
Использование файлов для конкретных сайтов настоятельно предпочтительно. Это изолирует изменения, упрощает откат и предотвращает ситуацию, когда одна ошибка конфигурации выводит из строя все размещённые сервисы.
Шаг 2: Настройте несколько директив listen в одном блоке server
Простейшая многопортовая настройка привязывает один блок сервера к нескольким портам. Nginx будет применять идентичную логику маршрутизации независимо от того, через какой порт подключился клиент.
“`nginx
server {
listen 80;
listen 8080;
server_name example.com;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example_access.log;
error_log /var/log/nginx/example_error.log warn;
}
“`
Что это делает:
- `listen 80;` — принимает стандартный HTTP-трафик
- `listen 8080;` — принимает трафик на альтернативном HTTP-порту (распространено для сред разработки, внутренних API или проверок работоспособности балансировщика нагрузки)
- Оба порта обслуживают идентичный контент из `/var/www/html`
Граничный случай — привязка к определённому IP-адресу: На сервере с несколькими сетевыми интерфейсами (например, публичный IP и частный LAN IP) можно ограничить, на каком интерфейсе Nginx прослушивает:
“`nginx
listen 192.168.1.10:8080;
listen 0.0.0.0:80;
“`
Это критически важно в конфигурациях серверов с несколькими сетевыми интерфейсами для предотвращения непреднамеренного публичного раскрытия внутренних сервисов.
Шаг 3: Настройте HTTPS на нескольких портах
HTTPS требует параметра `ssl` в директиве `listen` и действительных путей к сертификату/ключу. Следующий пример привязывает HTTPS как к стандартному порту 443, так и к пользовательскому порту 8443:
“`nginx
server {
listen 443 ssl;
listen 8443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
Modern TLS hardening
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
“`
Почему порт 8443 часто используется:
- Позволяет HTTPS-трафику в средах, где порт 443 заблокирован вышестоящими брандмауэрами
- Используется в разработке/staging для запуска защищённого сервера без конфликта с production-сервисом на порту 443
- Требуется некоторыми фреймворками приложений (Tomcat, прокси Node.js), которые предоставляют HTTPS на нестандартных портах
Критическая ошибка: Пропуск `ssl_protocols` и `ssl_ciphers` оставляет Nginx с потенциально слабыми настройками по умолчанию. Всегда явно определяйте параметры TLS, особенно на серверах, обрабатывающих конфиденциальные данные. Если вам нужен доверенный сертификат, а не самоподписанный, SSL-сертификаты от признанного CA устраняют предупреждения браузера и удовлетворяют современным требованиям HSTS.
Шаг 4: Обслуживайте разный контент на разных портах
Когда порты должны обслуживать отдельные приложения — например, публичный веб-сайт на порту 80 и внутреннюю панель администратора на порту 8080 — используйте отдельные блоки `server`:
“`nginx
server {
listen 80;
server_name example.com;
root /var/www/public;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 8080;
server_name example.com;
root /var/www/admin;
index index.html;
Restrict admin panel to internal network only
location / {
allow 10.0.0.0/8;
allow 192.168.0.0/16;
deny all;
try_files $uri $uri/ =404;
}
}
“`
Реальные сценарии использования разделения контента по портам:
- Порт 80/443: Публичный веб-сайт
- Порт 8080: Внутренний REST API или конечная точка микросервиса
- Порт 8443: Защищённая панель администратора с ограничением по списку разрешённых IP
- Порт 9000: Конечная точка метрик для сбора данных Prometheus (никогда не открывается публично)
- Порт 3000/5000: Обратный прокси к приложению Node.js или Python
Шаг 5: Использование Nginx в качестве обратного прокси на нескольких портах
Распространённый production-паттерн — использование Nginx для проксирования разных портов к разным серверам бэкенд-приложений:
“`nginx
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 8080;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
“`
Этот паттерн является основой контейнеризованных развёртываний на Выделенном сервере, где несколько Docker-контейнеров работают на разных внутренних портах, а Nginx выступает единственной внешней точкой входа.
Шаг 6: Проверьте конфигурацию
Никогда не перезапускайте Nginx без предварительного тестирования синтаксиса конфигурации. Синтаксическая ошибка приведёт к тому, что служба не сможет перезагрузиться, что выведет из строя все размещённые сайты.
“`bash
sudo nginx -t
“`
Ожидаемый вывод при успехе:
“`
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
“`
При наличии ошибок вывод укажет файл и номер строки. Исправьте все обнаруженные проблемы перед продолжением.
Для перезагрузки без простоя (предпочтительнее полного перезапуска в production):
“`bash
sudo systemctl reload nginx
“`
Полный перезапуск необходим только при изменении `worker_processes`, `user` или других директив уровня мастер-процесса:
“`bash
sudo systemctl restart nginx
“`
Шаг 7: Убедитесь, что Nginx прослушивает правильные порты
После применения конфигурации убедитесь, что Nginx привязался к ожидаемым портам, используя `ss` (предпочтительнее устаревшего `netstat`):
“`bash
sudo ss -tlnp | grep nginx
“`
Пример вывода:
“`
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
LISTEN 0 511 0.0.0.0:8080 0.0.0.0:* users:(("nginx",pid=1234,fd=7))
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1234,fd=8))
LISTEN 0 511 0.0.0.0:8443 0.0.0.0:* users:(("nginx",pid=1234,fd=9))
“`
Если порт не отображается, проверьте:
- Синтаксис директивы `listen` в файле конфигурации
- Не занят ли этот порт другим процессом: `sudo ss -tlnp | grep :8080`
- Прошла ли проверка `nginx -t` без ошибок
- Политики SELinux или AppArmor, которые могут блокировать привязку к нестандартным портам
Тестирование с помощью curl из командной строки (надёжнее браузера для отладки):
“`bash
curl -I http://example.com
curl -I http://example.com:8080
curl -Ik https://example.com
curl -Ik https://example.com:8443
“`
Флаг `-I` получает только заголовки. Ответ `200 OK` или `301 Moved Permanently` подтверждает, что порт активен и Nginx отвечает корректно.
Шаг 8: Откройте порты брандмауэра
Прослушивание порта в Nginx недостаточно, если брандмауэр хоста блокирует входящие соединения. Убедитесь, что порты разрешены:
UFW (Ubuntu/Debian):
“`bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 8443/tcp
sudo ufw reload
“`
firewalld (CentOS/RHEL/AlmaLinux):
“`bash
sudo firewall-cmd –permanent –add-port=8080/tcp
sudo firewall-cmd –permanent –add-port=8443/tcp
sudo firewall-cmd –reload
“`
iptables (напрямую):
“`bash
sudo iptables -A INPUT -p tcp –dport 8080 -j ACCEPT
sudo iptables -A INPUT -p tcp –dport 8443 -j ACCEPT
“`
В облачной инфраструктуре (AWS EC2, DigitalOcean, Hetzner) необходимо также обновить группу безопасности или правила облачного брандмауэра на уровне провайдера — изменений брандмауэра на уровне хоста недостаточно.
Сравнение: однопортовые и многопортовые конфигурации Nginx
| Функция | Один порт | Несколько портов (один блок) | Несколько портов (отдельные блоки) |
|---|
| — | — | — | — |
|---|
| Сложность конфигурации | Низкая | Низкая | Средняя |
|---|
| Изоляция контента | Отсутствует | Отсутствует | Полная |
|---|
| Контроль доступа по порту | Не применимо | Невозможно | Полностью поддерживается |
|---|
| Сценарий использования | Простые веб-сайты | Зеркала dev/staging | Микросервисы, панели администратора |
|---|
| Обратный прокси по порту | Один upstream | Один upstream | Независимые upstream |
|---|
| Терминация SSL | На блок | Общий сертификат | Независимые сертификаты на блок |
|---|
| Разделение логов | Единый лог | Единый лог | Файлы логов по портам |
|---|
Распространённые ошибки и способы их избежать
Конфликт портов с существующими сервисами: Порт 80 может уже использоваться Apache. Выполните `sudo ss -tlnp | grep :80` перед настройкой. Остановите конфликтующие сервисы или перенастройте их на использование других портов.
Конфликты `default_server`: Если несколько блоков сервера опускают `default_server` или несколько блоков претендуют на него для одного порта, Nginx будет использовать первый блок в порядке файлов. Будьте явными:
“`nginx
listen 80 default_server;
“`
IPv6 не охвачен: Добавление `listen 80;` привязывает только к IPv4. Для серверов с двойным стеком добавьте:
“`nginx
listen [::]:80;
listen [::]:8080;
“`
SELinux блокирует нестандартные порты: На RHEL/CentOS с принудительным SELinux Nginx не может привязываться к портам, не включённым в его политику, без явного разрешения:
“`bash
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage port -a -t http_port_t -p tcp 8443
“`
Забыли перезагрузить после изменений: Правки конфигурации не вступают в силу до перезагрузки Nginx. Автоматизируйте это в CI/CD-пайплайнах с шагом `nginx -t && systemctl reload nginx` после развёртывания.
Практическая матрица решений
Используйте этот контрольный список для определения правильного паттерна многопортовой конфигурации для вашего сценария:
- Одинаковый контент, несколько портов — Используйте несколько директив `listen` в одном блоке `server`
- Разный контент по портам — Используйте отдельные блоки `server` с разными директориями `root`
- Разные бэкенд-приложения по портам — Используйте отдельные блоки `server` с `proxy_pass`, указывающими на разные адреса upstream
- Защита нестандартного порта — Добавьте `ssl` к директиве `listen` и укажите пути к сертификатам; убедитесь, что SAN сертификата охватывает домен
- Ограничение порта для внутреннего трафика — Добавьте директивы `allow`/`deny` или привяжите `listen` только к частному IP
- Работа на VPS с cPanel — Убедитесь, что встроенная конфигурация Apache/Nginx в cPanel не конфликтует; используйте «Include Editor» cPanel или выделенную директорию drop-in конфигурации Nginx
- Управление несколькими вариантами панелей управления — Ознакомьтесь с доступными Панелями управления VPS, чтобы найти ту, которая предоставляет управление портами Nginx через GUI
Часто задаваемые вопросы
Может ли Nginx прослушивать один и тот же порт в нескольких блоках server?
Да. Несколько блоков `server` могут использовать один и тот же порт. Nginx различает их с помощью директивы `server_name`, которая сопоставляет HTTP-заголовок `Host`. Если ни один `server_name` не совпадает, запрос обрабатывает блок `default_server`.
Влияет ли добавление большего количества портов listen на производительность Nginx?
Накладные расходы незначительны. Каждая директива `listen` добавляет файловый дескриптор к мастер-процессу Nginx. Практический предел — это потолок открытых файловых дескрипторов системы (`ulimit -n`), а не количество портов. Для высоконагруженных развёртываний настройте `worker_rlimit_nofile` и `worker_connections` в `nginx.conf`.
Как перенаправить весь трафик с порта 8080 на порт 80?
Используйте выделенный блок сервера с директивой `return`:
“`nginx
server {
listen 8080;
server_name example.com;
return 301 http://example.com$request_uri;
}
“`
Почему Nginx не прослушивает порт, хотя конфигурация выглядит правильной?
Четыре наиболее распространённые причины: (1) конфигурация не была перезагружена после редактирования, (2) другой процесс уже привязан к этому порту, (3) правило брандмауэра блокирует порт, или (4) SELinux/AppArmor препятствует привязке. Систематически проверяйте каждую причину с помощью `ss -tlnp`, `nginx -t` и команд проверки статуса брандмауэра.
Можно ли использовать разные SSL-сертификаты для разных HTTPS-портов на одном домене?
Да. Каждый блок `server` имеет собственные директивы `ssl_certificate` и `ssl_certificate_key`. Два блока сервера могут прослушивать порты 443 и 8443 соответственно и ссылаться на совершенно разные файлы сертификатов, даже для одного и того же `server_name`. Это полезно при ротации сертификатов или при параллельном использовании устаревшего и нового сертификата в переходный период.
