Systemd: простая настройка и управление сервисами

Краткие ссылки
- Работа с systemd и службами
- Простая настройка сервиса
- Отладка и типичные ошибки
- Безопасность и ограничения для сервисов
- SOP: развертывание нового сервиса
- Критерии приёмки и тесты
- Альтернативы и когда systemd не подходит
Работа с systemd и службами
Systemd хранит конфигурацию единиц (units) в нескольких местах. Важно понимать, куда помещать файлы и какие пути имеют приоритет:
- /lib/systemd/system/ — стандартные unit-файлы, поставляемые пакетами; при обновлениях пакетов эти файлы могут перезаписываться.
- /etc/systemd/system/ — локальные переопределения и пользовательские сервисы; здесь ставьте свои .service файлы.
- /etc/systemd/users/ — сервисы, запускаемые от имени отдельных пользователей (для user-сессий).
Определение: unit — абстракция, которой управляет systemd (служба, сокет, mount, target и т. д.). Unit-файлы описывают поведение этих объектов.
Полезные команды:
service --status-allВывод показывает список системных сервисов: “+” — запущен, “-“ — остановлен.
service status nginxПоказывает краткий статус конкретной службы. Для подробных логов используйте журнал systemd:
journalctl -fn 50 -u nginxОпции: -n 50 — последние 50 строк; -f — следить в реальном времени; -u
Совет: многие приложения всё ещё пишут лог в свои access/error файлы. Journal полезен для всего, что пишет в stdout/stderr, а также для сообщений systemd.
Простая настройка сервиса
Задача: запустить приложение как фоновой сервис, обеспечить автозапуск и перезапуск при завершении.
- Создайте unit-файл в /etc/systemd/system/ с расширением .service:
sudo touch /etc/systemd/system/myapp.service
sudo chmod 644 /etc/systemd/system/myapp.service- Пример минимального unit-файла:
[Unit]
Description=MyApp service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=serviceuser
Group=servicegroup
WorkingDirectory=/opt/myapp
Environment=ENV=production
ExecStartPre=/usr/bin/test -x /opt/myapp/bin/myapp
ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yml
ExecStop=/bin/kill -s TERM $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID
[Install]
WantedBy=multi-user.targetПояснения по секциям и директивам:
[Unit]
- Description — человекочитаемое описание.
- After — гарантирует запуск после указанного target или unit; не делает жёсткой зависимости.
- StartLimitIntervalSec — интервал для ограничений повторных попыток запуска (0 отключает лимит).
[Service]
- Type — стратегия запуска: simple, forking, oneshot, notify и прочие.
- Restart / RestartSec — политика перезапуска и задержка перед повторным стартом.
- User / Group — под каким пользователем будет работать процесс.
- WorkingDirectory — рабочая директория процесса.
- Environment — переменные окружения; для множества переменных можно использовать EnvironmentFile=
- ExecStartPre / ExecStart / ExecStartPost / ExecStop / ExecReload — команды для жизненного цикла.
[Install]
- WantedBy — указывает, к какому target привязать сервис при enable. multi-user.target — стандарт для системных демонов.
Важно: если вы меняете unit-файл, выполните:
sudo systemctl daemon-reloadЗатем включите автозапуск и запустите сервис:
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myappАльтернативный способ запуска через service:
sudo service myapp start
sudo service myapp restartОтладка и типичные ошибки
Если сервис не запускается — проверьте по шагам:
- systemctl status myapp — выводит текущий статус и последние строки журнала.
- journalctl -u myapp -n 200 — больше строк для истории.
- systemctl daemon-reload — если вы редактировали unit.
- systemctl start myapp и systemctl restart myapp — смотрите отклик.
- Проверка исполняемого файла: права, SELinux/AppArmor, отсутствие зависимостей.
- systemd-analyze verify /etc/systemd/system/myapp.service — проверяет синтаксис и общие ошибки unit-файла.
- Проверить WorkingDirectory и переменные окружения; часто сервис падает из-за отсутствия файлов или прав.
- Посмотреть, не блокируется ли порт другим процессом.
Важно: journalctl может показывать только сообщения, направленные в системный журнал. Многие приложения логируют отдельно — проверьте /var/log/yourapp или путь, явно указанный в конфигурации.
Примеры ошибок и их причины:
- Немедленный выход процесса после старта: неправильный ExecStart, отсутствие прав или неправильно заданные аргументы.
- Permission denied при чтении файлов: проверьте User/Group и права файлов/директорий.
- Сервис повторно рестартуется в цикле: проверьте Restart и StartLimit*, используйте RestartPreventExitStatus, если нужно.
Безопасность и ограничения для сервисов
Systemd предоставляет множество опций для изоляции и ограничения сервисов. Некоторые полезные директивы:
- NoNewPrivileges=yes — запрещает повышать привилегии дочерним процессам.
- PrivateTmp=yes — изолирует временные каталоги процесса.
- ProtectSystem=full — делает /usr и /etc только для чтения (по умолчанию).
- ProtectHome=yes — ограничивает доступ к домашним каталогам.
- ReadOnlyDirectories=/var/lib/somepath — монтирует перечисленные каталоги в режиме только чтение для процесса.
- CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SYS_ADMIN — список допустимых capability; лучше сужать.
- AmbientCapabilities=CAP_NET_BIND_SERVICE — для передачи определённых capability процессу.
- RestrictAddressFamilies=AF_INET AF_INET6 — ограничение сетевых семейств.
- SystemCallFilter=@default @network-io — ограничение syscalls (требует аккуратной настройки).
Важно: безопасность — это баланс. Начните с простых директив (User, NoNewPrivileges, PrivateTmp) и добавляйте по мере необходимости. Тестируйте сервисы в staging перед продакшеном.
SOP: развертывание нового сервиса
Шаги для безопасного и повторяемого развертывания:
- Создать системного пользователя и группу:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin serviceuser- Разместить бинарник в /opt/myapp и установить права:
sudo chown -R serviceuser:servicegroup /opt/myapp
sudo chmod -R 750 /opt/myapp- Написать unit-файл в /etc/systemd/system/myapp.service с нужными ограничениями безопасности.
- Проверить синтаксис: systemd-analyze verify /etc/systemd/system/myapp.service
- Перезагрузить демон: sudo systemctl daemon-reload
- Включить и запустить сервис: sudo systemctl enable –now myapp
- Проверить статус и логи: sudo systemctl status myapp; sudo journalctl -u myapp -f
- Добавить мониторинг и алерты: проверять, что сервис жив и отвечает на healthcheck.
Критерии приёмки
- Сервис запускается после reboot и помечен как enabled.
- Живая проверка (healthcheck) возвращает OK в течение 30 секунд после запуска.
- Логи доступны через journalctl и включают stdout/stderr приложения.
- Права доступа минимальны: User не root, директории с правильными правами.
- Принятые политики безопасности применяются (NoNewPrivileges, PrivateTmp и т. п.).
Тесты и случаи приёмки
- Тест 1: Остановка и запуск — после sudo systemctl restart myapp сервис возвращается в состояние active.
- Тест 2: Перезагрузка хоста — сервис автоматически стартует и проходит healthcheck.
- Тест 3: Нагрузка — при резком увеличении запросов сервис продолжает работать или перезапускается согласно политике Restart.
- Тест 4: Отказ зависимости — если зависимый сервис недоступен, unit остаётся в предсказуемом состоянии (Backoff/failed).
Роль-по-ролевая чек-лист (Developer / Admin / Оператор)
Developer:
- Предоставить конфиг и startup команду (ExecStart).
- Описать зависимости и healthcheck.
- Указать переменные окружения и файлы конфигурации.
Администратор:
- Создать system user/group и права на каталоги.
- Настроить unit-файл с базовой безопасностью.
- Добавить мониторинг и ротацию логов.
Оператор:
- Проверять status и журнал после деплоя.
- Настроить алерты на падение или повторные рестарты.
- Проводить плановые перезапуски и обновления.
Альтернативы и когда systemd не подходит
Когда выбрать systemd:
- Сервисы, которые должны автоматически стартовать при загрузке и управляться системой.
- Демоны, которым нужен перезапуск и интеграция с журналом systemd.
Когда использовать альтернативы:
- Лёгкие одноразовые фоновые процессы для разработческой среды: tmux / screen достаточно.
- Node.js процессы в окружении разработчика: pm2 удобен для перезапуска и кластеризации.
- Контейнеризированные приложения: Docker/Kubernetes берут на себя управление жизненным циклом, поэтому systemd в контейнере часто избыточен.
- Простые скрипты cron — для периодических задач.
Контрпример: если ваше приложение разворачивается в Kubernetes, управляйте жизненным циклом в Kubernetes, а не через systemd на контейнере.
Ментальные модели и эвристики
- “Systemd — это оркестр“: unit-файлы описывают ноты, targets задают сцену запуска.
- Безопасность по принципу наименьшего привилегирования: минимум прав, необходимые для работы.
- Сохраните idempotent SOP: деплой должен давать одинаковый результат при повторном выполнении.
Безопасность: быстрые рекомендации
- Не запускайте приложение от root без необходимости.
- Добавляйте NoNewPrivileges=yes и PrivateTmp=yes.
- Ограничьте возможности директивами CapabilityBoundingSet и RestrictAddressFamilies.
- Для сетевых демонов используйте привилегию CAP_NET_BIND_SERVICE вместо запуска от root.
Краткое резюме
Systemd — мощный инструмент для управления процессами и службами в Linux. Для правильной настройки сервиса создайте unit-файл в /etc/systemd/system/, укажите ExecStart и базовые параметры безопасности, затем выполните daemon-reload, enable и start. Для отладки используйте systemctl status и journalctl. Тестируйте и автоматизируйте SOP для повторяемого деплоя.
Важно: перед применением жёстких ограничений протестируйте service в staging, чтобы избежать неожиданного поведения в продакшене.
Похожие материалы
Sentry и GitLab для React: настройка и практика
Exim: направить входящую почту в скрипт
Удаление Git или смена удалённого репозитория
Автообновление страниц в браузере — расширения и советы
Go For It — обзор простого таймер‑todo для Linux