Nginx Unit — отдельный сервер приложений от разработчиков nginx: он запускает PHP, Python, Node.js и ряд других языков из одного процесса управления, без отдельных служб вроде php-fpm или pm2. Веб-сервер nginx при этом не заменяется: Unit берёт на себя выполнение приложения, а TLS и раздачу статики перед ним обычно всё равно настраивают через nginx. Разберём, когда такая связка упрощает администрирование, а когда привычная схема с php-fpm или pm2 остаётся проще.
Чем Unit отличается от php-fpm и pm2
Unit управляется не текстовым конфигом с перезагрузкой по сигналу, а REST API поверх управляющего сокета: приложения, листенеры и маршруты описываются JSON-объектом и применяются PUT-запросом без остановки процесса. Добавление нового приложения или изменение числа воркеров не требует редактирования файла конфигурации и команды reload, как в связке с php-fpm.
Для Node.js разница принципиальная: pm2 запускает обычный процесс Node.js и следит за ним снаружи, а Unit встраивается в приложение через модуль unit-http, который подставляется вместо стандартного http-модуля. Перенос существующего Node-приложения на Unit требует правки кода запуска, а не только конфигурации сервера.
Установка и процессы Unit
Unit ставится как отдельный пакет плюс языковые модули — для PHP, Python, Node.js и так далее, собранные под конкретную версию интерпретатора. Основной процесс unitd слушает управляющий сокет control.unit.sock и порождает процессы-роутеры и отдельные процессы приложений, количество которых задаётся в конфигурации каждого приложения.
Роль nginx в этой схеме не меняется: он остаётся тем же веб-сервером, что описан в статье об архитектуре Nginx. Nginx слушает порт 80 или 443, отдаёт статику напрямую и проксирует динамические запросы на Unit через proxy_pass, как на любой другой upstream.
curl -X PUT --data-binary @app.json --unix-socket /var/run/control.unit.sock http://localhost/config/applications/myapp
{
"type": "php",
"root": "/var/www/myapp/public/",
"index": "index.php",
"processes": { "max": 4, "spare": 1 }
}
Приложение в JSON-конфигурации
Каждое приложение описывается отдельным объектом с типом, путём и числом процессов. Листенер связывает сетевой порт или unix-сокет с именем приложения, поэтому на одном хосте могут одновременно работать PHP-сайт, Python-сервис и Node-бэкенд, каждый со своими процессами и лимитами.
| Параметр | php-fpm + pm2 | Nginx Unit |
|---|---|---|
| Формат конфигурации | текстовые файлы ini и json отдельно для каждой службы | один JSON-объект через REST API |
| Применение изменений | reload или restart службы | PUT-запрос без остановки процесса |
| Запуск Node.js | обычный процесс, pm2 следит снаружи | модуль unit-http внутри кода приложения |
| Разные языки на одном хосте | отдельная служба на каждый язык | один процесс unitd для всех языков |
Такое разделение удобно для хостинга нескольких приложений на разных языках на одной VDS: не нужно держать отдельный systemd-юнит под каждый язык и синхронизировать их перезапуск вручную.
Nginx перед Unit: прокси и статика
Unit слушает собственный порт или unix-сокет, а nginx перед ним работает так же, как перед php-fpm или любым другим backend: принимает соединение, отдаёт статические файлы напрямую из файловой системы и проксирует запросы к динамическому контенту.
Базовая настройка server-блока, TLS-сертификатов и логов не меняется и описана в статье про настройку Nginx для сайта на VDS. Дополнительно в location для динамических запросов указывается proxy_pass на листенер Unit вместо fastcgi_pass на php-fpm.
На что проверить перед переходом
Перед тем как переносить рабочий сайт на Unit, стоит пройти по короткому списку проверок — часть ограничений проявляется только в продакшене, а не на тестовом стенде.
- Node.js-приложение потребует правки кода запуска под unit-http — обычный process.listen не заработает с Unit без изменений.
- Для PHP нужен модуль unit-php, собранный под установленную версию PHP — несовпадение версии не даст приложению стартовать.
- Управляющий сокет control.unit.sock должен быть доступен только локально и закрыт от внешнего доступа файрволом.
- Число процессов приложения задаётся в конфигурации явно, а не определяется автоматически по нагрузке.
- Логи приложения по умолчанию попадают в общий лог Unit, а не в отдельный файл на процесс, как привычно для pm2.
Частые вопросы
Можно ли убрать nginx и оставить только Unit?
Технически Unit умеет самостоятельно слушать порт и отдавать статические файлы, но для продакшен-сайта с TLS-сертификатами и несколькими доменами на одной VDS обычно проще оставить nginx перед ним — так удобнее управлять сертификатами и логами на одном уровне.
Что делать, если версия PHP на сервере не совпадает с модулем Unit?
Unit позволяет держать несколько языковых модулей одновременно — например php81 и php83 как отдельные файлы модулей, и каждое приложение в конфигурации указывает нужную версию. Модуль собирается под конкретную версию PHP и не подходит для соседней минорной версии без пересборки.
Как проверить, что приложение в Unit запущено и отвечает?
Текущая конфигурация и статус читаются через тот же управляющий сокет: GET-запрос к /config показывает активные приложения и листенеры, а /status — число процессов и обработанных запросов. Ошибки запуска приложения попадают в лог Unit.