Как установить Node.js и PM2 на Ubuntu: полное руководство по производственной среде
Node.js — это асинхронная, событийно-ориентированная среда выполнения JavaScript, построенная на движке V8 от Chrome и предназначенная для выполнения JavaScript-кода на стороне сервера с высокой пропускной способностью. PM2 — это менеджер процессов производственного уровня для приложений Node.js, который обеспечивает демонизацию, автоматическое восстановление после сбоев, агрегацию логов, балансировку нагрузки в режиме кластера и генерацию скриптов запуска — всё через единый интерфейс CLI.
В этом руководстве рассматриваются все методы установки, параметры конфигурации и операционные шаблоны, необходимые для надёжного запуска приложений Node.js на Ubuntu 20.04, 22.04 или 24.04 LTS в производственной среде.
Предварительные требования
Перед началом убедитесь в следующем:
- Операционная система: Ubuntu 20.04, 22.04 или 24.04 LTS (серверная или десктопная)
- Привилегии пользователя: `sudo` или root-доступ
- Сетевой доступ: Исходящий HTTPS для загрузки пакетов и скриптов
- Установлен curl: Выполните `sudo apt install curl -y`, если он ещё не установлен
Если вы запускаете это на облачном сервере, среда VPS Хостинг является наиболее распространённой целью развёртывания для рабочих нагрузок Node.js, и всё описанное в этом руководстве применимо напрямую.
Шаг 1: Обновление системных пакетов
Всегда синхронизируйте индекс пакетов и применяйте ожидающие обновления перед установкой нового программного обеспечения. Устаревшие метаданные пакетов — частый источник конфликтов зависимостей.
“`bash
sudo apt update
sudo apt upgrade -y
“`
После завершения обновления перезагрузитесь, если было обновлено ядро:
“`bash
sudo reboot
“`
Шаг 2: Установка Node.js — выбор подходящего метода
Существует три основных метода установки Node.js на Ubuntu. Каждый из них имеет свои компромиссы с точки зрения управления версиями, изоляции и общесистемной доступности.
Сравнение методов
| Функция | NodeSource (apt) | NVM | Системный apt (universe) |
|---|
| — | — | — | — |
|---|
| Управление версиями | Одна фиксированная мажорная версия | Несколько версий на пользователя | Как правило, устаревшая LTS |
|---|
| Общесистемная установка | Да | Нет (по умолчанию для каждого пользователя) | Да |
|---|
| Переключение версий | Требует повторного запуска скрипта настройки | `nvm use <version>` | Не поддерживается |
|---|
| Лучше всего подходит для | CI/CD, серверы с одной версией | Разработка, мультипроектные среды | Только быстрое тестирование |
|---|
| sudo требуется для глобальных npm-пакетов | Да | Нет | Да |
|---|
| Пригодность для продакшена | Высокая | Средняя | Низкая |
|---|
Метод 1: Установка Node.js через NodeSource (рекомендуется для серверов)
NodeSource поддерживает актуальные репозитории Debian/Ubuntu для каждой активной ветки выпуска Node.js. Это предпочтительный подход для производственных серверов, где требуется единая стабильная версия на уровне всей системы.
Добавьте репозиторий NodeSource для текущего LTS-релиза:
“`bash
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash –
“`
Этот скрипт выполняет несколько действий: определяет вашу версию Ubuntu, добавляет соответствующий apt-репозиторий NodeSource, импортирует GPG-ключ подписи и запускает `apt-get update`. Флаг `-E` сохраняет переменные окружения при повышении привилегий до sudo, что важно, если у вас настроены параметры прокси.
Установите Node.js и npm:
“`bash
sudo apt install nodejs -y
“`
Пакет NodeSource включает в себя как `node`, так и `npm` в едином пакете `nodejs`. В отличие от пакета Ubuntu universe, он не разделяет их.
Проверьте установку:
“`bash
node -v
npm -v
“`
Пример ожидаемого вывода:
“`
v20.14.0
10.7.0
“`
Фиксация на конкретной мажорной версии: Если вам нужен Node.js 18 вместо текущей LTS, замените `setup_lts.x` на `setup_18.x` в команде curl. Доступные ветки включают `setup_18.x`, `setup_20.x` и `setup_22.x`.
Метод 2: Установка Node.js через NVM (рекомендуется для разработки и сред с несколькими версиями)
NVM (Node Version Manager) устанавливает Node.js в ваш домашний каталог, не требуя привилегий root ни для самого Node.js, ни для глобально установленных npm-пакетов. Это устраняет проблемы с правами доступа, которые часто возникают при запуске `npm install -g` на системно установленном Node.js.
Установите NVM:
“`bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
“`
Перед выполнением этой команды проверьте официальный репозиторий NVM на наличие последнего тега релиза — номер версии в URL меняется с каждым выпуском.
Перезагрузите окружение оболочки:
“`bash
source ~/.bashrc
“`
Если вы используете Zsh, вместо этого подключите `~/.zshrc`. Установщик NVM добавляет свой блок инициализации в тот файл конфигурации оболочки, который он обнаружит.
Установите последнюю LTS-версию Node.js:
“`bash
nvm install –lts
“`
Установите конкретную версию наряду с LTS:
“`bash
nvm install 18
nvm install 20
“`
Переключайтесь между установленными версиями:
“`bash
nvm use 20
nvm alias default 20
“`
Команда `alias default` устанавливает версию, которая активируется в новых сеансах оболочки, что критически важно для скриптов и заданий cron, которые не подключают ваш интерактивный профиль оболочки.
Проверка:
“`bash
node -v
npm -v
“`
Критическая проблема NVM для продакшена: Поскольку NVM привязан к пользователю, скрипты запуска PM2 и юниты systemd не будут иметь доступа к бинарному файлу Node.js, управляемому NVM, если вы явно не настроите путь. Смотрите Шаг 5, чтобы узнать, как правильно это обработать.
Шаг 3: Установка PM2
PM2 распространяется как npm-пакет и должен быть установлен глобально, чтобы его CLI был доступен на уровне всей системы.
Установите PM2:
“`bash
sudo npm install -g pm2
“`
Если вы установили Node.js через NVM, опустите `sudo`:
“`bash
npm install -g pm2
“`
Проверьте установку:
“`bash
pm2 -v
“`
Установите конкретную версию PM2 (полезно при фиксации инфраструктуры):
“`bash
sudo npm install -g pm2@5.3.1
“`
PM2 версии 5.x — это текущая стабильная ветка. По сравнению с v4 в ней были внесены значительные улучшения в веб-панель управления (pm2 plus), ротацию логов и систему модулей.
Шаг 4: Управление приложениями Node.js с помощью PM2
Запуск приложения
Перейдите в каталог вашего приложения и запустите его:
“`bash
cd /var/www/my-app
pm2 start app.js –name "my-app"
“`
Всегда указывайте флаг `–name`. Без него PM2 использует имя файла в качестве имени процесса, что становится неоднозначным при наличии нескольких сервисов.
Запуск с дополнительными параметрами:
“`bash
pm2 start app.js –name "my-app" –watch –max-memory-restart 300M
“`
- `–watch`: Перезапускает процесс при изменении исходных файлов (полезно на стейджинге, не рекомендуется в продакшене)
- `–max-memory-restart 300M`: Автоматически перезапускает процесс, если он превышает 300 MB RSS-памяти — критическая защита от утечек памяти
Просмотр запущенных процессов
“`bash
pm2 list
“`
Выводит таблицу с идентификатором процесса, именем, режимом (fork/cluster), PID, статусом, использованием CPU, потреблением памяти и количеством перезапусков.
Для панели мониторинга в реальном времени:
“`bash
pm2 monit
“`
Управление процессами
“`bash
pm2 restart my-app # Graceful restart
pm2 reload my-app # Zero-downtime reload (cluster mode only)
pm2 stop my-app # Stop without removing from process list
pm2 delete my-app # Stop and remove from process list
“`
Разница между `restart` и `reload`: `restart` завершает процесс и запускает новый, вызывая кратковременный простой. `reload` (доступно только в режиме кластера) поочерёдно перезапускает воркеры, сохраняя доступность на протяжении всего процесса. Всегда используйте `reload` в продакшен-развёртываниях с кластером.
Управление логами
“`bash
pm2 logs # Stream logs from all processes
pm2 logs my-app # Stream logs for a specific process
pm2 logs my-app –lines 200 # Show last 200 lines
pm2 flush # Clear all log files
“`
По умолчанию PM2 хранит логи в `~/.pm2/logs/`. Для производственных серверов установите модуль ротации логов, чтобы предотвратить исчерпание дискового пространства:
“`bash
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 10
pm2 set pm2-logrotate:compress true
“`
Это выполняет ротацию логов при достижении 50 MB, сохраняет 10 сжатых архивов и предотвращает неконтролируемый рост логов — распространённая проблема на долго работающих серверах, которую часто замечают только тогда, когда заканчивается место на диске.
Шаг 5: Настройка автозапуска PM2 при загрузке системы
PM2 должен быть настроен на работу после перезагрузки сервера. Это обеспечивается через юнит systemd-сервиса, генерируемый самим PM2.
Сгенерируйте команду запуска:
“`bash
pm2 startup
“`
PM2 выведет команду, адаптированную к вашей системе инициализации и текущему пользователю. Она выглядит следующим образом:
“`
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu –hp /home/ubuntu
“`
Скопируйте и выполните эту точную команду. Не изменяйте её — путь к бинарному файлу PM2 и домашний каталог должны соответствовать конфигурации вашей системы.
Настройка запуска для NVM: Если вы установили Node.js через NVM, путь в сгенерированной команде будет указывать на ваш бинарный файл, управляемый NVM. Это правильно, но вы должны убедиться, что версия NVM установлена как версия по умолчанию перед запуском `pm2 startup`:
“`bash
nvm alias default 20
pm2 startup
“`
Сохраните текущий список процессов:
“`bash
pm2 save
“`
Это записывает список процессов в `~/.pm2/dump.pm2`. При перезагрузке юнит systemd читает этот файл и восстанавливает все сохранённые процессы. Если вы впоследствии добавляете или удаляете приложения, снова запустите `pm2 save`, чтобы обновить снимок.
Убедитесь, что юнит systemd активен:
“`bash
systemctl status pm2-ubuntu
“`
Замените `ubuntu` на ваше фактическое имя пользователя.
Шаг 6: Производственное развёртывание с файлами экосистемы PM2
Для всего, что выходит за рамки одного скрипта приложения, используйте файл конфигурации экосистемы PM2. Он обеспечивает воспроизводимые, версионируемые определения процессов и устраняет необходимость запоминать длинные флаги CLI.
Генерация файла экосистемы
“`bash
pm2 ecosystem
“`
Это создаёт `ecosystem.config.js` в текущем каталоге.
Готовая к продакшену конфигурация экосистемы
“`javascript
module.exports = {
apps: [
{
name: 'api-server',
script: './src/server.js',
instances: 'max',
exec_mode: 'cluster',
watch: false,
max_memory_restart: '500M',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
error_file: '/var/log/pm2/api-server-error.log',
out_file: '/var/log/pm2/api-server-out.log',
merge_logs: true,
env: {
NODE_ENV: 'development',
PORT: 3000
},
env_production: {
NODE_ENV: 'production',
PORT: 8080
}
},
{
name: 'worker',
script: './src/worker.js',
instances: 2,
exec_mode: 'fork',
cron_restart: '0 2 * * *',
env_production: {
NODE_ENV: 'production'
}
}
]
};
“`
Пояснение ключевых решений по конфигурации:
- `instances: 'max'`: PM2 автоматически создаёт по одному воркеру на каждое логическое ядро CPU. На 4-ядерном сервере это создаёт 4 процесса Node.js, полностью используя возможности оборудования.
- `exec_mode: 'cluster'`: Использует встроенный модуль кластера Node.js. Все экземпляры совместно используют один порт через балансировку нагрузки сокетов операционной системы.
- `exec_mode: 'fork'`: Запускает процесс как отдельный дочерний процесс. Требуется для приложений, которые не являются HTTP-серверами (обработчики очередей, запланированные задания, WebSocket-серверы со sticky-сессиями).
- `merge_logs: true`: Объединяет stdout всех экземпляров кластера в единый файл лога, что значительно упрощает анализ логов.
- `cron_restart`: Планирует автоматические перезапуски с использованием синтаксиса cron. Полезно для воркеров, накапливающих состояние, или для применения ночных изменений конфигурации.
Запуск с файлом экосистемы
“`bash
pm2 start ecosystem.config.js –env production
pm2 save
“`
Рабочий процесс развёртывания без простоев
При развёртывании новой версии вашего приложения:
“`bash
git pull origin main
npm install –production
pm2 reload ecosystem.config.js –env production
“`
`pm2 reload` отправляет `SIGINT` каждому воркеру по одному, ожидает готовности нового воркера, затем завершает старый. Ваше приложение должно корректно обрабатывать `SIGINT` и сигнализировать о готовности с помощью `process.send('ready')`, чтобы это работало правильно.
Обработчик корректного завершения в вашем приложении:
“`javascript
process.on('SIGINT', () => {
server.close(() => {
console.log('HTTP server closed');
process.exit(0);
});
});
“`
Шаг 7: Мониторинг и наблюдаемость PM2
Встроенный мониторинг
“`bash
pm2 monit
“`
Отображает графики CPU и памяти в реальном времени для каждого процесса в терминале.
Информация о процессах
“`bash
pm2 show my-app
“`
Выводит подробные метаданные: время работы, количество перезапусков, версионирование, путь к интерпретатору, переменные окружения и расположение файлов логов.
Веб-панель PM2 (PM2 Plus)
PM2 предлагает размещённую панель мониторинга на pm2.io. Подключите ваш сервер:
“`bash
pm2 link <secret_key> <public_key>
“`
Это обеспечивает исторические метрики, оповещения и удалённое управление процессами — особенно ценно при управлении несколькими серверами или когда вам нужна видимость без SSH-доступа.
Шаг 8: Обновление Node.js и PM2
Обновление PM2
“`bash
sudo npm install -g pm2@latest
pm2 update
“`
`pm2 update` необходим после обновления бинарного файла PM2 — он обновляет работающий демон PM2 в памяти без прерывания запущенных процессов.
Обновление Node.js через NodeSource
Повторно запустите скрипт настройки для новой мажорной версии:
“`bash
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash –
sudo apt install nodejs -y
“`
После обновления Node.js перезапустите PM2, чтобы убедиться, что он использует новый бинарный файл:
“`bash
pm2 restart all
“`
Обновление Node.js через NVM
“`bash
nvm install 22
nvm alias default 22
nvm use 22
pm2 restart all
“`
Если вы изменили версию NVM по умолчанию, повторно сгенерируйте скрипт запуска PM2, чтобы обновить путь к бинарному файлу в юните systemd:
“`bash
pm2 unstartup
pm2 startup
pm2 save
“`
Соображения по усилению безопасности
Запуск приложений Node.js в продакшене требует внимания помимо управления процессами:
- Запускайте от имени непривилегированного пользователя: Никогда не запускайте PM2 или Node.js от имени root. Создайте выделенного системного пользователя (`adduser –system –group nodeapp`) и запускайте PM2 под этой учётной записью.
- Управление переменными окружения: Не вшивайте секреты в `ecosystem.config.js`. Используйте файл `.env`, загружаемый через `dotenv`, или передавайте секреты через ваш конвейер развёртывания. Файл экосистемы обычно фиксируется в системе контроля версий.
- Обратный прокси: Разместите Nginx или Caddy перед вашим приложением Node.js. Это обеспечивает завершение TLS, раздачу статических файлов, ограничение частоты запросов и буферизацию запросов. Дополните это решением SSL Сертификаты для принудительного использования HTTPS.
- Правила брандмауэра: Заблокируйте прямой доступ к порту Node.js (например, 3000, 8080) из публичного интернета. Только обратный прокси должен взаимодействовать с Node.js.
- Ограничения ресурсов: Установите `max_memory_restart` в PM2 и настройте системные значения `ulimit`, чтобы предотвратить дестабилизацию сервера одним неуправляемым процессом.
Для высоконагруженных производственных развёртываний, где критична изоляция ресурсов, среда Выделенные серверы обеспечивает полный контроль над оборудованием и устраняет проблему «шумного соседа», присущую общей инфраструктуре.
Выбор подходящей среды хостинга для Node.js
| Рабочая нагрузка | Рекомендуемая среда | Обоснование |
|---|
| — | — | — |
|---|
| Личные проекты, стейджинг | [VPS Хостинг](https://alexhost.com/ru/vps/) | Экономичность, полный root-доступ, масштабируемость |
|---|
| Высоконагруженные API | [Выделенные серверы](https://alexhost.com/ru/dedicated-servers/) | Предсказуемая производительность, отсутствие конкуренции за ресурсы |
|---|
| ML-инференс + Node.js | [GPU Хостинг](https://alexhost.com/ru/gpu-hosting/) | Перенос вычислительно интенсивных задач на GPU-воркеры |
|---|
| Управляемая панель управления | [VPS с cPanel](https://alexhost.com/ru/vps/control-panels/cpanel-vps/) | Управление процессами и файлами через графический интерфейс |
|---|
Контрольный список технических решений
Используйте этот контрольный список перед развёртыванием Node.js и PM2 в продакшене:
- [ ] Node.js установлен через NodeSource (сервер) или NVM (разработка) — не через пакет Ubuntu universe
- [ ] PM2 установлен глобально с правильными разрешениями для вашего метода установки
- [ ] Приложение запущено с флагом `–name` и определённым порогом `–max-memory-restart`
- [ ] Режим кластера включён для HTTP-серверов; режим fork используется для фоновых воркеров
- [ ] `pm2 startup` выполнен и сгенерированная команда запущена с sudo
- [ ] `pm2 save` выполнен после настройки всех процессов
- [ ] Модуль ротации логов установлен и настроен
- [ ] Nginx или Caddy настроен как обратный прокси с TLS
- [ ] Приложение корректно обрабатывает `SIGINT` для перезагрузок без простоев
- [ ] Секреты управляются вне `ecosystem.config.js`
- [ ] Юнит systemd PM2 проверен с помощью `systemctl status pm2-<username>`
- [ ] Брандмауэр блокирует прямой доступ к портам Node.js из публичного интернета
Часто задаваемые вопросы
В чём разница между режимом fork и режимом кластера в PM2?
Режим fork запускает приложение как единственный дочерний процесс — один экземпляр, используется одно ядро CPU. Режим кластера использует нативный модуль кластера Node.js для создания нескольких рабочих процессов, которые совместно используют один TCP-порт, обеспечивая истинное использование нескольких ядер и перезагрузки без простоев. Используйте режим кластера для HTTP/HTTPS-серверов и режим fork для воркеров, заданий cron или приложений, поддерживающих внутреннее состояние, несовместимое с многопроцессным совместным использованием.
Почему PM2 не перезапускается после перезагрузки сервера, хотя я выполнил `pm2 startup`?
Наиболее распространённая причина — `pm2 save` не был выполнен после настройки процессов, поэтому файл дампа пуст или отсутствует. Вторая по распространённости причина — несоответствие пути NVM: если версия NVM по умолчанию была изменена после генерации скрипта запуска, юнит systemd указывает на несуществующий бинарный файл. Решите это, запустив `pm2 unstartup`, установив правильную версию NVM по умолчанию, затем повторно выполнив `pm2 startup` и `pm2 save`.
Может ли PM2 управлять процессами, не связанными с Node.js?
Да. PM2 может управлять любым исполняемым файлом, указав интерпретатор. Например: `pm2 start script.py –interpreter python3`. Это делает PM2 полезным в качестве универсального супервизора процессов для микросервисных архитектур со смешанными языками.
Как запустить несколько приложений Node.js на разных портах за одним сервером?
Определите каждое приложение как отдельную запись в `ecosystem.config.js` с отдельными переменными окружения `PORT`. Настройте Nginx как обратный прокси с отдельными блоками `server` или директивами `location`, маршрутизирующими к каждому порту. Все приложения совместно используют один демон PM2 и управляются через единое представление `pm2 list`.
Что лучше использовать для производственного VPS — NVM или NodeSource?
NodeSource, как правило, предпочтительнее для производственных серверов. Он устанавливает Node.js как системный пакет, делая его доступным для всех пользователей и системных сервисов без зависимостей от инициализации оболочки. Модель активации NVM для каждого пользователя и каждой оболочки создаёт тонкие сбои в юнитах systemd, заданиях cron и конвейерах CI/CD, которые выполняются вне интерактивного сеанса оболочки. Оставьте NVM для локальных машин разработки, где одновременное управление несколькими версиями Node.js является реальной необходимостью.
