Установка с systemd#
Это руководство описывает классическую установку в Linux с systemd.
Оно запускает два сервиса:
incidentrelay.service # HTTP API, UI, webhooks
incidentrelay-scheduler.service # reminders, escalations, periodic jobs
Планировщик должен работать как отдельный сервис. Не запускайте его внутри каждого веб-воркера.
Рекомендуемые пути#
/var/www/incidentrelay # application directory
/var/www/incidentrelay/venv # Python virtual environment
/etc/incidentrelay/incidentrelay.conf # configuration file
/var/lib/incidentrelay # SQLite database or runtime state
/var/log/incidentrelay # logs
/usr/local/lib/incidentrelay/voice_providers # custom voice providers
IncidentRelay читает путь к конфигурации из:
INCIDENTRELAY_CONFIG_FILE
Старую переменную ONCALL_CONFIG_FILE использовать не следует.
1. Установка системных пакетов#
Пример для Debian / Ubuntu:
sudo apt-get update
sudo apt-get install -y \
git \
python3 \
python3-venv \
python3-pip \
build-essential \
curl
Если вы используете PostgreSQL, установите также сборочные/runtime-зависимости PostgreSQL:
sudo apt-get install -y libpq-dev
2. Клонирование IncidentRelay#
sudo mkdir -p /var/www
sudo git clone https://github.com/roxy-wi/IncidentRelay.git /var/www/incidentrelay
cd /var/www/incidentrelay
3. Создание виртуального окружения#
sudo python3 -m venv /var/www/incidentrelay/venv
sudo /var/www/incidentrelay/venv/bin/pip install --upgrade pip
sudo /var/www/incidentrelay/venv/bin/pip install -r /var/www/incidentrelay/requirements.txt
sudo /var/www/incidentrelay/venv/bin/pip install gunicorn
Для инсталляций с PostgreSQL:
sudo /var/www/incidentrelay/venv/bin/pip install psycopg2-binary
4. Создание каталогов#
sudo mkdir -p /etc/incidentrelay
sudo mkdir -p /var/lib/incidentrelay
sudo mkdir -p /var/log/incidentrelay
sudo mkdir -p /usr/local/lib/incidentrelay/voice_providers
Установите владельца:
sudo chown -R www-data:www-data /var/www/incidentrelay
sudo chown -R www-data:www-data /var/lib/incidentrelay
sudo chown -R www-data:www-data /var/log/incidentrelay
Файлы пользовательских голосовых провайдеров — это исполняемый код Python. Держите этот каталог доступным для записи только администраторам:
sudo chown root:root /usr/local/lib/incidentrelay/voice_providers
sudo chmod 755 /usr/local/lib/incidentrelay/voice_providers
5. Создание конфигурации#
Создайте:
/etc/incidentrelay/incidentrelay.conf
Пример для SQLite:
[main]
log_level = INFO
log_file = /var/log/incidentrelay/incidentrelay.log
[server]
host = 0.0.0.0
port = 8080
public_base_url = http://localhost:8080
[database]
type = sqlite
path = /var/lib/incidentrelay/incidentrelay.db
[sqlite]
wal = true
busy_timeout = 5000
[voice]
provider = stub
providers_dir = /usr/local/lib/incidentrelay/voice_providers
callback_secret = change-me
Для продакшена за Nginx или HAProxy задайте public_base_url равным реальному внешнему URL:
[server]
public_base_url = https://incidentrelay.example.com
public_base_url используется для генерируемых ссылок и URL колбэков.
6. Установка сервисов systemd#
Скопируйте файлы сервисов:
sudo cp /var/www/incidentrelay/systemd/incidentrelay.service /etc/systemd/system/
sudo cp /var/www/incidentrelay/systemd/incidentrelay-scheduler.service /etc/systemd/system/
Перезагрузите systemd:
sudo systemctl daemon-reload
7. Запуск миграций#
cd /var/www/incidentrelay
sudo -u www-data \
INCIDENTRELAY_CONFIG_FILE=/etc/incidentrelay/incidentrelay.conf \
/var/www/incidentrelay/venv/bin/python app/migrate.py migrate
8. Создание первого пользователя-администратора#
cd /var/www/incidentrelay
sudo -u www-data \
INCIDENTRELAY_CONFIG_FILE=/etc/incidentrelay/incidentrelay.conf \
/var/www/incidentrelay/venv/bin/python manage.py create-admin \
--username admin \
--password 'change-me-123' \
--email admin@example.com
9. Запуск сервисов#
sudo systemctl enable incidentrelay
sudo systemctl enable incidentrelay-scheduler
sudo systemctl start incidentrelay
sudo systemctl start incidentrelay-scheduler
Проверьте статус:
sudo systemctl status incidentrelay
sudo systemctl status incidentrelay-scheduler
Откройте:
http://SERVER_IP:8080/login
10. Логи#
Логи веб-сервиса:
journalctl -u incidentrelay -f
Логи планировщика:
journalctl -u incidentrelay-scheduler -f
Файл лога приложения:
tail -f /var/log/incidentrelay/incidentrelay.log
Файлы сервисов systemd#
Веб-сервис#
[Unit]
Description=IncidentRelay Web service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/incidentrelay
Environment=INCIDENTRELAY_CONFIG_FILE=/etc/incidentrelay/incidentrelay.conf
Environment=INCIDENTRELAY_SERVICE=web
Environment=PYTHONUNBUFFERED=1
ExecStart=/var/www/incidentrelay/venv/bin/gunicorn \
--bind 0.0.0.0:8080 \
--workers 1 \
--threads 4 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
"app:create_app()"
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Сервис планировщика#
[Unit]
Description=IncidentRelay Scheduler service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/incidentrelay
Environment=INCIDENTRELAY_CONFIG_FILE=/etc/incidentrelay/incidentrelay.conf
Environment=INCIDENTRELAY_SERVICE=scheduler
Environment=PYTHONUNBUFFERED=1
ExecStart=/var/www/incidentrelay/venv/bin/python -m app.scheduler_worker
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
Важное замечание о планировщике#
Веб-процесс не должен запускать планировщик автоматически.
Правильная модель:
web service:
create_app()
no scheduler autostart
scheduler service:
create_app()
start_scheduler()
Если запуск планировщика сейчас происходит внутри create_app(), защитите его условием:
import os
if os.getenv("INCIDENTRELAY_SERVICE") == "scheduler":
start_scheduler()
Если app.scheduler_worker запускает планировщик явно, обычно лучше полностью убрать автоматический запуск планировщика из create_app().
Продакшен с обратным прокси#
Для продакшена обычно лучше привязать Gunicorn к localhost и публиковать IncidentRelay через Nginx или HAProxy с HTTPS.
Измените ExecStart веб-сервиса:
ExecStart=/var/www/incidentrelay/venv/bin/gunicorn \
--bind 127.0.0.1:8080 \
--workers 1 \
--threads 4 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
"app:create_app()"
Затем задайте:
[server]
public_base_url = https://incidentrelay.example.com
Вариант с PostgreSQL#
Для более крупных инсталляций используйте PostgreSQL.
Пример секции конфигурации:
[database]
type = postgresql
host = 127.0.0.1
port = 5432
name = incidentrelay
user = incidentrelay
password = change-me
Для PostgreSQL при необходимости увеличьте число веб-воркеров:
ExecStart=/var/www/incidentrelay/venv/bin/gunicorn \
--bind 127.0.0.1:8080 \
--workers 4 \
--threads 4 \
--timeout 120 \
--access-logfile - \
--error-logfile - \
"app:create_app()"
Для SQLite оставляйте --workers 1.
Обновление IncidentRelay#
cd /var/www/incidentrelay
sudo systemctl stop incidentrelay-scheduler
sudo systemctl stop incidentrelay
sudo git pull
sudo /var/www/incidentrelay/venv/bin/pip install -r requirements.txt
sudo -u www-data \
INCIDENTRELAY_CONFIG_FILE=/etc/incidentrelay/incidentrelay.conf \
/var/www/incidentrelay/venv/bin/python app/migrate.py migrate
sudo systemctl start incidentrelay
sudo systemctl start incidentrelay-scheduler
Устранение неполадок#
Файл конфигурации не найден#
Проверьте:
systemctl show incidentrelay --property=Environment
systemctl show incidentrelay-scheduler --property=Environment
Проверьте, что файл существует:
ls -l /etc/incidentrelay/incidentrelay.conf
Отказ в доступе к базе данных SQLite#
Проверьте права доступа:
sudo -u www-data test -w /var/lib/incidentrelay
sudo -u www-data test -r /etc/incidentrelay/incidentrelay.conf
Напоминания дублируются#
Проверьте, что планировщик не запущен внутри веб-воркеров и что активен только один сервис планировщика:
systemctl status incidentrelay-scheduler
ps aux | grep scheduler
Сервис не запускается после обновления кода#
Проверьте логи:
journalctl -u incidentrelay -n 100 --no-pager
journalctl -u incidentrelay-scheduler -n 100 --no-pager