Node.js на VPS: разворачиваем приложение с PM2
Устанавливаем Node.js через nvm, запускаем приложение как надёжный фоновый процесс с PM2 и настраиваем автозапуск после перезагрузки сервера и обратный прокси через Nginx.
От разработки к production: почему просто node app.js не работает
Локально на своём компьютере запустить Node.js-приложение просто: команда node app.js в терминале — и сервер поднят. На production-сервере этот же подход быстро обнажает несколько проблем, которые незаметны при коротких локальных экспериментах, но критичны для сервиса, который должен работать круглосуточно без присмотра.
Во-первых, процесс, запущенный интерактивно через SSH, привязан к этой сессии: закрытие терминала или разрыв соединения посылает процессу сигнал SIGHUP, и приложение завершается вместе с сессией. Во-вторых, если приложение упадёт из-за необработанного исключения в коде, оно просто останется в упавшем состоянии — никто не перезапустит его автоматически, и сайт останется недоступным до вмешательства администратора. В-третьих, после перезагрузки сервера (плановой или из-за сбоя) ни один процесс, запущенный вручную, не поднимется сам.
Эта статья закрывает все три проблемы: установка Node.js через nvm с возможностью держать нужную версию независимо от системных пакетов, запуск приложения как управляемого фонового процесса через PM2 с автоматическим перезапуском при падении, настройка автозапуска после перезагрузки сервера и, наконец, размещение Nginx перед Node-приложением как обратного прокси.
Установка Node.js через nvm
nvm (Node Version Manager) — менеджер версий Node.js, устанавливающий сам Node не в системные директории, а в домашнюю папку конкретного пользователя, что даёт возможность держать сразу несколько версий и переключаться между ними без прав root и без риска сломать другие проекты на сервере, зависящие от иной версии.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
После установки nvm становится доступна команда для установки конкретной версии Node.js — обычно имеет смысл ставить текущую LTS-версию (Long Term Support), получающую обновления безопасности дольше всего и рекомендованную для production-использования.
nvm install --lts
nvm use --lts
nvm alias default lts/*
node --version
Команда nvm alias default закрепляет выбранную версию так, что она автоматически становится активной в каждой новой SSH-сессии данного пользователя — без этого шага пришлось бы вручную выполнять nvm use при каждом новом подключении к серверу, включая случаи, когда PM2 или другой сервис запускается через системную автозагрузку.
Альтернатива nvm — системный пакет из apt (nodejs) или сторонний репозиторий NodeSource. Такой путь проще для одноразовой установки, но менее гибок: обновление системного пакета Node.js затрагивает сразу всё, что на сервере на него полагается, а откат к предыдущей версии в случае несовместимости требует дополнительных усилий по сравнению с mgновенным nvm use другой версии.
Первый запуск и его ограничения
Прежде чем переходить к PM2, полезно один раз запустить приложение напрямую — это подтверждает, что зависимости установлены (npm install) и сам код работает, прежде чем добавлять слой управления процессом поверх.
npm install
node app.js
В этом режиме приложение работает только пока открыт терминал текущей SSH-сессии — это нормально для проверки, что всё работает, но абсолютно непригодно для реального использования: любое отключение от сервера, любая ошибка в коде или перезагрузка сервера немедленно остановит сервис без какого-либо автоматического восстановления.
Существует техника запуска процесса «в отрыве» от терминала через nohup или комбинацию & и disown, но это лишь частично решает проблему разрыва SSH-сессии и вообще не решает вопрос автоматического перезапуска при падении или после перезагрузки сервера — для реального production нужен полноценный менеджер процессов вроде PM2, а не обходные пути на уровне shell.
PM2: менеджер процессов для Node.js
PM2 — это менеджер процессов, специально спроектированный для приложений на Node.js: он запускает приложение как управляемый фоновый процесс (демон), следит за его состоянием, автоматически перезапускает при падении, собирает логи в одном месте и умеет запускать несколько копий приложения для использования всех ядер CPU сервера.
npm install -g pm2
pm2 start app.js --name myapp
Флаг --name задаёт человекочитаемое имя процесса в списке PM2 вместо номера — это заметно удобнее при работе с несколькими приложениями на одном сервере, когда нужно быстро понять, какой процесс за что отвечает, не заглядывая каждый раз в полный путь к файлу запуска.
pm2 list
pm2 logs myapp
pm2 restart myapp
pm2 stop myapp
pm2 delete myapp
pm2 list показывает таблицу всех управляемых процессов с их статусом, потреблением памяти и CPU и количеством перезапусков — резкий рост счётчика перезапусков одного процесса обычно первый явный сигнал, что приложение регулярно падает и стоит посмотреть в его логи через pm2 logs, прежде чем проблема станет заметна пользователям.
Автоперезапуск при падении и режим кластера
Главное практическое преимущество PM2 перед голым node app.js — автоматический перезапуск процесса при неожиданном завершении, будь то необработанное исключение, выход за лимит памяти или любое другое аварийное завершение. PM2 перезапускает упавший процесс почти мгновенно, минимизируя время недоступности сервиса для пользователей.
Для многоядерных серверов PM2 поддерживает режим кластера: вместо одного процесса Node.js (который по своей природе однопоточен для выполнения JavaScript-кода) запускается столько копий приложения, сколько ядер CPU доступно, а PM2 распределяет входящие соединения между ними через встроенный балансировщик — это позволяет полноценно задействовать все ядра сервера без изменения кода самого приложения.
pm2 start app.js -i max --name myapp
pm2 scale myapp 2
Значение max для флага -i автоматически подстраивается под число ядер CPU конкретного сервера — это удобно для типового деплоя, но на VPS с малым количеством vCPU (1-2 ядра) выигрыш от кластерного режима будет скромным, а на некоторых нагрузках, в основном ограниченных не CPU, а ожиданием ответа от базы данных или внешнего API, разница может оказаться незначительной по сравнению с одним процессом.
pm2 startup и pm2 save: автозапуск после перезагрузки сервера
Сам по себе PM2 не переживает перезагрузку сервера автоматически — по умолчанию после перезагрузки все процессы, которые он контролировал, останутся неактивными, пока кто-то вручную их не поднимет. Для настройки автозапуска существует связка из двух команд.
pm2 startup
Команда pm2 startup не настраивает автозапуск сама по себе, а выводит на экран готовую команду (обычно начинающуюся с sudo env PATH=...), которую нужно скопировать и выполнить отдельно — именно эта вторая команда регистрирует PM2 как службу systemd (или аналогичный механизм на других системах инициализации), которая поднимается при загрузке сервера от имени текущего пользователя.
pm2 save
После настройки автозапуска обязательно выполняется pm2 save — эта команда сохраняет снимок текущего списка управляемых процессов (какие приложения запущены, с какими параметрами) в файл, который PM2 читает при следующем автоматическом старте службы. Если добавить новое приложение под PM2, но забыть выполнить pm2 save заново, при следующей перезагрузке сервера новое приложение не поднимется, хотя старые продолжат запускаться как обычно — это одна из самых частых практических ошибок при первой настройке PM2.
Логирование и диагностика через PM2
PM2 автоматически перехватывает стандартный вывод и поток ошибок каждого управляемого процесса и сохраняет их в отдельные лог-файлы, доступные без необходимости самостоятельно настраивать перенаправление вывода в коде приложения.
pm2 logs myapp --lines 200
pm2 flush myapp
Со временем лог-файлы PM2 могут занимать заметный объём на диске, особенно если приложение активно пишет в консоль при каждом запросе — модуль pm2-logrotate решает эту проблему, автоматически ограничивая размер и количество хранимых файлов логов по расписанию.
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
Для более глубокой диагностики (потребление памяти и CPU в реальном времени по каждому процессу отдельно) удобна интерактивная панель pm2 monit — она открывается прямо в терминале и не требует установки дополнительных внешних инструментов мониторинга для базовой оценки состояния запущенных приложений.
Для более полной картины (история метрик за прошедшие дни, а не только текущий момент, оповещения о падении процесса на почту или в мессенджер) существует бесплатный веб-интерфейс PM2 Plus, подключаемый к уже работающим процессам без изменения кода приложения, — для небольшого проекта на одном VPS базовых команд pm2 list, pm2 logs и pm2 monit обычно достаточно, а более продвинутый мониторинг имеет смысл добавлять уже по мере реального роста числа обслуживаемых процессов и серверов.
Nginx как обратный прокси перед Node.js
Node.js-приложение (например, на Express) обычно слушает какой-то внутренний порт вроде 3000, недоступный напрямую снаружи. Стандартная production-схема — разместить перед ним Nginx, который принимает входящие запросы на 80/443 портах и перенаправляет их на внутренний порт приложения через директиву proxy_pass.
server {
listen 80;
server_name example.ru;
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;
}
}
Заголовки Upgrade и Connection в примере нужны для корректной проксировании WebSocket-соединений (часто используемых в Node-приложениях для realtime-функциональности) — без них попытка апгрейда протокола с HTTP на WebSocket будет обрываться на уровне Nginx, даже если само приложение полностью готово их обрабатывать.
Такая связка даёт сразу несколько практических преимуществ: Nginx берёт на себя терминацию TLS-сертификата (само Node-приложение может вообще не знать про HTTPS), отдачу статических файлов напрямую с диска в обход приложения, ограничение частоты запросов от одного клиента и, при нескольких запущенных через PM2-кластер копиях приложения, дополнительный слой балансировки нагрузки поверх встроенного механизма PM2.
Приложение при этом стоит настраивать на прослушивание именно localhost (127.0.0.1), а не всех сетевых интерфейсов (0.0.0.0) — это исключает случайный прямой доступ к внутреннему порту Node.js в обход Nginx и всех настроенных на нём правил безопасности, если порт не был явно и осознанно открыт для внешнего доступа через firewall.
Переменные окружения и конфигурация приложения
Production-приложение на Node.js обычно требует набора переменных окружения — строку подключения к базе данных, ключи внешних API, режим работы (NODE_ENV=production). Хранить эти значения прямо в коде — плохая практика, а PM2 предоставляет собственный механизм передачи переменных окружения процессу без изменения самого кода приложения.
pm2 start app.js --name myapp --env production
pm2 set myapp:NODE_ENV production
Более гибкий и распространённый на практике способ — файл ecosystem.config.js, в котором декларативно описываются все параметры запуска приложения (имя, путь к файлу, число экземпляров, переменные окружения для разных сред) в одном месте, что удобнее разрозненных флагов командной строки, особенно если на сервере работает несколько приложений или несколько окружений одного приложения.
module.exports = {
apps: [{
name: 'myapp',
script: 'app.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
}
}]
};
pm2 start ecosystem.config.js
pm2 save
Обновление без простоя: pm2 reload
Команда pm2 restart полностью останавливает процесс и запускает его заново — на короткое время между остановкой старой версии и полной готовностью новой сервис оказывается недоступен, что для сайта с постоянным потоком запросов означает видимые пользователю ошибки, пусть и на несколько секунд.
pm2 reload myapp
В режиме кластера (несколько копий процесса, запущенных через -i) pm2 reload перезапускает копии по одной: пока одна копия перезагружается с новым кодом, остальные продолжают обслуживать входящие запросы, и только после того как перезапущенная копия снова готова принимать соединения, PM2 переходит к следующей. Это даёт полностью бесшовное обновление кода без единого отклонённого запроса пользователя.
Для одиночного процесса вне кластерного режима такой возможности физически нет — если запущена всего одна копия приложения, её обновление неизбежно требует короткой остановки; переход на кластерный режим хотя бы с двумя копиями на сервере с двумя и более ядрами CPU — минимальное условие для получения выгоды от pm2 reload на практике.
Чек-лист разворачивания Node.js-приложения с PM2
Шаг 1. Установите Node.js через nvm, зафиксируйте нужную LTS-версию как версию по умолчанию для пользователя.
Шаг 2. Проверьте работоспособность приложения прямым запуском node app.js, прежде чем переходить к PM2.
Шаг 3. Запустите приложение под PM2 с явным именем процесса, при необходимости — в режиме кластера через -i max.
Шаг 4. Настройте автозапуск через pm2 startup (выполнив выведенную команду отдельно) и обязательно завершите настройку командой pm2 save.
Шаг 5. Настройте ротацию логов через модуль pm2-logrotate, чтобы логи не заполнили диск сервера со временем.
Шаг 6. Разместите Nginx перед приложением как обратный прокси, настройте TLS-сертификат на уровне Nginx, а само приложение держите слушающим только localhost.
Итог: PM2 как минимальная production-обвязка для Node.js
PM2 закрывает три ключевые проблемы голого запуска Node.js-приложения на сервере: переживание разрыва SSH-сессии, автоматический перезапуск при падении и восстановление после перезагрузки сервера. Для подавляющего большинства проектов на одном VPS этого набора возможностей достаточно, без необходимости в более сложных системах вроде Kubernetes или Docker Swarm.
Связка Node.js под PM2 за Nginx как обратным прокси — устоявшийся и проверенный годами способ размещения приложений на JavaScript в production, одинаково хорошо подходящий и для небольшого API-сервиса, и для полноценного веб-приложения с рендерингом на сервере.
Если разворачивание конкретного Node.js-приложения на VPS вызывает сложности — оставьте заявку внизу страницы, поможем настроить окружение, PM2 и обратный прокси под особенности вашего проекта.
Почему стоит выбрать нас
Быстрый запуск
Подберём конфигурацию и развернём проект в день обращения.
Надёжность
NVMe-диски, защита от DDoS и резервные копии по расписанию.
Поддержка 24/7
Дежурные инженеры на связи в любое время суток.
Настройка под ключ
Установим CMS, настроим веб-сервер, SSL и почту за вас.
Перенос без простоя
Аккуратно перенесём сайт и базу данных на новый сервер.
Прозрачные цены
Актуальные тарифы и честный подбор без навязывания.
Вопросы и ответы
Почему нельзя просто оставить запущенным node app.js через SSH и закрыть терминал?
Процесс, запущенный интерактивно в сессии SSH, привязан к этой сессии и по умолчанию завершается вместе с ней при отключении (сигнал SIGHUP) — приложение просто перестанет отвечать сразу после того, как администратор закроет соединение.
Обязательно ли использовать именно nvm, а не системный пакет Node.js?
Не обязательно, но крайне рекомендуется — nvm позволяет держать несколько версий Node.js одновременно и переключаться между ними за секунды, тогда как системный пакет обычно один на всю систему и его обновление способно сломать другие проекты на этом же сервере, если они рассчитаны на другую версию.
Что делает PM2 в случае падения приложения из-за необработанной ошибки?
PM2 отслеживает завершение процесса и автоматически перезапускает его почти мгновенно, одновременно записывая событие и стек ошибки в лог — приложение возвращается в рабочее состояние без вмешательства администратора, хотя саму причину падения стоит найти и исправить отдельно.
Нужно ли запускать PM2 от root?
Нет, и делать это не стоит — PM2 и сам процесс приложения должны работать от отдельного непривилегированного пользователя; команды pm2 startup и pm2 save настраиваются для этого же пользователя, чтобы автозапуск после перезагрузки работал без root-прав у самого приложения.
Как посмотреть, сколько памяти и CPU реально потребляет Node-приложение под PM2?
Командой pm2 monit — она открывает интерактивную панель в терминале с графиками потребления CPU и памяти по каждому процессу, управляемому PM2, в реальном времени.
Что произойдёт с процессами PM2 при перезагрузке сервера, если не настроить pm2 startup?
Ничего — без явно настроенного автозапуска PM2 не поднимется сам после перезагрузки, и все управляемые им процессы останутся неактивными до тех пор, пока администратор вручную не выполнит pm2 resurrect или заново не запустит приложения.
Зачем нужен Nginx перед Node.js, если Node сам умеет обслуживать HTTP-запросы?
Nginx берёт на себя терминацию TLS, отдачу статических файлов, ограничение скорости запросов и балансировку между несколькими экземплярами Node-процесса, оставляя самому приложению только бизнес-логику — это стандартная и проверенная схема размещения Node.js в production.
Можно ли запускать несколько экземпляров одного Node-приложения на одном сервере через PM2?
Да, режим кластера (pm2 start app.js -i max) запускает столько копий процесса, сколько ядер CPU доступно на сервере, и автоматически распределяет входящие соединения между ними через встроенный балансировщик PM2.
Как оплачивать услуги?
Оплата помесячная, для облачных серверов доступна почасовая тарификация. Принимаются карты, банковские переводы и электронные кошельки.
Есть ли круглосуточная поддержка?
Да, дежурные инженеры на связи 24/7.
Выдаёте ли закрывающие документы?
Да, предоставим необходимые документы для оплаты.
Как оставить заявку?
Заполните форму на странице или нажмите «Заказать» — мы свяжемся и поможем с подбором.