Як налаштувати 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
FAQ
Чи може Nginx прослуховувати один і той самий порт у кількох блоках server?
Так. Кілька блоків `server` можуть спільно використовувати один порт. Nginx розрізняє їх за допомогою директиви `server_name`, яка зіставляє HTTP заголовок `Host`. Якщо жоден `server_name` не збігається, запит обробляє блок `default_server`.
Чи впливає додавання більшої кількості портів прослуховування на продуктивність 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`. Це корисно при ротації сертифікатів або запуску застарілого сертифіката поряд з новим під час перехідного періоду.
