Nginx: что это такое, как работает, плюсы и минусы

Nginx: что это такое, как работает, плюсы и минусы Полезное

Nginx (читается «энджин-икс») — это программа с открытым исходным кодом, которая принимает HTTP-запросы и либо сама отдает ответ (файлы сайта), либо передает запрос дальше — приложению на Python, PHP, Node.js. В первой роли Nginx работает как веб-сервер, во второй — как обратный прокси, а если приложений несколько, то еще и как балансировщик нагрузки.

Ниже — устройство, плюсы и минусы, сравнение с Apache и минимальный конфиг с проверкой. Примеры проверены 23.09.2026 на Ubuntu 24.04 (пакет nginx 1.24.0) и в официальном Docker-образе nginx:stable-alpine (1.30.5).

Три роли Nginx и близкие термины

Эти роли часто смешивают, хотя это разные задачи:

Роль Что делает Пример
Веб-сервер Отдает файлы с диска: HTML, CSS, картинки root /var/www/mysite;
Обратный прокси Принимает запрос от клиента и пересылает его приложению, ответ возвращает клиенту proxy_pass http://app;
Балансировщик Распределяет запросы между несколькими копиями приложения блок upstream с двумя server
TLS-терминатор Принимает HTTPS, расшифровывает и дальше общается с приложением listen 443 ssl; + сертификат

Обратный прокси стоит перед серверами и защищает их от клиента. Прямой прокси стоит перед клиентами и ходит в интернет от их имени. Nginx обычно используют в первой роли.

Кроме HTTP, Nginx умеет проксировать TCP/UDP (модуль stream) и почтовые протоколы.

Как Nginx работает

Nginx запускает один master-процесс и несколько worker-процессов. Master читает конфигурацию и управляет воркерами, а запросы обслуживают воркеры. Число воркеров задает worker_processes, и значение auto означает «по числу ядер процессора».

Главная особенность — событийная модель. Воркер не выделяет отдельный поток на каждое соединение и не ждет, пока медленный клиент дочитает ответ. Он держит тысячи соединений и через механизм ОС (epoll в Linux, kqueue во FreeBSD и macOS) узнает, какое из них готово к чтению или записи. Поэтому при большом числе одновременных подключений Nginx расходует мало памяти.

Лимит соединений на воркер задает worker_connections: в пакете Ubuntu 24.04 стоит 768, в официальном Docker-образе — 1024. Это именно соединения, включая соединения к приложениям за прокси, а не «запросы пользователя».

Упрощение, о котором стоит помнить: Nginx сам не выполняет PHP или Python. Динамику он передает внешнему процессу — PHP-FPM по протоколу FastCGI, приложению по HTTP (proxy_pass), uWSGI или SCGI.

Плюсы и минусы Nginx

Плюсы Минусы
Держит много одновременных соединений при малом расходе памяти Нет .htaccess: правила для каталогов меняет только администратор в основном конфиге
Быстро отдает статические файлы Сам не исполняет PHP/Python — нужен PHP-FPM или сервер приложений
Один инструмент закрывает веб-сервер, прокси, балансировку, кеш, TLS Синтаксис конфига и порядок выбора location новичку неочевидны
Перезагрузка конфига без разрыва соединений (reload) Часть функций (активные проверки здоровья, API управления) есть только в платной NGINX Plus
Свободная лицензия (BSD-подобная), пакеты во всех популярных дистрибутивах Сборка для Windows официально считается бета-версией, для продакшена не рекомендуется

Модуль либо вкомпилирован в сборку, либо подключается как динамический через load_module; состав сборки показывает nginx -V.

Nginx или Apache

Критерий Nginx Apache HTTP Server 2.4
Модель обработки Событийная, воркеры Модули MPM: prefork, worker, event
Настройка на уровне каталога Нет Да, через .htaccess (если разрешено AllowOverride)
PHP Через PHP-FPM Через PHP-FPM или встроенный mod_php
Типичная роль Фронт: статика, прокси, TLS Сервер приложений, shared-хостинг

