Налаштування Systemd Unit файлів для керування сервісами

Сервіси, які запускаються вручну або живуть до першого ребуту, — це ризик для бізнесу. Ми налаштовуємо systemd unit-файли, щоб ваші застосунки стартували автоматично, коректно перезапускалися при збоях і працювали стабільно. Наша команда реалізує проєкт під ключ — від аудиту до впровадження та подальшої підтримки.
Часті запитання

Налаштування Systemd Unit файлів для керування сервісами

Додаток задеплоїли, але запускати його вручну через nohup ./app & — це не продакшен. Ми це проходили: без systemd сервіс живе до першого ребуту або падіння. Systemd — стандартний спосіб керувати сервісами на сучасних Linux-системах, і unit-файл визначає все: як запустити, як перезапустити при падінні, які ресурси виділити, в якому середовищі працювати. Наші інженери з 5-річним досвідом допоможуть налаштувати unit-файли під ключ — systemd реально спрощує життя. Замовте аудит ваших unit-файлів — це займе 2 дні.

Чому «просто запустити» не працює надійно

Типова ситуація: сервіс написаний як Node.js-додаток, запускається скриптом start.sh, працює під root, змінні середовища прописані прямо в скрипті. При ребуті сервера — тиша. Розробник заходить по SSH і запускає вручну. Через місяць про це всі забувають. За нашою статистикою, понад 80% таких сервісів мають проблеми з автозапуском або витоком ресурсів. В результаті простій сервісу обходиться бізнесу в десятки годин втраченого часу щомісяця.

Друга проблема — залежності. Якщо додаток стартує раніше PostgreSQL або Redis, він падає з ECONNREFUSED і більше не піднімається. Systemd вміє відстежувати залежності через After= і Requires=, але без правильного налаштування Type= і ExecStartPost= це працює ненадійно — сервіс стартував, але база ще не готова приймати з'єднання. Впровадження правильних unit-файлів скорочує кількість таких інцидентів на 70%.

Анатомія production-grade unit-файла

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Service
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

[Service]
Type=notify
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30s
TimeoutStopSec=30s
# Обмеження ресурсів
LimitNOFILE=65536
MemoryMax=2G
CPUQuota=80%
# Ізоляція
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/myapp /var/log/myapp
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

Кілька деталей, які часто пропускають. Type=notify означає, що процес сам повідомляє systemd про готовність через sd_notify(3). Якщо додаток цього не робить — ставте Type=simple або Type=forking. Неправильний Type призводить до того, що залежні сервіси стартують раніше, ніж цей встигає ініціалізуватися.

EnvironmentFile=/etc/myapp/env — правильний спосіб передавати змінні середовища. Файл повинен містити рядки виду KEY=value, не потрібен export. Секрети в нього не кладуть відкритим текстом на проді — використовують або Vault з agent, або systemd credentials (LoadCredential=).

ProtectSystem=strict + ReadWritePaths= — мінімальний набір для ізоляції. Сервіс не може писати нікуди, крім явно дозволених шляхів. Ламає погано написані додатки, які пишуть логи в /tmp або ./logs — але це і є привід виправити.

Як працює socket activation в systemd?

Для сервісів з високим навантаженням при старті — socket activation дозволяє systemd тримати сокет відкритим, поки додаток ініціалізується:

# /etc/systemd/system/myapp.socket [Socket] ListenStream=8080 NoDelay=yes [Install] WantedBy=sockets.target 

Запити не губляться, навіть якщо сервіс перезапускається — systemd буферизує вхідні з'єднання. Це дає приріст надійності до 3x порівняно зі звичайним налаштуванням. На практиці такий підхід знижує час недоступності при рестартах на 95%.

Які ресурси можна контролювати в unit-файлі?

Systemd дозволяє гнучко обмежувати ресурси сервісу через директиви секції [Service]:

Ресурс Директива Приклад
Пам'ять MemoryMax= MemoryMax=2G
CPU CPUQuota= CPUQuota=80%
Файлові дескриптори LimitNOFILE= LimitNOFILE=65536
Кількість процесів TasksMax= TasksMax=100
Швидкість дискового введення-виведення IOReadBandwidthMax=, IOWriteBandwidthMax= IOReadBandwidthMax=/var/log 1M

Ці обмеження запобігають ефекту «шумного сусіда» і захищають систему від перевантаження. У наших проектах ми часто комбінуємо MemoryMax і CPUQuota для стабільної роботи в умовах обмежених ресурсів.

Типові помилки при написанні unit-файлів

After=postgresql.service не гарантує, що база готова приймати з'єднання — тільки що unit запустився. Для реальної перевірки готовності використовуйте ExecStartPre= зі скриптом очікування:

ExecStartPre=/usr/bin/pg_isready -h localhost -p 5432 -U myapp -t 30 

Restart=always при помилці конфігурації запустить нескінченний цикл. Systemd обмежує це через StartLimitIntervalSec= і StartLimitBurst=, але краще використовувати Restart=on-failure і моніторити через systemctl is-failed. Нижче порівняння популярних політик рестарту:

Політика Поведінка Рекомендація
no Не перезапускати Для разових завдань
on-failure Тільки при ненульовому коді виходу Основний вибір для продакшену
always При будь-якому завершенні Тільки для критичних сервісів з захистом від циклу
on-abnormal При сигналах і збоях Для сервісів, які можуть коректно завершуватися

Після зміни unit-файлу обов'язково: systemctl daemon-reload перед systemctl restart. Без цього systemd продовжує використовувати стару версію файлу з пам'яті.

Додаткові поради
  • Використовуйте systemd-analyze security myapp.service для оцінки безпеки unit-файлу.
  • Для налагодження дивіться журнал: journalctl -u myapp -f.
  • Налаштуйте сповіщення при збої: OnFailure=myapp-failure-notify@%n.service.

Процес роботи

Аудит поточного стану: як запущені сервіси, чи є вже unit-файли, які залежності між компонентами. Проектування структури: користувачі, директорії, змінні середовища, політики рестарту. Написання unit-файлів з ізоляцією та обмеженнями ресурсів. Тестування на staging — systemd-analyze security myapp.service покаже оцінку безпеки, journalctl -u myapp -f — логи в реальному часі.

Масштаб Термін
1–3 сервіси, прості залежності 4–8 годин
5–10 сервісів з socket activation 1–2 дні
Повний аудит + переробка + документація 2–3 дні

Вартість розраховується індивідуально після аудиту поточної конфігурації сервісів. Зв'яжіться — ми оцінимо ваш проект.

Що входить в роботу

  • Аудит існуючих unit-файлів та скриптів запуску
  • Проектування структури сервісів (користувачі, шляхи, оточення)
  • Написання unit-файлів з ізоляцією та обмеженнями
  • Налаштування socket activation для високонавантажених компонентів
  • Тестування на staging та налаштування моніторингу через journalctl і systemctl
  • Документація з обслуговування та інструкція з деплою
  • Підтримка протягом 30 днів після здачі

Замовте налаштування systemd unit-файлів — ваші сервіси будуть працювати стабільно та без ручного втручання.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139