Запуск Axum как системный сервис с systemd
Systemd — это система инициализации и управления службами в Linux, которая позволяет запускать, останавливать и мониторить приложения Axum в качестве системных служб.
Содержание
- Создание systemd-сервиса
- Управление сервисом
- Настройка автоматического перезапуска
- Управление зависимостями
- Логирование
- Мониторинг состояния
- Работа с переменными окружения
- Лучшие практики
Создание systemd-сервиса
Основной конфигурационный файл
Для запуска Axum-приложения как системной службы, создайте файл .service
в директории /etc/systemd/system/
:
sudo nano /etc/systemd/system/axum-app.service
Базовая конфигурация:
[Unit]
Description=Axum Web Service
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=axumuser
Group=axumuser
WorkingDirectory=/opt/axum-app
ExecStart=/opt/axum-app/axum-server
Restart=on-failure
RestartSec=5s
Environment="RUST_LOG=info"
[Install]
WantedBy=multi-user.target
Подготовка окружения
- Создайте пользователя (для безопасности избегайте запуска от root):
sudo useradd -r -s /bin/false axumuser
- Подготовьте директорию для приложения:
sudo mkdir -p /opt/axum-app
sudo cp /path/to/your/axum-server /opt/axum-app/
sudo chown -R axumuser:axumuser /opt/axum-app
sudo chmod 755 /opt/axum-app/axum-server
Управление сервисом
Перезагрузка конфигурации systemd
После создания или изменения конфигурационного файла, выполните:
sudo systemctl daemon-reload
Управление жизненным циклом
Чтобы запустить сервис:
sudo systemctl start axum-app
Остановка сервиса:
sudo systemctl stop axum-app
Перезапуск:
sudo systemctl restart axum-app
Проверка статуса:
sudo systemctl status axum-app
Автозапуск после перезагрузки
Чтобы сервис автоматически запускался после перезагрузки сервера:
sudo systemctl enable axum-app
Отключение автозапуска:
sudo systemctl disable axum-app
Настройка автоматического перезапуска
Systemd поддерживает различные стратегии перезапуска:
[Service]
# Перезапуск при аварийном завершении
Restart=on-failure
# Пауза перед перезапуском (в секундах)
RestartSec=5
# Другие возможные значения Restart:
# always - всегда перезапускать независимо от причины завершения
# on-abnormal - перезапуск при аварийных сигналах или таймауте
# on-watchdog - перезапуск только при срабатывании сторожевого таймера
# on-abort - перезапуск только при получении сигнала аварийного завершения
# no - не перезапускать (по умолчанию)
Ограничение числа перезапусков
Предотвращение бесконечных перезапусков при стабильных сбоях:
[Service]
Restart=on-failure
RestartSec=5s
# Максимум 3 перезапуска каждые 30 секунд
StartLimitIntervalSec=30
StartLimitBurst=3
# Что делать, если достигнут лимит перезапусков
StartLimitAction=none # или reboot, poweroff
Управление зависимостями
Управление порядком запуска сервисов:
[Unit]
# Запуск после сетевого подключения
After=network.target
# И после того, как база данных запущена
After=postgresql.service
# Если наш сервис зависит от базы данных
Requires=postgresql.service
# Опционально: если база данных не обязательна, но желательна
Wants=postgresql.service
Логирование
Systemd автоматически перехватывает вывод приложения и направляет его в журнал:
# Просмотр логов сервиса
sudo journalctl -u axum-app
# Просмотр только последних 100 строк
sudo journalctl -u axum-app -n 100
# Отслеживание новых сообщений в реальном времени
sudo journalctl -u axum-app -f
Настройка логов в конфигурации
[Service]
# Журналирование стандартного вывода и ошибок
StandardOutput=journal
StandardError=journal
# Дополнительные метаданные для журнала
SyslogIdentifier=axum-app
Мониторинг состояния
Базовый статус
sudo systemctl status axum-app
Расширенная проверка здоровья
Systemd может контролировать здоровье сервиса через HTTP:
[Service]
Type=simple
ExecStart=/opt/axum-app/axum-server
# Проверка здоровья каждые 30 секунд
ExecStartPost=/bin/sh -c 'sleep 5 && systemd-notify --ready'
WatchdogSec=30
# Скрипт, который проверяет работоспособность сервиса
ExecStartPre=/opt/axum-app/healthcheck.sh
Скрипт проверки здоровья healthcheck.sh
:
#!/bin/bash
# Простая проверка, что сервис отвечает на HTTP-запросы
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/health)
if [ "$response" = "200" ]; then
systemd-notify WATCHDOG=1
exit 0
else
exit 1
fi
Работа с переменными окружения
Указание переменных в конфигурации
[Service]
Environment="DATABASE_URL=postgres://user:pass@localhost/mydb"
Environment="RUST_LOG=info"
Environment="PORT=3000"
Использование файла с переменными окружения
[Service]
EnvironmentFile=/etc/axum-app/app.env
Файл /etc/axum-app/app.env
:
DATABASE_URL=postgres://user:pass@localhost/mydb
RUST_LOG=info
PORT=3000
JWT_SECRET=your_secret_key
Лучшие практики
1. Ограничение ресурсов
[Service]
# Ограничение CPU
CPUQuota=50%
# Ограничение памяти
MemoryLimit=512M
# Ограничение на количество файловых дескрипторов
LimitNOFILE=65535
2. Безопасность
[Service]
# Запуск от непривилегированного пользователя
User=axumuser
Group=axumuser
# Дополнительные ограничения безопасности
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
NoNewPrivileges=true
PrivateDevices=true
3. Уведомления при сбоях
Можно настроить отправку уведомлений при сбоях:
[Service]
ExecStopPost=/opt/axum-app/notify_failure.sh
Скрипт notify_failure.sh
:
#!/bin/bash
if [ "$SERVICE_RESULT" = "failure" ]; then
# Отправка уведомления в Slack, Telegram, по email и т.д.
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Axum service failed!"}' \
https://hooks.slack.com/services/YOUR_WEBHOOK_URL
fi
4. Корректная обработка сигналов
В вашем Axum-приложении реализуйте обработку сигналов завершения для graceful shutdown:
use tokio::signal;
#[tokio::main]
async fn main() {
// Настройка приложения
let app = Router::new()
// ... маршруты и слои
;
// Получение адреса из конфигурации
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
// Запуск сервера с graceful shutdown
axum::Server::bind(&addr)
.serve(app.into_make_service())
.with_graceful_shutdown(shutdown_signal())
.await
.unwrap();
}
async fn shutdown_signal() {
let ctrl_c = async {
signal::ctrl_c()
.await
.expect("Failed to install Ctrl+C handler");
};
#[cfg(unix)]
let terminate = async {
signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("Failed to install signal handler")
.recv()
.await;
};
#[cfg(not(unix))]
let terminate = std::future::pending::<()>();
tokio::select! {
_ = ctrl_c => {},
_ = terminate => {},
}
println!("Shutdown signal received, starting graceful shutdown");
}
5. Динамическая конфигурация
Для проектов, требующих разные конфигурации для разных окружений:
# Создание файлов конфигурации для разных окружений
sudo mkdir -p /etc/axum-app/environments
sudo cp app.env.production /etc/axum-app/environments/production
sudo cp app.env.staging /etc/axum-app/environments/staging
И в сервис добавляем:
[Service]
EnvironmentFile=/etc/axum-app/environments/%i
Затем можно запускать разные экземпляры:
# Запуск продакшен-версии
sudo systemctl start axum-app@production
# Запуск staging-версии
sudo systemctl start axum-app@staging
6. Полный пример конфигурации
[Unit]
Description=Axum Web Application
Documentation=https://github.com/yourusername/axum-app
After=network.target postgresql.service
Wants=network-online.target postgresql.service
[Service]
User=axumuser
Group=axumuser
WorkingDirectory=/opt/axum-app
ExecStart=/opt/axum-app/axum-server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StartLimitIntervalSec=60
StartLimitBurst=3
# Переменные окружения
EnvironmentFile=/etc/axum-app/app.env
# Ограничения ресурсов
CPUWeight=100
MemoryHigh=512M
MemoryMax=1G
LimitNOFILE=65535
# Безопасность
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
NoNewPrivileges=true
CapabilityBoundingSet=
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
# Логирование
StandardOutput=journal
StandardError=journal
SyslogIdentifier=axum-app
[Install]
WantedBy=multi-user.target
7. Проверка и отладка
Проверка конфигурации:
sudo systemd-analyze verify /etc/systemd/system/axum-app.service
Запуск с отладочной информацией:
sudo SYSTEMD_LOG_LEVEL=debug systemctl start axum-app
Использование systemd для запуска Axum-приложений в качестве системных служб обеспечивает надежность, автоматическое восстановление при сбоях и интеграцию с экосистемой Linux. Это делает его идеальным выбором для развертывания веб-приложений в production-окружении.