Частая связка — Nginx на входе, за ним Apache или приложение. Вывод «Nginx всегда быстрее» неверен: у Apache есть событийный MPM event, а узким местом под нагрузкой обычно оказывается приложение или база.

Минимальный конфиг: статика + прокси + балансировка

Сначала рабочий пример целиком. Установка в Ubuntu:

sudo apt update
sudo apt install nginx
nginx -v

Перед правкой (особенно если на сервере уже работают другие сайты): держите открытой текущую SSH-сессию, сохраните копию конфигурации под уникальным именем и запишите путь к ней — это ваша точка отката.

B=/etc/nginx.bak-$(date +%F-%H%M%S)
test ! -e "$B" && sudo cp -a /etc/nginx "$B" && echo "Копия: $B"

Имя только с датой (/etc/nginx.bak-$(date +%F)) не годится для повторных правок: при втором запуске за день такой каталог уже есть, и cp -a не заменит его, а положит новую копию внутрь, в /etc/nginx.bak-ДАТА/nginx. После этого непонятно, какую версию восстанавливать. Время в имени и проверка test ! -e исключают копирование поверх существующего пути. Полный порядок правки, проверки и отката — в разделе «Как безопасно менять конфиг Nginx» ниже.

Файл /etc/nginx/sites-available/mysite — так раскладывают сайты пакеты Debian и Ubuntu. В RHEL, Rocky, AlmaLinux и в пакетах с nginx.org каталогов sites-* нет: тот же блок кладут в /etc/nginx/conf.d/mysite.conf, без симлинка. Два учебных «приложения» здесь изображает сам Nginx на портах 9001 и 9002 — так пример запускается без Python или Node.js. В реальном проекте на их месте ваше приложение.

# Два учебных бэкенда: вместо них обычно ваше приложение (Python, Node.js, PHP-FPM)
server {
    listen 127.0.0.1:9001;
    return 200 "app-1 got $request_uri\n";
}
server {
    listen 127.0.0.1:9002;
    return 200 "app-2 got $request_uri\n";
}

upstream app {
    zone app 64k;
    server 127.0.0.1:9001;
    server 127.0.0.1:9002;
}

