---
title: "Как запустить Node.js-приложение на VPS: PM2, nginx и systemd"
description: "Node.js на VPS с Ubuntu или Debian: установка LTS-версии, отдельный пользователь, .env, запуск под PM2 или systemd, nginx как прокси и обновление без простоя."
url: https://tihost.io/blog/nodejs-app-on-vps
language: ru
section: "Руководства"
published: 2026-10-05
updated: 2026-10-05
publisher: Tihost (https://tihost.io)
---

# Как запустить Node.js-приложение на VPS: PM2, nginx и systemd

> **Коротко:** Чтобы Node.js-приложение работало на VPS круглосуточно, установите актуальную LTS-версию Node.js из репозитория NodeSource, заведите для приложения отдельного пользователя, вынесите секреты в .env и запустите процесс под PM2: `pm2 start`, затем `pm2 save` и `pm2 startup`. Снаружи на портах 80 и 443 работает nginx, а новый код выкатывается без простоя командой `pm2 reload`.

**Главное:**

- Node.js на сервер ставят из репозитория NodeSource или через nvm: пакет `nodejs` из стандартного репозитория Ubuntu и Debian обычно заметно старше актуальной LTS-версии.
- PM2 держит Node.js-приложение запущенным круглосуточно: `pm2 start` запускает процесс, `pm2 save` запоминает список процессов, `pm2 startup` поднимает их после перезагрузки сервера.
- Node.js-приложение слушает локальный порт (например, 3000), а наружу на портах 80 и 443 смотрит nginx как обратный прокси - в нём же настраивается HTTPS.
- `pm2 reload` в режиме cluster перезапускает процессы Node.js по одному, поэтому обновление кода проходит без простоя, а `pm2 restart` и `systemctl restart` дают короткий перерыв.
- Небольшому API или сайту на Node.js хватает VPS с 1 vCPU и 2 ГБ памяти - на Tihost такая конфигурация стоит $4.00 в месяц.

> Команды рассчитаны на Ubuntu 22.04/24.04 и Debian 12. Перед началом пройдите [первую настройку сервера](https://tihost.io/blog/vps-first-setup): дальше команды выполняются от пользователя с sudo, а не от root.

## Шаг 1. Установите актуальную LTS-версию Node.js

LTS (Long Term Support) - ветка Node.js с долгой поддержкой и исправлениями безопасности, для сервера берут именно её. Основной путь - репозиторий NodeSource: скрипт `setup_lts.x` подключает его для текущей LTS-ветки, после чего Node.js и npm ставятся и обновляются обычным `apt`. Скрипт сначала скачивается в файл - его можно прочитать перед запуском:

```bash
sudo apt update
sudo apt install -y ca-certificates curl git
curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt install -y nodejs
node -v
npm -v
```

Второй путь - nvm (Node Version Manager): он ставит Node.js в домашний каталог пользователя командой `nvm install --lts` и удобен, когда на одном сервере нужны разные версии. Минус для сервера - путь к `node` зависит от пользователя и версии, и его приходится прописывать в systemd и cron вручную. Номера LTS-веток и график поддержки - на [nodejs.org](https://nodejs.org/).

## Шаг 2. Создайте отдельного пользователя для приложения

Приложение не должно работать от root: если в нём найдут уязвимость, атакующий получит права только этого пользователя. Пользователь `app` без пароля не войдёт по SSH сам, а вы переключаетесь в него через `sudo -iu app`:

```bash
sudo adduser --disabled-password --gecos "" app
sudo -iu app
```

## Шаг 3. Загрузите код приложения

Код удобнее всего доставлять через git: клонируете репозиторий один раз, дальше обновляете `git pull`. `npm ci` ставит зависимости строго по `package-lock.json`, а `npm run build --if-present` собирает проект, если в нём есть скрипт `build` (TypeScript, Next.js, Nest):

```bash
git clone https://github.com/you/myapp.git ~/myapp
cd ~/myapp
npm ci
npm run build --if-present
```

Для приватного репозитория создайте пользователю `app` SSH-ключ (`ssh-keygen -t ed25519`) и добавьте публичную часть в репозиторий как deploy key только на чтение - так серверу не нужен ваш личный пароль или токен. Подробнее о ключах - в статье [про подключение к VPS по SSH](https://tihost.io/blog/ssh-connect-to-vps).

## Шаг 4. Вынесите настройки и секреты в .env

Пароли, токены и адреса баз данных не хранят в коде и в git - их кладут в файл `.env`, который может прочитать только владелец. Добавьте `.env` в `.gitignore`, чтобы он случайно не попал в репозиторий:

```bash
cat > ~/myapp/.env <<'EOF'
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://myapp:password@localhost:5432/myapp
EOF
chmod 600 ~/myapp/.env
```

Приложение должно само прочитать `.env`: чаще всего это пакет dotenv (`npm install dotenv` и `require("dotenv").config()` первой строкой), а в Node.js 20.6 и новее есть встроенный флаг `--env-file=.env`. При запуске через systemd файл подставляет сам systemd - об этом ниже. Если нужна база данных, её установка и настройка доступа описаны в статье [про PostgreSQL на VPS](https://tihost.io/blog/postgresql-on-vps).

## Шаг 5. Запустите приложение под PM2

PM2 - менеджер процессов для Node.js: он перезапускает упавшее приложение, собирает логи и умеет перезагружать процессы по одному. Поставьте его глобально от пользователя с sudo:

```bash
sudo npm install -g pm2
```

Запуск, сохранение списка процессов и автозапуск. `-i 2` включает режим cluster с двумя процессами - это нужно для обновления без простоя даже на сервере с 1 vCPU. `pm2 startup` создаёт сервис systemd `pm2-app`, который после перезагрузки сервера восстановит процессы из `pm2 save`:

```bash
sudo -iu app
cd ~/myapp
pm2 start server.js --name myapp -i 2
pm2 save
exit
sudo pm2 startup systemd -u app --hp /home/app
```

> Режим cluster подходит приложениям, которые не хранят состояние в памяти процесса: сессии и кеш держите в Redis или базе данных, иначе два процесса будут видеть разные данные. Если это не ваш случай, запускайте без `-i 2` - всё остальное работает так же. Документация PM2 - на [pm2.keymetrics.io](https://pm2.keymetrics.io/).

## Альтернатива PM2: сервис systemd

Если одного процесса достаточно, PM2 можно не ставить: systemd уже есть в Ubuntu и Debian и делает то же самое - запускает приложение при загрузке и перезапускает через 5 секунд после падения. `EnvironmentFile` передаёт переменные из `.env` в окружение процесса, dotenv при этом не нужен. Минус - `systemctl restart` останавливает приложение на время перезапуска:

```bash
sudo tee /etc/systemd/system/myapp.service > /dev/null <<'EOF'
[Unit]
Description=Node.js app
After=network-online.target
Wants=network-online.target

[Service]
User=app
WorkingDirectory=/home/app/myapp
EnvironmentFile=/home/app/myapp/.env
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
```

## Шаг 6. Проверьте статус и логи

`pm2 status` показывает процессы, их память и число перезапусков, `pm2 logs` - вывод приложения. Модуль `pm2-logrotate` ротирует логи, чтобы они не заняли весь диск. Для варианта с systemd то же самое дают `systemctl status myapp` и `journalctl -u myapp -f`. Команды PM2 выполняйте от пользователя `app`:

```bash
pm2 status
pm2 logs myapp --lines 100
pm2 install pm2-logrotate
```

## Шаг 7. Поставьте nginx перед приложением

Обратный прокси (reverse proxy) принимает запросы из интернета и передаёт их приложению на локальный порт. nginx берёт на себя HTTPS, сжатие, статику и лимиты, а порт 3000 остаётся закрытым снаружи. Заголовки `Upgrade` и `Connection` нужны для WebSocket. Сохраните конфиг как `/etc/nginx/sites-available/myapp`, заменив `example.com` на свой домен:

`/etc/nginx/sites-available/myapp`:

```
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
```

```bash
sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/myapp
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo ufw allow 80,443/tcp
```

Домен должен указывать на IP сервера - как это настроить, описано в статье [про привязку домена к VPS](https://tihost.io/blog/domain-to-vps). Сертификат Let's Encrypt и редирект на HTTPS добавляются за пару команд - по инструкции [nginx и Let's Encrypt](https://tihost.io/blog/nginx-letsencrypt-https).

## Шаг 8. Обновляйте приложение без простоя

`pm2 reload` в режиме cluster поднимает новый процесс, дожидается его запуска и только потом останавливает старый - и так по очереди для каждого. Пользователи не видят ошибок, пока выкатывается новая версия:

```bash
sudo -iu app
cd ~/myapp
git pull
npm ci
npm run build --if-present
pm2 reload myapp
```

## Какой VPS нужен Node.js-приложению

API, Telegram-боту или небольшому сайту на Node.js хватает 1 vCPU и 2 ГБ памяти - на Tihost это конфигурация [Starter](https://tihost.io/blog/starter-vps) за $4.00 в месяц. Если на том же сервере работают база данных и сборка фронтенда, берите 4 ГБ и больше: подробнее о расчёте - в статье [сколько оперативной памяти нужно VPS](https://tihost.io/blog/how-much-ram-vps). Серверы Tihost работают на KVM с NVMe и полным root-доступом и разворачиваются примерно за 2 минуты после оплаты.

**Запустите сервер за 2 минуты.** AMD Ryzen 9, NVMe и защита от DDoS в Германии, Финляндии и Польше. Оплата криптовалютой или картой. [Заказать сервер](https://tihost.io/login)

## Частые вопросы

### Что лучше для Node.js на сервере - PM2 или systemd?

PM2 удобнее, когда нужны режим cluster и обновление без простоя через `pm2 reload`. systemd уже встроен в Ubuntu и Debian и проще для одного процесса, но `systemctl restart` даёт короткий перерыв в работе.

### Как поставить Node.js LTS на Ubuntu?

Подключите репозиторий NodeSource скриптом `setup_lts.x` и выполните `sudo apt install -y nodejs`. Альтернатива - nvm и команда `nvm install --lts` в домашнем каталоге пользователя.

### Почему Node.js-приложение останавливается, когда я закрываю SSH?

Приложение, запущенное командой `node server.js` из терминала, завершается вместе с SSH-сессией. Запустите его под PM2 или как сервис systemd - тогда оно работает независимо от SSH и поднимается после перезагрузки сервера.

### Нужен ли nginx, если Node.js сам умеет слушать порт?

nginx перед Node.js-приложением отвечает за HTTPS, сжатие, статику и несколько сайтов на одном IP, а порт приложения остаётся закрытым снаружи. Без nginx пришлось бы запускать Node.js с правами на порты 80 и 443 и настраивать сертификаты в коде.

### Как обновить Node.js-приложение без простоя?

Запустите приложение под PM2 в режиме cluster (`pm2 start server.js -i 2`), а после `git pull` и `npm ci` выполните `pm2 reload myapp`: PM2 перезапустит процессы по одному, и запросы продолжат обслуживаться.

### Сколько памяти нужно Node.js-приложению на VPS?

Небольшому API или боту на Node.js хватает VPS с 2 ГБ памяти. Если рядом работает база данных или на сервере собирается фронтенд, удобнее 4-8 ГБ.

---

Обновлено 2026-10-05 · https://tihost.io/blog/nodejs-app-on-vps
