Skip to content
VDS · Сайти та вебсервери

Застосунок Node.js під systemd

Як запустити застосунок Node на VDS так, щоб він пережив розрив SSH і перезавантаження машини: unit systemd, змінні середовища, логи.

Оновлено 23 серпня 2026 р.

Запущений вручну node index.js завершується разом із сесією SSH. Щоб застосунок працював постійно й піднімався після перезавантаження, запустіть його як службу systemd — це вбудований механізм системи, тому встановлювати нічого не потрібно.

Підготовка

Встановіть Node з офіційного репозиторію, а не зі старого системного пакета:

curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node -v

Створіть окремого користувача — застосунок не повинен працювати від імені root:

useradd -r -m -d /srv/app -s /usr/sbin/nologin appuser
chown -R appuser:appuser /srv/app
sudo -u appuser npm ci --omit=dev --prefix /srv/app

Служба systemd

Файл /etc/systemd/system/myapp.service:

[Unit]
Description=My Node app
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/usr/bin/node /srv/app/index.js
Restart=always
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

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

Restart=always піднімає процес знову після збою. EnvironmentFile — це звичайний файл KEY=value без лапок і без export; встановіть йому права 600, адже в ньому зберігаються паролі.

Публікація через проксі

Застосунок має слухати лише 127.0.0.1:3000, а вебсервер із сертифікатом віддає його назовні:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Докладніше дивіться в розділах зворотний проксі та Let's Encrypt. Якщо застосунок слухає 0.0.0.0, він доступний з інтернету в обхід проксі та без шифрування.

Логи та оновлення

journalctl -u myapp -f
journalctl -u myapp --since "1 hour ago" -p err
systemctl restart myapp

Вивід у stdout автоматично потрапляє до журналу — налаштовувати власні файли логів чи ротацію не потрібно.

Типові помилки

СимптомПричина
status=203/EXECНеправильний шлях до node або до файлу в ExecStart — використовуйте абсолютні шляхи
Служба перезапускається по колуЗастосунок падає під час запуску: перевірте journalctl -u myapp -n 50
EADDRINUSEПроцес, запущений вручну, досі працює: ss -tulpn | grep 3000
Працює через SSH, але не як службаБракує змінних середовища — у systemd їх немає, задайте їх у EnvironmentFile
Збірка не має достатньо пам'яті на VDS-1Збирайте локально й завантажуйте готову збірку на машину

Не ставте pm2 поверх systemd. Два супервізори над одним процесом створюють плутанину: systemd вважає процес живим, поки pm2 його перезапускає.