systemd: управление сервисами

systemd — система инициализации Linux, управляющая службами (сервисами): запускает их при старте, перезапускает при падении, собирает логи через journald.

Зачем нужно

Без systemd приложение на сервере останавливается при закрытии SSH-сессии или перезагрузке сервера. Systemd unit-файл превращает Node.js приложение в системный сервис: автозапуск, перезапуск при падении, централизованные логи через journalctl. Это стандартный способ управления процессами без Docker.

Где используется

  • Запуск Node.js / Python / Go приложения как системного сервиса
  • Nginx, PostgreSQL, Redis управляются через systemd
  • Cron-like задачи через systemd timers
  • Мониторинг состояния процессов на сервере

Основной контент

Управление сервисами

# Основные команды
sudo systemctl start myapp          # запустить
sudo systemctl stop myapp           # остановить
sudo systemctl restart myapp        # перезапустить
sudo systemctl reload myapp         # перезагрузить конфиг (без рестарта)
sudo systemctl status myapp         # статус сервиса
sudo systemctl enable myapp         # автозапуск при загрузке
sudo systemctl disable myapp        # отключить автозапуск

# Просмотр логов сервиса
sudo journalctl -u myapp            # все логи
sudo journalctl -u myapp -f         # follow (live)
sudo journalctl -u myapp --since "1 hour ago"
sudo journalctl -u myapp -n 100     # последние 100 строк

Создание unit-файла для Node.js

# /etc/systemd/system/myapp.service
[Unit]
Description=My Node.js Application
Documentation=https://github.com/myuser/myapp
After=network.target postgresql.service    # запускать после сети и БД

[Service]
Type=simple
User=deploy                               # запускать от непривилегированного пользователя
Group=deploy
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node dist/index.js
ExecReload=/bin/kill -HUP $MAINPID        # reload signal

# Автоматический перезапуск
Restart=on-failure
RestartSec=5s
StartLimitInterval=60s
StartLimitBurst=3                         # не более 3 перезапусков за 60s

# Переменные окружения
Environment=NODE_ENV=production
Environment=PORT=3000
EnvironmentFile=/etc/myapp.env            # дополнительные переменные из файла

# Логи
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# Ограничения безопасности
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
# Активировать сервис
sudo systemctl daemon-reload         # перечитать unit-файлы
sudo systemctl enable --now myapp    # включить и запустить

# Проверить
sudo systemctl status myapp

Файл с переменными окружения

# /etc/myapp.env (права 600, владелец root или deploy)
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
REDIS_URL=redis://localhost:6379
SECRET_KEY=supersecretkey
sudo chmod 600 /etc/myapp.env
sudo chown root:root /etc/myapp.env

systemd timers (альтернатива cron)

# /etc/systemd/system/cleanup.service
[Unit]
Description=Database cleanup job

[Service]
Type=oneshot
User=deploy
ExecStart=/usr/bin/node /var/www/myapp/scripts/cleanup.js

# /etc/systemd/system/cleanup.timer
[Unit]
Description=Run cleanup every day at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true             # запустить если пропустили время

[Install]
WantedBy=timers.target
sudo systemctl enable --now cleanup.timer
systemctl list-timers                    # просмотр таймеров

Частые ошибки

  • Забыть daemon-reload после изменения unit-файла — systemd использует старую версию
  • Запуск от root без необходимости — указывать User= и Group=
  • Restart=always без StartLimitBurst — сервис перезапускается бесконечно при проблемах с конфигом
  • Хранить секреты в Environment= внутри unit-файла (видны через systemctl show) — использовать EnvironmentFile= с ограниченными правами

Связанные темы

Ресурсы