server {
    listen 80;
    server_name example.local;
    server_tokens off;

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

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

    location /api/ {
        proxy_pass http://app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Включаем сайт, проверяем синтаксис и применяем без остановки сервера:

sudo mkdir -p /var/www/mysite
echo "<h1>Hello from Nginx</h1>" | sudo tee /var/www/mysite/index.html
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
curl -H "Host: example.local" http://127.0.0.1/
for i in 1 2 3 4; do curl -s -H "Host: example.local" http://127.0.0.1/api/users; done

Результат: nginx -t сообщает syntax is ok и test is successful, первый curl возвращает страницу, а в этом последовательном прогоне запросы к /api/ чередовались между двумя бэкендами:

<h1>Hello from Nginx</h1>
app-1 got /api/users
app-2 got /api/users
app-1 got /api/users
app-2 got /api/users

Что здесь происходит

  • server_name example.local — Nginx выбирает блок server по заголовку Host. Без -H "Host: ..." запрос попадет в сайт по умолчанию (в Ubuntu он включен из коробки), и curl покажет страницу «Welcome to nginx!».
  • location / отдает файлы из root, а try_files ... =404 возвращает 404, если файла нет, вместо попытки угадать.
  • upstream app — группа бэкендов, по умолчанию round-robin. Директива zone хранит состояние группы в общей памяти, которую видят все воркеры; с ней четыре последовательных запроса выше чередовались 1-2-1-2, а без нее у каждого воркера свое состояние, и в прогоне на двух воркерах порядок был app-1, app-1, app-2, app-1. Строгой очередности алгоритм не обещает: параллельные запросы, отказы и временно отключенные серверы меняют выбор, поэтому в приложении на конкретный порядок не полагайтесь.
  • Если бэкенд не принимает соединение, Nginx по умолчанию (proxy_next_upstream error timeout) передает запрос другому серверу: при остановленном втором бэкенде все четыре запроса вернули 200, причем и GET, и POST. Для POST это работает именно потому, что соединение не установилось и запрос еще не ушел бэкенду. Если же запрос уже отправлен, а бэкенд упал или не ответил вовремя, неидемпотентные запросы (POST, PATCH, LOCK) по умолчанию на другой сервер не передаются. Параметр non_idempotent снимает это ограничение, но тогда операция может выполниться дважды: включайте его, только если приложение защищено от дублей. И даже без повтора клиент после такого обрыва не знает наверняка, выполнилась ли операция.
  • server_tokens off скрывает версию: в ответе Server: nginx вместо Server: nginx/1.24.0 (Ubuntu).
  • Бэкенды слушают только 127.0.0.1, поэтому снаружи в обход Nginx к ним не достучаться.

Одна косая черта в proxy_pass меняет URL

Это частая ловушка. С proxy_pass http://app; приложение получает путь целиком: app-1 got /api/users. Если написать proxy_pass http://app/;, Nginx заменит совпавшую часть /api/ на /, и приложение увидит app-1 got /users. Какой вариант нужен, зависит от того, какие пути ждет приложение.

Если не получилось

Симптом: nginx -t падает. Уберем точку с запятой после root /var/www/mysite:

2026/09/23 15:57:34 [emerg] 2644#2644: invalid number of arguments in "root" directive in /etc/nginx/sites-enabled/mysite:23
nginx: configuration file /etc/nginx/nginx.conf test failed

Так выглядит вывод в Ubuntu 24.04 (дата и номер процесса у вас будут свои). В официальном образе и пакетах с nginx.org строка ошибки начинается с nginx: [emerg], текст тот же.

Ошибка указывает на строку 23, хотя пропуск в строке 22: без ; Nginx склеил root со следующей директивой index. Исправление — вернуть ; и снова запустить nginx -t. Если все же выполнить nginx -s reload (или systemctl reload nginx) с ошибкой, команда завершится с ошибкой, а Nginx продолжит работать со старым конфигом. А вот restart с такой ошибкой сервер не поднимет.

Симптом: 502 Bad Gateway на /api/. Nginx жив, но не достучался до приложения. В error.log будет строка вида connect() failed (111: Connection refused) while connecting to upstream с адресом бэкенда. Проверьте, что приложение запущено и слушает тот адрес и порт, что указан в upstream.

Симптом: вместо вашего сайта «Welcome to nginx!». server_name не совпал с Host, ответил сайт по умолчанию. Проверьте домен и ls -l /etc/nginx/sites-enabled/.

Как безопасно менять конфиг Nginx (Ubuntu/Debian)

Порядок ниже — для Ubuntu/Debian с systemd; в других дистрибутивах отличаются пути к файлам сайтов (см. выше), остальные команды те же.

  1. Доступ: работайте в открытой SSH-сессии и не закрывайте ее до конца проверки. Правка Nginx не трогает SSH, но ошибка в файрволе или сети может.
  2. Копия под уникальным именем, как в блоке «Перед правкой»: B=/etc/nginx.bak-$(date +%F-%H%M%S), затем test ! -e "$B" && sudo cp -a /etc/nginx "$B". Путь из $B запишите: переменная живет только в текущей сессии.
  3. Правка файла сайта, а не общего nginx.conf.
  4. sudo nginx -t — это проверка синтаксиса и того, что файлы из конфига открываются, а не того, что сайт работает правильно. sudo nginx -T дополнительно покажет итоговый конфиг целиком: видно, какие файлы реально подключены.
  5. sudo systemctl reload nginx, а не restart: старые воркеры доработают текущие запросы. Команда должна завершиться без ошибки, свежие строки [emerg] смотрите в sudo tail /var/log/nginx/error.log.
  6. Проверка ответа: локально curl -I -H "Host: example.local" http://127.0.0.1/, с другой машины — по реальному домену, а для HTTPS через curl -I --resolve example.com:443:IP_сервера https://example.com/, чтобы проверить и Host, и сертификат по SNI. Ждем ожидаемый код (200 или 301), а не страницу «Welcome to nginx!».
  7. Откат, если сломалось: вернуть файл именно из той копии, что сделана перед этой правкой (sudo cp -a "$B"/sites-available/mysite /etc/nginx/sites-available/, где $B — записанный путь), или убрать симлинк из sites-enabled, затем снова nginx -t, reload и curl.

И две оговорки о безопасности. Заголовку X-Forwarded-For приложение может доверять только если оно недоступно напрямую: клиент способен прислать свой поддельный X-Forwarded-For, а $proxy_add_x_forwarded_for лишь дописывает к нему реальный адрес. А при включении файрвола сначала разрешите SSH, потом 80 и 443, и только затем включайте его — иначе можно потерять доступ к серверу. В Ubuntu с ufw это sudo ufw allow OpenSSH, sudo ufw allow 'Nginx Full', sudo ufw enable и проверка sudo ufw status до выхода из текущей SSH-сессии.

Форки и родственные проекты

Nginx создал Игорь Сысоев, первая публичная версия вышла в 2004 году. С 2019 года проект принадлежит F5, которая развивает открытую версию и платную NGINX Plus. Открытая версия выходит двумя ветками: mainline с новыми функциями и stable только с исправлениями; на сентябрь 2026 это 1.31.x и 1.30.x, для продакшена обычно берут stable или пакет дистрибутива (в Ubuntu 24.04 — 1.24.0 с патчами безопасности от Ubuntu). Есть форки: Angie — российский проект бывших разработчиков Nginx с совместимым синтаксисом, и freenginx — форк, который с 2024 года ведет Максим Дунин, бывший ключевой разработчик Nginx. Базовые директивы (server, location, proxy_pass, upstream) в них работают так же, но расширения и номера версий у каждого проекта свои.

Выводы

  • Nginx — это веб-сервер, обратный прокси, балансировщик и TLS-терминатор в одной программе; роли удобно различать по задаче.
  • Сильная сторона — событийная модель: много соединений при малом расходе памяти. Динамику он передает приложению или PHP-FPM.
  • Главные минусы — нет .htaccess, нужен отдельный сервер для PHP/Python, неочевидная логика location и proxy_pass.
  • Рабочий цикл изменений: копия -> правка -> nginx -t -> reload -> проверка curl -> откат при ошибке.

Где применяется / связь с практикой

Освойте тему на практике

Nginx стоит перед большинством веб-проектов, поэтому его настройка входит в базовые задачи Linux-администратора и DevOps-инженера: публикация сайта, прокси к приложению, HTTPS, разбор 502 по логам. Системно разобрать администрирование Linux, включая веб-серверы, сеть и диагностику, можно на курсе «Administrator Linux. Professional». Попробовать формат и задать вопросы преподавателям можно на бесплатных открытых уроках Otus.

FAQ

Можно ли запустить Nginx на Windows?
Официальная сборка для Windows есть, но разработчики считают ее бета-версией с ограничениями производительности. Для разработки на Windows удобнее запускать Nginx в Docker или WSL.

Чем reload отличается от restart?
reload перечитывает конфиг и плавно заменяет воркеры без разрыва соединений, а при ошибке в конфиге оставляет старую версию. restart останавливает и заново запускает сервер, и с ошибкой в конфиге Nginx не поднимется.

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

OTUS Журнал
Скидка 5% 12-19 октября на курсы (popup)
Бесплатные открытые уроки (поп-ап)