Мониторинг VPS, панелей и VPN в Telegram.
Русский · English
StackSentry это Telegram-бот для VPS. Он следит за железом, службами, панелями (3X-UI, Marzban, Marzneshin, PasarGuard, Remnawave, S-UI, Hiddify, Outline) и VPN (WireGuard, OpenVPN, AmneziaWG, sing-box, Xray, Shadowsocks, Tailscale), присылает алерты и показывает подписки. Опасные действия (рестарт, обновление системы, перезагрузка) выполняются только по кнопке с подтверждением и только администратором.
Текущая версия: 1.1.3. Проект публичный:
документация, политика безопасности.
Проверку обновлений можно запустить кнопкой «Проверить обновления» в боте,
в разделе «Помощь» Mini App или через sudo stacksentry-menu update-check;
она идёт по ветке main.
Обновление работает из main без ручной настройки. Для дополнительной защиты
можно задать UPDATE_SHA256 в /etc/stacksentry.conf, тогда архив проверяется
по пину. GitHub Releases
проект не публикует.
Установка одной командой:
bash <(curl -Ls https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh)Альтернативы без curl | bash:
# скачать и проверить установщик отдельно
curl -fsSLo /tmp/stacksentry-install.sh \
https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh
sudo bash /tmp/stacksentry-install.sh
# GitHub CLI
gh api repos/Hijackery/stacksentry/contents/install.sh \
-H "Accept: application/vnd.github.raw" > /tmp/stacksentry-install.sh
sudo bash /tmp/stacksentry-install.sh
# приватный форк или корпоративный GitHub с токеном
GH_TOKEN=... bash -c 'curl -fsSL -H "Authorization: Bearer $GH_TOKEN" \
https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh | bash'Мастер скачает код, спросит токены, поставит зависимости, создаст отдельного пользователя, включит автозапуск и проверит, что всё работает.
- Зачем это нужно
- Как это выглядит
- Совместимость
- Быстрый старт
- Подключение к панели
- Как устроено
- Команды и экраны
- Меню настроек
stacksentry-menu - Настройки
- Безопасность
- Обновление и удаление
- Если что-то не работает
- Документация
- Версии и обновление
- Разработка
- Проект
Панели и VPN показывают состояние, но в них нужно заходить. Бот приносит самое важное в Telegram и не мешает, когда всё в порядке.
| Мониторинг | CPU, RAM, swap, диск, сеть, load; службы; панель и ядро; стек панелей/VPN; пользователи, подписки и трафик |
| Панели | API 3X-UI, Marzban, Marzneshin, PasarGuard, Remnawave, S-UI, Hiddify, Outline; остальные: детект службы/порта/процесса |
| Алерты | гистерезис без «дребезга», кулдаун, мьют «знаю, до утра»; под алертом сразу «Рестарт» и «Журнал» |
| Действия | рестарт службы и ядра панели, обновления пакетов, релиз-обновление ОС (APT), перезагрузка, безопасные команды |
| Обновления | проверка main; установка с подтверждением и 2FA, опциональный пин UPDATE_SHA256; без GitHub Releases |
| История | почасовые средние CPU/RAM/диска за 24 часа, 7 или 30 дней; p95 и пики |
| Установка | одна команда, адаптивный мастер по ОС/службам/панели, неинтерактивный режим, самопроверка |
| Универсальность | systemd, OpenRC, SysVinit; apt/dnf/yum/zypper/pacman/apk/xbps/emerge/eopkg/pkg; Python 3.10+ |
| Mini App | read-only панель в Telegram: обзор, службы, панель, трафик, подписки, история, терминал и встроенная «Помощь»; вход по Telegram (+ TOTP, если 2FA включена) |
| Терминал | stacksentry-menu: настройки, диагностика, рестарт, журнал, обновление; секреты маскируются |
| Безопасность | отдельный непривилегированный пользователь, узкий sudoers, подтверждение и аудит опасных действий |
Сводка начинается с вердикта: ночью достаточно одного взгляда:
🟢 Состояние сервера: всё в норме · CPU 12% · RAM 41% · Диск 63% · x-ui 🟢 · панель 🟢
CPU ▓▓░░░░░░░░ 12.0% 🟢
RAM ▓▓▓▓░░░░░░ 41.0% 🟢
Диск ▓▓▓▓▓▓░░░░ 63.0% 🟢
Алерт с причиной и действиями:
🔴 КРИТИЧНО · Сервис x-ui не работает · 03:12
Статус failed, SubState failed
[♻️ Рестарт x-ui] [📜 Журнал x-ui]
[📊 Текущее состояние] [🏠 В меню]
[😴 Знаю, до утра]
Результат действия с кодом возврата и контекстной кнопкой:
✅ x-ui перезапущен за 1.2 с
Сервис x-ui перезапущен
[📜 Журнал x-ui] [🏠 В меню]
| Что | Поддержка |
|---|---|
| Службы | systemd (Debian/Ubuntu, RHEL/Rocky/Alma, Fedora, openSUSE, Arch), OpenRC (Alpine, Gentoo), SysVinit |
| Пакеты | apt, dnf, yum, zypper, pacman, apk, xbps, emerge, eopkg, pkg: определяются автоматически |
| Python | 3.10 и новее; установщик подбирает интерпретатор сам |
| Панели | API: 3X-UI, Marzban, Marzneshin, PasarGuard, Remnawave, S-UI, Hiddify, Outline. Остальные VPN/прокси: детект и мониторинг службы/порта/процесса |
| Рестарт ядра | 3X-UI, Marzban, Marzneshin, PasarGuard, S-UI через API; Remnawave/Hiddify/Outline только через службу/контейнер |
| sudo | классический sudo и sudo-rs (Ubuntu 26.04+): правила генерируются без шаблонов и алиасов |
| Архитектуры | x86_64, ARM: всё, где есть Python и поддерживаемая инициализация |
Выбрать менеджер служб вручную можно через --init systemd|openrc|sysv.
Если systemd нет, бот работает так же: журнал читается из bot.log, а состояние
служб помечается как недоступное (без ложных «crit»).
- сервер с Linux (любой поддерживаемый дистрибутив) и, по желанию, панелью;
- токен Telegram-бота от @BotFather;
- ваш numeric ID (например, @userinfobot);
- доступ к панели: токен (3X-UI/Remnawave/S-UI/Hiddify), логин/пароль (Marzban/Marzneshin/PasarGuard) или секретный путь (Outline). Полная матрица в docs/COMPATIBILITY.md.
Установка одной командой:
bash <(curl -Ls https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh)Альтернативы без curl | bash:
# скачать и проверить установщик отдельно
curl -fsSLo /tmp/stacksentry-install.sh \
https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh
sudo bash /tmp/stacksentry-install.sh
# GitHub CLI
gh api repos/Hijackery/stacksentry/contents/install.sh \
-H "Accept: application/vnd.github.raw" > /tmp/stacksentry-install.sh
sudo bash /tmp/stacksentry-install.sh
# приватный форк или корпоративный GitHub с токеном
GH_TOKEN=... bash -c 'curl -fsSL -H "Authorization: Bearer $GH_TOKEN" \
https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh | bash'Или через пайп (так можно с sudo):
curl -fsSL https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh | sudo bashНе добавляйте
sudoк формеbash <(curl …): sudo закрывает файловый дескриптор process substitution, и bash отвечаетbash: /dev/fd/63: No such file or directory. Либо запускайтеbash <(…)уже от root (без sudo), либо используйте пайпcurl … | sudo bash.
Мастер задаёт вопросы четвёртым шагом, до установки зависимостей, поэтому
отвечать нужно в начале. Вопросы читаются с терминала (/dev/tty), так что
диалог работает и при установке через пайп.
Что спросит мастер:
- токен бота и ID администраторов (токен сразу проверяется через Telegram);
- 2FA (TOTP) опционально: при включении код нужен для входа в Mini App и опасных действий, при отказе TOTP не используется;
- адрес панели,
webBasePathи API-токен (адрес проверяется); - список служб под наблюдением;
- необязательный чат для алертов;
- для Mini App HTTPS настраивается автоматически (
sslip.io+ Caddy); для терминала можно указать свой адрес или оставить SSH-туннель.
Mini App, терминал, root-сессия и 2FA ставятся этой же командой. Отдельный
install.sh --terminal ... после установки не нужен.
sudo stacksentry-menu # меню: состояние, настройки, рестарт, журнал, обновление
systemctl status stacksentry-botОткройте бота в Telegram, нажмите /start → /status. Если что-то не так,
бот сам скажет, что именно. /version покажет версию, ОС, пакетный менеджер и
выбранную панель; /stack показывает, что найдено на сервере. Mini App и терминал уже
установлены: если при установке вы указали публичные HTTPS-адреса, рядом со
скрепкой появится кнопка «Панель», а в главном меню появятся «📱 Открыть Mini App» и
вкладка «Терминал». Останется только один раз привязать домен:
@BotFather → /setdomain (без https://). Это требование Telegram, API для
этого шага нет.
Для автоматизации и повторной установки: --yes не задаёт вопросы, а берёт
значения из переменных окружения или уже готового .env. Если .env полный,
он сохраняется как есть; недостающие значения можно передать заранее. Полный
набор в unattended-режиме включается явно:
--webapp --webapp-origin https://... --terminal --root-terminal --terminal-origin https://....
sudo env \
TELEGRAM_BOT_TOKEN='123456789:AA...' \
TELEGRAM_ADMIN_IDS='11111111' \
PANEL_TYPE='3x-ui' \
PANEL_URL='https://panel.example.com:2053' \
PANEL_API_TOKEN='...' \
bash install.sh --yesДля Marzban/Marzneshin/PasarGuard вместо токена передайте
PANEL_USERNAME и PANEL_PASSWORD; для Outline только PANEL_URL с
секретным путём. PANEL_TYPE можно не указывать, мастер возьмёт найденный тип
или 3x-ui. Полный список типов и доступов приведён в
docs/COMPATIBILITY.md.
Полезные опции: --repo owner/name, --ref ветка, --prefix DIR, --user NAME,
--no-start, --force-config, --print-source, --sha256 HASH, --init TYPE,
--webapp --webapp-origin https://..., --terminal, --root-terminal, --2fa,
--menu. Полный список: bash install.sh --help.
Повторный запуск установщика обновляет код и сохраняет .env/состояние; для
проверки обновлений из бота есть /updatecheck, кнопка в «Помощи» и раздел «Помощь» в Mini App.
Самообновление работает из main сразу. Если в /etc/stacksentry.conf задан
UPDATE_SHA256, архив дополнительно проверяется по этому пину.
| Панель | Авторизация | Что даёт |
|---|---|---|
| 3X-UI 2.x/3.x | Bearer API token | статус, inbound'ы, подписки, трафик, рестарт xray |
| Marzban | PANEL_USERNAME + PANEL_PASSWORD (OAuth2) |
статус, пользователи, трафик, рестарт xray |
| Remnawave | Bearer API token | статус, пользователи, трафик |
| Marzneshin | логин/пароль (OAuth2 /api/admins/token) |
статус, пользователи, трафик, рестарт backend через переприменение конфига |
| PasarGuard | логин/пароль (OAuth2 /api/admin/token) |
статус, пользователи, трафик, рестарт core |
| S-UI | PANEL_API_TOKEN в заголовке Token |
статус, клиенты, трафик, рестарт sing-box |
| Hiddify | PANEL_API_TOKEN (admin UUID) в Hiddify-API-Key |
статус, пользователи, трафик |
| Outline | секретный путь SB_API_PREFIX в PANEL_URL |
статус, access keys, трафик |
Переключение: sudo stacksentry-menu set PANEL_TYPE s-ui (и адрес/токен),
затем рестарт. Для 3X-UI/Remnawave/S-UI/Hiddify используется
PANEL_API_TOKEN, для Marzban логин и пароль.
Особенности адресов:
- S-UI:
PANEL_URLуказывает на корень панели вместе с её web path, напримерhttp://host:2095/app; бот сам добавит/apiv2/. - Hiddify:
PANEL_URLуказывает на корень вместе с admin proxy path, напримерhttps://example.com/AbCdEf; бот сам добавит/api/v2/. - Outline:
PANEL_URLсодержит полный адрес с секретнымSB_API_PREFIX, напримерhttps://host:port/SecretPath; отдельный токен не нужен. - 3X-UI:
PANEL_BASE_PATHэто webBasePath панели;/panel/apiдобавит бот.
Установщик, меню и бот подстраиваются под сервер. Мастер определяет ОС,
пакетный менеджер, службы и тип панели, затем спрашивает только нужное:
токен для 3X-UI/Remnawave/S-UI/Hiddify, логин/пароль для
Marzban/Marzneshin/PasarGuard или секретный путь для Outline, с проверкой API.
stacksentry-menu detect показывает найденное, в меню есть пункт «Тип панели»,
а рестарт ядра сам выбирает endpoint. Главное меню бота не показывает
«Трафик»/«Подписки», пока API не настроен, и показывает команды обновления для
фактического пакетного менеджера (APT-специфичные только на APT).
Панели: 3X-UI, S-UI, Marzban, Marzneshin, PasarGuard, Hiddify, Remnawave, Outline. Прокси/ядра: Xray, V2Ray, sing-box, Hysteria, TUIC, Trojan, NaiveProxy, Mieru, ShadowTLS, Brook, mtg, Shadowsocks, Squid, Dante, 3proxy, GOST. VPN/mesh: WireGuard, AmneziaWG, OpenVPN, IPsec/StrongSwan, SoftEther, Tailscale, ZeroTier, NetBird, Headscale, Nebula.
Определение идёт по юнитам (systemd/OpenRC/SysV), путям конфигов и именам
процессов (ps). API-интеграция есть у 3X-UI (inbound'ы, подписки, рестарт
xray), Marzban, Marzneshin, PasarGuard, Remnawave, S-UI, Hiddify и Outline
(пользователи/клиенты, трафик); остальные показываются как службы/порты и
помечаются «API не поддерживается». Docker-контейнеры видны как служба docker, но не
опрашиваются через Docker API (это дало бы боту root-эквивалентные права).
Установщик сам находит панели/VPN по службам, путям и портам. Если поддерживаемая
панель не найдена, можно оставить PANEL_URL и PANEL_API_TOKEN пустыми, бот будет
наблюдать службы, VPN-стек, железо и алерты, а разделы панели/подписок
скажут, что API не настроен. Позже включить API: sudo stacksentry-menu →
адрес панели и токен (или переустановка с --panel).
Токен создаётся в самой панели, а не в Telegram и не в боте.
3X-UI v3.x
- «Настройки панели → Учётная запись → API-токен» → создать.
- Scope:
node-sync(илиadmin). - Скопируйте значение сразу: панель показывает его один раз, позже остаётся только отметка «задано».
То же по API: POST /panel/api/setting/apiTokens/create с name, scope,
expiresAt (нужен уже существующий admin-токен).
3X-UI 2.x
«Настройки → API Tokens» либо из терминала:
sudo x-ui setting -getApiToken true -tokenName monitor-bot -tokenScope node-syncВ v3 эта команда новых токенов не создаёт, она лишь ротирует служебный
cli-fallback.
Почему не monitor: этот scope даёт только статус панели. Для inbound'ов и
подписок нужен node-sync, для действий в панели: admin.
Поле webBasePath это отдельная настройка «URL панели» в 3X-UI. Обычно
она равна /, и тогда поле в мастере оставляют пустым.
Путь /panel из адресной строки вводить не нужно: интерфейс 3X-UI всегда
живёт на .../panel, а API на .../panel/api. Если вписать /panel в
webBasePath, получится лишний сегмент .../panel/panel/api.
Установщик проверяет путь до запроса токена (верный путь без токена отвечает
401, неверный 404) и молча исправляет ошибку. Полный адрес, вставленный в
это поле, он тоже распознаёт.
curl -s -o /dev/null -w '%{http_code}\n' \
-H 'X-Requested-With: XMLHttpRequest' \
https://panel.example.com:2053/panel/api/server/status401 означает, что путь верный и нужен токен. С токеном:
curl -fsS -H "Authorization: Bearer <токен>" \
https://panel.example.com:2053/panel/api/server/statusОтвет должен содержать "success":true.
- Если в панели задан «Домен панели» (
webDomain), 3X-UI сверяет заголовокHostи отвечает403на всё остальное. Тогда вPANEL_URLдолжно быть ровно это имя, а не IP. - Имя должно резолвиться с самого сервера. Если домен указывает на публичный
IP и обратного NAT нет, используйте
http://127.0.0.1:2053с тем жеPANEL_BASE_PATH. IPv6 пишите в скобках:http://[::1]:2053. httpдопустим, когда панель слушает localhost: трафик не выходит за пределы машины. Если панель доступна по публичному адресу, используйте толькоhttps://, иначе токен и содержимое API идут открытым текстом. Для самоподписанного сертификата не отключайте проверку, а укажитеPANEL_CA_BUNDLE.- Бот не следует редиректам: если
httpперенаправляет наhttps, просто поменяйте схему.
Telegram / Mini App ⇄ бот (непривилегированный пользователь stacksentry)
├─ psutil / systemctl / journalctl: метрики и службы
├─ inventory: ОС, пакеты, панели, VPN
├─ API панели (8 типов): пользователи, трафик, рестарт ядра
├─ updates: проверка main; установка по pinned SHA
└─ sudo stacksentry-ctl (узкий sudoers): рестарт, обновления, reboot, журнал
- Код:
/opt/stacksentry, принадлежитroot; бот не может переписать сам себя. - Секреты:
.envс правами640 root:stacksentry. - Состояние: SQLite в
/var/lib/stacksentry(история, аудит, мьюты). - Привилегии: только через
sudo stacksentry-ctl; список разрешённых подкоманд перечислен точно, без шаблонов. - Обновления: выполняются отдельным systemd-юнитом
(
stacksentry-apt-*.service), потому что бот живёт сProtectSystem=strict;stacksentry-ctlсам определяетapt/dnf/yum/zypper/pacman/apk/xbps/emerge/eopkg/pkg. - Self-update: установщик запускается отдельным юнитом из
main, сохраняет.envи состояние и перезапускает бота; пинUPDATE_SHA256опционален. - Mini App: отдельный read-only сервис на
127.0.0.1:8787под собственным пользователемstacksentry-webapp; наружу только HTTPS-прокси, вход по Telegram initData.
| Команда | Что показывает |
|---|---|
/status |
вердикт одной строкой, замечания, метрики, службы и панель |
/traffic |
трафик: inbound'ы/клиенты или пользователи панели |
/services |
состояние служб; рестарт и журнал рядом |
/panel |
доступность панели и API, версия и обновления |
/subs |
подписки: сроки, трафик, исчерпанные и отключённые |
/history |
почасовые средние CPU/RAM/диска за сутки |
/logs |
журнал выбранного сервиса, фильтр «только ошибки» |
/audit |
журнал действий бота, фильтры «отказы / действия» |
/stack |
что найдено на сервере: панели, VPN, прокси, службы |
/maint |
обслуживание: обновления пакетов, перезагрузка, команда из allowlist |
/run <команда> |
выполнить диагностическую команду из белого списка |
/version |
версия StackSentry, Python, ОС, пакетный менеджер и панель |
/updatecheck |
проверить обновления StackSentry в main |
/help |
помощь простыми словами: что нажать и что значат цифры |
Кнопки дублируют команды; на каждом экране есть «🏠 В меню», так что в тупике оказаться нельзя. Гостям кнопки не показываются. При переходе между меню предыдущий экран заменяется, поэтому вереница сообщений не копится (это не касается «Подробнее» и «Свернуть»: они разворачивают тот же экран).
Команду на сервер можно прислать в любом разделе. Отправьте её
сообщением (или /run <команда>). Бот попросит подтверждение и вернёт вывод.
Разрешены только безопасные диагностические команды из COMMAND_ALLOWLIST;
список покажет /run без аргументов. Произвольный shell недоступен.
Обновления в /maint разделены и отчитываются в чат. Кнопка обновления
индексов вызывает команду фактического пакетного менеджера (apt update,
dnf makecache, pacman -Sy и т. п.); кнопка обновления системы запускает его штатный
upgrade/full-upgrade. phased и «запустить релиз» (do-release-upgrade)
доступны только на APT/Ubuntu и на других системах скрыты. Все фоновые задачи бот ведёт сам:
когда юнит завершится, в чат придёт код возврата и хвост журнала, вводить
journalctl не нужно. Одно действие даёт одно сообщение: «в очереди» → «запущено» →
отчёт, без вереницы. Вручную журнал смотреть так: sudo stacksentry-menu apt-logs.
/run <команда> (или текст в чате) запускает только команды из
COMMAND_ALLOWLIST. Все они только читают и запускаются как argv без shell:
ни pipes, ни перенаправлений, ни записи. Если команды нет в системе, бот
скажет, что она не установлена.
| Команда | Что показывает |
|---|---|
os_logs / os_errors |
журнал ОС: предупреждения / только ошибки (100 строк) |
kernel_logs / dmesg |
сообщения ядра |
xui_logs |
журнал службы x-ui |
xui_service / x-ui status |
статус панели |
failed_units |
упавшие systemd-юниты |
sockets / net_summary |
слушающие порты / сводка сокетов |
addresses / routes |
IP-адреса / маршруты |
top_cpu |
процессы по CPU и памяти |
uname / cpu_info / block_devices |
система, CPU, диски |
log_size / inodes / df -h / free -h / uptime |
место и ресурсы |
upgradable / upgrade_sim |
доступные обновления / симуляция apt |
vmstat / time_status / logged_in / boot_time |
нагрузка, время, сеансы |
journalctl --disk-usage / systemctl list-timers --all |
журнал и таймеры |
Примеры: /run os_logs, /run failed_units, /run sockets. Команда /run
без аргументов показывает этот список прямо в боте, с группами и описаниями.
У логов (os_logs, xui_logs, kernel_logs, dmesg) под выводом есть кнопки
«📜 Ещё 200 строк», «❌ Только ошибки» и «🔎 Поиск» по тексту, как у журналов служб.
Команды и кнопки работают только в личном чате администратора. В группе бот
отвечает отказом: адреса, подписки и трафик не должны утекать в общий чат.
ALERT_CHAT_ID разрешает только исходящие алерты в группу, управление там
недоступно.
/status начинается с вердикта, детали спрятаны за «📋 Подробнее». Метрики
выровнены моноширинным блоком, время подписано «время сервера». Под алертом
сразу есть ♻️ Рестарт, 📜 Журнал и 😴 Знаю, до утра, мьют на 8 часов,
хранится в SQLite и переживает перезапуск.
После установки доступна консольная панель:
sudo stacksentry-menu # интерактивное меню
sudo stacksentry-menu show # настройки (секреты замаскированы)
sudo stacksentry-menu keys # какие ключи разрешено менять
stacksentry-menu check PANEL_TIMEOUT 20 # проверка без изменений (без root)
sudo stacksentry-menu set PANEL_TIMEOUT 20
sudo stacksentry-menu restart # применить
sudo stacksentry-menu detect # что найдено: ОС, панели, VPN, службы
sudo stacksentry-menu restart-xray # перезапустить ядро (где поддерживается)
sudo stacksentry-menu apt-logs 100 # журнал фоновых apt-обновлений
sudo stacksentry-menu logs 100Интерактивное меню рисуется в рамке и сгруппировано по разделам; сверху показано живое состояние службы:
╔════════════════════════════════════════════════════════╗
│ StackSentry: панель управления │
│ Служба stacksentry-bot: ● работает │
│ Диагностика │
│ 1. Состояние службы и последние ошибки │
│ 2. Показать настройки (секреты замаскированы) │
│ 3. Журнал бота (последние 50 строк) │
│ 4. Что найдено на сервере (ОС, панели, VPN) │
│────────────────────────────────────────────────────────│
│ Telegram │
│ 5. Токен бота (@BotFather) │
│ 6. ID администраторов │
│ 7. Чат для алертов │
│ … │
│ 25. Проверить обновления StackSentry │
│ 26. Удалить бота │
│ 0. Выход │
╚════════════════════════════════════════════════════════╝
| Пункт | Что делает | Что ввести | Пример |
|---|---|---|---|
| 1 | состояние службы и последние ошибки | - | - |
| 2 | показывает настройки, секреты замаскированы | - | - |
| 3 | журнал бота, 50 строк | - | - |
| 4 | автоопределение: ОС, пакетный менеджер, панели, VPN, службы | - | - |
| 5 | токен Telegram-бота | значение от @BotFather | 123456789:AAH... |
| 6 | ID администраторов | числа через запятую | 11111111,22222222 |
| 7 | чат для алертов | ID чата; у групп он отрицательный; пусто: в личку | -1001234567890 |
| 8 | тип панели (PANEL_TYPE) |
один из поддерживаемых типов | s-ui |
| 9 | адрес панели (PANEL_URL) |
схема, хост, порт и (для S-UI/Hiddify) путь панели | https://panel.example.com:5580 |
| 10 | путь панели (PANEL_BASE_PATH) |
webBasePath 3X-UI; у S-UI/Hiddify путь обычно уже в адресе |
пусто или mypanel |
| 11 | API-токен панели | токен 3X-UI/Remnawave/S-UI или admin UUID Hiddify | AbCdEf... |
| 12 | логин и пароль Marzban (подменю) | PANEL_USERNAME, PANEL_PASSWORD |
admin, *** |
| 13 | TLS и CA (подменю) | PANEL_VERIFY_TLS: true/false; PANEL_CA_BUNDLE: путь к PEM |
true, /etc/ssl/panel-ca.pem |
| 14 | порог CPU (подменю) | CPU_WARN и CPU_CRIT, % |
80, 95 |
| 15 | порог памяти (подменю) | MEM_WARN и MEM_CRIT, % |
85, 95 |
| 16 | порог диска (подменю) | DISK_WARN и DISK_CRIT, % |
85, 93 |
| 17 | гистерезис и кулдаун (подменю) | ALERT_HYSTERESIS в %, ALERT_COOLDOWN в сек |
5, 1800 |
| 18 | за сколько дней предупреждать о подписке | целое число дней | 3 |
| 19 | службы под наблюдением | имена служб через запятую | x-ui,fail2ban |
| 20 | уровень логирования | DEBUG / INFO / WARNING / ERROR |
INFO |
| 21 | любой ключ из белого списка | сначала имя ключа, затем значение | DISK_PATH → / |
| 22 | перезапуск бота с проверкой | - | - |
| 23 | перезапуск ядра панели | подтверждение y |
y |
| 24 | обновление StackSentry (опционально по UPDATE_SHA256) |
- | - |
| 25 | проверка обновлений StackSentry | - | - |
| 26 | показать TOTP-секрет / настроить 2FA | QR и секрет | - |
| 27 | статус Mini App и адрес для /setdomain |
- | - |
| 28 | удаление | yes для подтверждения |
yes |
Пустое значение очищает настройку: sudo stacksentry-menu set PANEL_BASE_PATH "".
Для пунктов 5–20 можно не ходить в меню, а сразу писать:
sudo stacksentry-menu set KEY VALUE (то же, что пункт 21, но одной командой).
# примеры значений
sudo stacksentry-menu set PANEL_TYPE s-ui
sudo stacksentry-menu set PANEL_URL https://panel.example.com:2095/app
sudo stacksentry-menu set PANEL_BASE_PATH "" # «URL панели» = /
sudo stacksentry-menu set TELEGRAM_ADMIN_IDS 11111111,22222222
sudo stacksentry-menu set ALERT_CHAT_ID -1001234567890
sudo stacksentry-menu set SERVICES x-ui,fail2ban
sudo stacksentry-menu set CPU_WARN 80
sudo stacksentry-menu set LOG_LEVEL INFO
# проверить значение, ничего не меняя
stacksentry-menu check CPU_WARN 80
# проверить обновления StackSentry и посмотреть журнал пакетных обновлений
sudo stacksentry-menu update-check
sudo stacksentry-menu apt-logs 100Что важно знать:
- ввод проверяется: неверный номер показывает диапазон,
qдля выхода; - менять можно только ключи из белого списка (
stacksentry-menu keys); значения проверяются до записи; .envперезаписывается атомарно с правами640 root:<сервисный пользователь>;- секреты не печатаются целиком;
- пути можно переопределить:
sudo PREFIX=/opt/бот ENV_FILE=/opt/бот/.env stacksentry-menu; - автоочистку экрана можно выключить:
STACKSENTRY_NO_CLEAR=1 sudo stacksentry-menu.
Все параметры находятся в /opt/stacksentry/.env; пример с комментариями:
.env.example. Переменные окружения процесса имеют приоритет
над файлом.
| Ключ | Значение |
|---|---|
TELEGRAM_BOT_TOKEN |
токен бота от @BotFather |
TELEGRAM_ADMIN_IDS |
ID администраторов через запятую |
ALERT_CHAT_ID |
чат для алертов (пусто: админам в личку) |
TELEGRAM_API_URL |
свой Bot API или прокси (по умолчанию официальный) |
PANEL_URL |
адрес панели, например https://panel.example.com:2053 |
PANEL_BASE_PATH |
«URL панели» (webBasePath), если задан |
PANEL_API_TOKEN |
токен панели (3X-UI node-sync, Remnawave, S-UI Token, Hiddify admin UUID) |
PANEL_TYPE |
3x-ui, marzban, marzneshin, pasarguard, remnawave, s-ui, hiddify или outline |
PANEL_USERNAME |
логин Marzban (только для PANEL_TYPE=marzban) |
PANEL_PASSWORD |
пароль Marzban (только для PANEL_TYPE=marzban) |
PANEL_VERIFY_TLS |
проверять TLS-сертификат панели |
PANEL_CA_BUNDLE |
свой CA-файл (PEM); перекрывает PANEL_VERIFY_TLS |
PANEL_ALLOW_INSECURE |
разрешить http:///без TLS для панели не на localhost (не рекомендуется) |
PANEL_TIMEOUT |
таймаут запросов к панели, сек |
SERVICES |
службы под наблюдением, через запятую (x-ui,fail2ban) |
DISK_PATH |
что проверять по месту |
CPU_WARN |
порог предупреждения по CPU, % |
CPU_CRIT |
порог критического CPU, % |
MEM_WARN |
порог предупреждения по памяти, % |
MEM_CRIT |
порог критической памяти, % |
DISK_WARN |
порог предупреждения по диску, % |
DISK_CRIT |
порог критического диска, % |
INODE_WARN |
порог предупреждения по inode, % |
INODE_CRIT |
порог критического inode, % |
CHECK_FAILED_UNITS |
1: проверять упавшие systemd-юниты |
CHECK_FAILED_UNITS_IGNORE |
юниты-шум через запятую; none показывать все |
CHECK_TLS |
1: проверять срок TLS-сертификата панели |
CHECK_BACKUP_PATH |
файл или каталог бэкапа для проверки свежести |
CHECK_BACKUP_MAX_AGE_H |
максимальный возраст бэкапа, часов |
CHECK_HTTP_URLS |
внешние HTTP-адреса через запятую |
CHECK_DNS_HOSTS |
DNS-имена через запятую |
CHECK_SMART |
1: проверять SMART через smartctl (опционально) |
ALERT_HYSTERESIS |
на сколько % метрика должна отойти назад, чтобы снять алерт |
ALERT_CONFIRM_CHECKS |
сколько проверок подряд подтверждают срабатывание (2 отсекает всплески) |
ALERT_RECOVERY_CHECKS |
сколько проверок подряд подтверждают восстановление |
ALERT_COOLDOWN |
как часто повторять активный алерт, сек |
ALERT_CRITICAL_CHAT_ID |
отдельный чат для critical |
ALERT_CRITICAL_TOPIC_ID |
тема в чате critical (для групп с topics) |
ALERT_WARNING_CHAT_ID |
отдельный чат для warning |
ALERT_WARNING_TOPIC_ID |
тема в чате warning |
ALERT_QUIET_START |
начало тихих часов, HH:MM |
ALERT_QUIET_END |
конец тихих часов, HH:MM |
EXPIRING_SOON_DAYS |
за сколько дней подписка считается истекающей |
CHECK_INTERVAL |
период фоновой проверки, сек (минимум 15) |
UPDATE_NOTIFY |
1: уведомлять админов о новом commit StackSentry в main |
UPDATE_CHECK_INTERVAL |
период фоновой проверки обновлений, сек (минимум 3600) |
ACTION_COOLDOWN |
пауза между одинаковыми действиями, сек |
CONFIRM_TTL |
сколько живёт кнопка подтверждения, сек |
TOTP_SECRET |
секрет TOTP (base32) для 2FA; пусто: 2FA выключена |
TOTP_REQUIRED |
1: требовать код для входа в Mini App и опасных действий бота |
ELEVATION_TTL |
сколько действует разблокировка после кода, сек |
TOTP_MAX_ATTEMPTS |
сколько попыток ввода кода до блокировки |
TOTP_LOCKOUT |
пауза после перебора кодов, сек |
WEBAPP_ENABLED |
1: включить read-only Mini App |
WEBAPP_HOST |
адрес прослушивания (по умолчанию 127.0.0.1) |
WEBAPP_PORT |
порт Mini App (по умолчанию 8787) |
WEBAPP_PUBLIC_ORIGIN |
публичный HTTPS-адрес для кнопки в Telegram |
WEBAPP_TERMINAL_ORIGIN |
публичный HTTPS-адрес терминала для вкладки внутри Mini App |
WEBAPP_SECRET |
секрет подписи cookie Mini App (≥ 32 символов) |
WEBAPP_SESSION_TTL |
срок жизни сессии Mini App, сек |
WEBAPP_METRICS_TOKEN |
Bearer-токен для /metrics (пусто: без авторизации) |
COMMAND_TIMEOUT |
таймаут разрешённых команд, сек |
COMMAND_ALLOWLIST |
безопасные команды диагностики (алиасы, см. раздел выше) |
STATE_PATH |
база SQLite |
LOG_PATH |
файл лога |
LOG_LEVEL |
DEBUG / INFO / WARNING / ERROR |
LOG_JSON |
1: писать логи одной JSON-строкой для journald/агрегатора |
SUDO_WRAPPER |
путь к stacksentry-ctl |
ALERT_CHAT_ID можно оставить пустым, тогда алерты приходят в личку всем ID из
TELEGRAM_ADMIN_IDS. Для общего чата добавьте туда бота, отправьте сообщение и
узнайте ID (@userinfobot, @getidsbot); у групп он отрицательный, например
-1001234567890.
Помните: в алертах есть адреса, подписки и трафик, поэтому в группе их увидят все участники. Команды и кнопки при этом всё равно работают только в личке.
Алерты сначала попадают в SQLite-outbox. Если Telegram недоступен, бот повторит отправку после рестарта, а не потеряет событие. Одинаковые события дедуплицируются.
Переход в аварию и восстановление подтверждаются несколькими проверками подряд
(ALERT_CONFIRM_CHECKS, ALERT_RECOVERY_CHECKS): одиночный всплеск CPU,
таймаут панели или короткий рестарт службы не превращается в ложную тревогу.
Для разных severity можно задать разные чаты и темы. В тихие часы warning
накапливаются и уходят одним дайджестом после ALERT_QUIET_END, а critical
доставляется сразу.
Кроме CPU/RAM/диска бот проверяет inode, упавшие systemd-юниты, срок
TLS-сертификата панели, свежесть бэкапа, внешние HTTP-адреса и DNS. Всё
включается в .env: CHECK_FAILED_UNITS, CHECK_TLS, CHECK_BACKUP_PATH,
CHECK_HTTP_URLS, CHECK_DNS_HOSTS. SMART выключен по умолчанию и требует
smartmontools (CHECK_SMART=1). Прогноз заполнения диска строится по истории
за неделю и появляется в сводке, когда до 100% остаётся меньше недели.
/healthzвозвращаетokи версию,/metricsотдаёт Prometheus-метрики (stacksentry_up, версия, число сэмплов и алертов в outbox).WEBAPP_METRICS_TOKENзакрывает/metricsBearer-токеном.LOG_JSON=1включает JSON-логи, удобные для journald и агрегаторов.
Дашборд в Telegram: обзор, службы, панель, трафик, подписки, история, обновления, терминал (если включён) и вкладка «Помощь» с краткой инструкцией по всем разделам, 2FA и терминалу.
Карточки и строки списков кликабельны: служба открывает состояние и журнал, метрика строит график за 24 часа/7/30 дней с p95 и пиками, проверка показывает причину и что делать, подписка раскрывает клиента и трафик. В шапке есть единый поиск по разделам, службам и подпискам. Закладки служб и настройка блоков дашборда хранятся в браузере.
Обновление можно запросить из вкладки «Обновления»: оно не выполняется напрямую,
а создаёт запрос в общей очереди. Бот присылает подтверждение в Telegram, при 2FA
требуется свежий код, после чего webapp показывает этапы и прогресс. Обновление
переживает перезапуск webapp: запрос и статус хранятся в STATE_DIR/update.
# всё автоматически: публичный IP -> <ip>.sslip.io -> Caddy -> Let's Encrypt
sudo bash install.sh --webapp --no-terminal
# свой домен и готовый TLS-прокси
sudo bash install.sh --webapp --webapp-origin https://sentry.example.comПри обычной установке домен не нужен: установщик берёт публичный IPv4,
создаёт бесплатный хост вида 203-0-113-5.sslip.io, ставит Caddy и выпускает
сертификат Let's Encrypt. Нужны свободные порты 80 и 443 (если 443 занят,
например Xray, используется 8443) и открытый публичный IP. Отключить
автонастройку: --no-webapp-auto.
В интерактивной установке мастер покажет публичный IP, будущий адрес и предупреждения, а затем предложит выбор:
- Автоматически:
sslip.io+ Caddy (рекомендуется). - Свой домен: ввести готовый HTTPS-адрес с валидным сертификатом.
- Только локально: без публичного адреса, доступ через SSH-туннель.
Если автоматический вариант не сработал, установщик предложит повторить, указать свой домен или оставить Mini App локальным.
Если установлен терминал, установщик спросит, открыть ли его внутри Mini App.
При автоматическом HTTPS создаётся отдельный адрес term.<host> и вкладка
«Терминал» появляется сама, вручную настраивать Caddy не нужно. Для своего
домена можно указать готовый HTTPS-адрес терминала. Вход в терминал всегда
защищён Telegram и TOTP. Если публичный терминал не нужен, ответьте n,
доступ останется только через SSH-туннель.
После установки остаётся один ручной шаг: привязать домен к боту через
@BotFather → /setdomain → например, 203-0-113-5.sslip.io (без https://
и без порта). Затем перезапустите бота: sudo systemctl restart stacksentry-bot.
Если Caddy недоступен в репозитории или порты заняты, установщик покажет
причину и предложит другой вариант.
- вход по подписи Telegram (
initData), без паролей; только администраторы. Если 2FA включена, дополнительно нужен TOTP-код на новую сессию; если выключена, Mini App не спрашивает код; - cookie
HttpOnly, срок 1 час (не более 24 ч); при публичном HTTPS используетсяSecure; SameSite=None(Telegram Web), локальноSameSite=Lax; подпись проверяетiat/exp, CSP без сторонних скриптов; - сервис
stacksentry-webappслушает127.0.0.1:8787, наружу только Caddy/Nginx с TLS; без публичного адреса доступен черезssh -L 8787:127.0.0.1:8787 root@сервер→http://127.0.0.1:8787; - кнопки появляются только при
WEBAPP_ENABLED=1и заданномWEBAPP_PUBLIC_ORIGIN; установщик выставляет оба значения сам. Без публичного адреса Mini App работает только через SSH-туннель, а кнопок в Telegram нет; - при этих условиях бот добавляет кнопку «Панель» в меню чата (Mini App) и
inline-кнопку «📱 Открыть Mini App» в главном меню администратора. «Панель» это
меню рядом со скрепкой; inline-кнопка находится в самом меню бота и видна
только ID из
TELEGRAM_ADMIN_IDS; - если API панели не настроен, дашборд показывает службы/VPN/железо и пишет, что inbound'ы/подписки недоступны.
Полноценный shell в браузере это отдельный сервис, не часть бота. Обычная интерактивная установка уже ставит его вместе с root-сессией и вкладкой в Mini App; отдельная команда нужна только для повторной настройки или автоматизации:
sudo bash install.sh --terminal # только терминал, без root
sudo bash install.sh --root-terminal # + root-сессия (sudo -i)
sudo bash install.sh --terminal-auto # автоматически открыть в Mini App
sudo bash install.sh --terminal --terminal-origin https://term.example.comЧто происходит:
- создаётся отдельный пользователь
stacksentry-termи службаstacksentry-terminal; - сервис слушает
127.0.0.1:8788, наружу не выставлен; - вход: Telegram
initDataи обязательный код TOTP на каждую сессию. Даже при компрометации Telegram-аккаунта администратора без TOTP войти нельзя; - у терминала отдельный TOTP-секрет от входа в Mini App. При первом
открытии вкладки «Терминал» в Mini App показываются QR и секрет; после
успешного входа QR скрывается и остаётся обычный запрос 6-значного кода.
Посмотреть секрет и QR вручную:
sudo stacksentry-menu totp; для доступа вне Telegram дополнительно нужен access token из/etc/stacksentry/terminal-secrets.env,600 root; - установщик автоматически создаёт SSH-ключ Ed25519
(
/var/lib/stacksentry-term/terminal-ssh/id_ed25519), добавляет публичную часть вauthorized_keysпользователяstacksentry-termи использует ключ для локального SSH-подключения к127.0.0.1. Приватный ключ не покидает сервер; если sshd/ключ недоступны, терминал автоматически работает через локальный PTY; - секреты терминала лежат в
/etc/stacksentry/terminal-secrets.envс правами600 root; systemd передаёт их процессу, сам пользователь файл не читает; - обычный shell работает под отдельным пользователем
stacksentry-shellбез sudo; root-сессия доступна только через точное правилоstacksentry-term ALL=(root) NOPASSWD: /bin/bash -l. В обычной установке она включена; отключить:--no-root-terminal; - секреты терминала (TOTP, тикеты, access token, токен бота) не передаются в PTY: shell получает только PATH/TERM/LANG/HOME/USER;
- вкладка «Терминал» внутри Mini App появляется, когда задан
WEBAPP_TERMINAL_ORIGIN. При авто-HTTPS установщик сам публикует терминал наterm.<host>и прописывает адрес; для своего домена используйте--terminal-originили ответьте на вопрос мастера. Терминал открывается в iframe, initData передаётся через hash, но TOTP всё равно запрашивается отдельно.
Нужен только бот без дополнительных сервисов? Отключите их при установке:
--no-webapp, --no-terminal, --no-root-terminal, --no-2fa.
Доступ по умолчанию только с сервера или через SSH-туннель:
ssh -L 8788:127.0.0.1:8788 root@сервер
# затем откройте http://127.0.0.1:8788Для доступа из Telegram задайте --terminal-origin https://... и поставьте
Caddy/Nginx с TLS перед 127.0.0.1:8788.
Root-терминал это полноценный root-shell. TOTP защищает вход, но при компрометации веб-слоя/сессии/зависимостей защита падает. Держите его за VPN/SSH-туннелем, не публикуйте в интернет без второго периметра.
Если 2FA включена, Mini App требует код TOTP при входе. В боте просмотр состояния, журналов и подписок остаётся без кода; код нужен там, где можно сломать сервер (step-up). Иначе каждые 15 минут пришлось бы заново вводить код даже для чтения статуса.
| Уровень | Что | 2FA |
|---|---|---|
| 🟢 просмотр в боте | статус, службы, панель, трафик, подписки, история, аудит | нет |
| 📱 Mini App | вход в панель | код TOTP на новую сессию |
| 🟡 действия | рестарт службы/xray, apt update, команда из allowlist |
код один раз, разблокировка на 15 мин |
| 🔴 разрушительное | apt full/phased, релиз-обновление, перезагрузка |
свежий код (не старше 2 мин) |
Как это выглядит:
- Открываете Mini App → «Подтвердите вход» → вводите 6 цифр.
- В боте нажимаете «Рестарт x-ui» → «🔐 Нужен код 2FA. Отправьте 6 цифр».
- Бот удаляет сообщение с кодом, проверяет и пишет «🔓 Действия разблокированы до 14:35».
- Появляется обычное подтверждение с последствиями. Дальше 15 минут опасные действия не спрашивают код (разрушительные всегда требуют свежий код).
- «🔐 Безопасность» в меню: статус, «Разблокировать», «Заблокировать сейчас».
Включение: установщик спрашивает при установке (по умолчанию да), либо
--2fa; отказ (--no-2fa) отключает TOTP. При генерации показываются
секрет, otpauth и QR-код для Google Authenticator/Aegis/1Password. Посмотреть
секрет и QR позже: sudo stacksentry-menu totp (только root).
Защита: код одноразовый в пределах окна, 3 попытки, блокировка на 5 минут,
все успехи и неудачи попадают в аудит. Секрет лежит в .env с правами
640 root:<группа сервиса>; логи его вырезают. Терминал использует отдельный
TOTP-секрет и всегда спрашивает код на каждую сессию.
- Токены бота и панели хранятся в
.envс правами640 root:<группа сервиса>; сервис читает их, но не может переписать файл. - Терминал (если включён) хранит свои секреты отдельно:
/etc/stacksentry/terminal.env,600 root, systemd передаёт их процессу черезEnvironmentFile. Сам сервисный пользователь файл не читает. - Логи чистятся форматтером: токен бота в URL, токены панели/терминала, TOTP и
access token вырезаются;
initDataне логируется; Telegram ID маскируются. - База
state.dbимеет права0600; в ней есть Telegram ID, аудит и подписки. - Шифрование «на уровне приложения» с ключом на том же сервере даёт мало: компрометация хоста всё равно раскрывает ключ. Для защиты диска используйте LUKS/шифрование VPS, бэкапы храните в шифрованном виде. Для терминала добавьте второй фактор (TOTP уже есть) и доступ через VPN/SSH-туннель.
- Бот работает непривилегированным пользователем
stacksentry; код и venv принадлежатroot,.envдоступен службе только на чтение. - Все привилегированные операции идут через
sudo stacksentry-ctlи узкий sudoers-список из точных команд (без шаблонов в аргументах, так требуют и классический sudo, иsudo-rs). Произвольного shell нет. aptвыполняется отдельными systemd-юнитамиstacksentry-apt-*.service, они не наследуют песочницу бота; при недоступности transient-юнита есть фолбэк.- Опасные действия требуют подтверждения; токен привязан к запросившему
администратору и одноразовый; всё пишется в
audit_log. - Mini App работает под отдельным пользователем без sudo и своей SQLite-базой;
его компрометация не даёт писать аудит бота или запускать
stacksentry-ctl. - Mini App требует TOTP при создании сессии: одного
initDataпри компрометации Telegram-аккаунта недостаточно. Использованные TOTP/initData сохраняются в SQLite и не принимаются повторно после перезапуска. Терминал требует отдельный TOTP на каждую сессию. Root-сессия дополнительно включается только флагом--root-terminal; SSH-ключ терминала хранится на сервере и наружу не выдаётся. - Клиент панели не следует редиректам, значения из панели экранируются, токен
бота не попадает в логи даже на
DEBUG. - Повторы ограничены
ACTION_COOLDOWN; flood control Telegram обрабатывается повтором с паузой, длинные сообщения режутся по строкам. - Команды принимаются только в личном чате; попытки посторонних пишутся в журнал
(
denied). - Установщик умеет проверять контрольную сумму архива (
--sha256). - Секреты вырезаются из логов форматтером (включая текст исключений), Telegram
ID маскируются (
…789),stacksentry-menu show/checkне печатают секреты. - Для самоподписанного сертификата есть
PANEL_CA_BUNDLE, вместо отключения проверки TLS можно держать пиннинг.
Ресурсы службы ограничены (MemoryMax=256M, TasksMax=64), вывод команд
обрезается (16 КБ) и имеет таймаут.
sudo stacksentry-doctor # конфиг, база, службы, панель
sudo stacksentry-doctor --no-network # без запросов к панели# обновление (конфиг и состояние сохраняются)
bash <(curl -Ls https://raw.githubusercontent.com/Hijackery/stacksentry/main/install.sh)
# то же из меню
sudo stacksentry-menu # пункт 24
# проверить обновления, ничего не устанавливая
sudo stacksentry-menu update-check
# или в боте: /updatecheck / «❓ Помощь» → «🔄 Проверить обновления»
# в боте: при наличии обновления появляется «⬆️ Обновить StackSentry»
# (подтверждение + свежий TOTP; .env и состояние сохраняются)
# удалить целиком: служба, sudoers, обёртка, меню, код, база и пользователь
sudo bash install.sh --uninstall
# сохранить базу и пользователя
sudo bash install.sh --uninstall --keep-state
# интерактивное меню установщика
sudo bash install.sh --menuУдаление печатает одну строку «Бот удалён.» и закрывает stacksentry-menu. При
--keep-state остаётся предупреждение о том, что база и пользователь сохранены.
GitHub Releases проект не публикует: проверка и установка идут по
main. ПинUPDATE_SHA256опционален. GitHub может отдаватьmainиз кэша пару минут,update-checkэто учитывает.
systemctl status stacksentry-bot
journalctl -u stacksentry-bot -n 50 --no-pager| Симптом | Что делать |
|---|---|
| «Синтаксис sudoers невалиден» | установщик печатает строку от visudo, пришлите её в issue |
«Системные метрики недоступны: /proc/stat» |
в старой установке остался ProcSubset=pid: sudo sed -i '/^ProcSubset=/d' /etc/systemd/system/stacksentry-bot.service && sudo systemctl daemon-reload && sudo systemctl restart stacksentry-bot |
| «Токен отклонён» | проверьте TELEGRAM_BOT_TOKEN и PANEL_API_TOKEN через sudo stacksentry-menu → «Показать настройки» |
inbounds/list недоступен |
у токена панели нет scope node-sync |
Панель отвечает 404 на API |
проверьте PANEL_URL/PANEL_BASE_PATH (частая ошибка: /panel в webBasePath) |
| Логи сервиса не видны | проверьте правило journal в sudoers и запуск через sudo |
| Ubuntu 26.04+ | sudo-rs запрещает шаблоны в аргументах, установщик это уже учитывает |
Проверьте настройки и журнал:
grep -E '^WEBAPP_(ENABLED|PUBLIC_ORIGIN)=' /opt/stacksentry/.env
sudo stacksentry-menu webapp
systemctl status stacksentry-bot stacksentry-webapp caddy
journalctl -u stacksentry-bot -n 100 --no-pager | grep -i 'Mini App'Кнопки появляются только при WEBAPP_ENABLED=1 и непустом
WEBAPP_PUBLIC_ORIGIN (HTTPS), а inline-кнопка только у администратора из
TELEGRAM_ADMIN_IDS. Если origin пустой, переустановите Mini App без домена:
sudo bash install.sh --webapp --no-terminal, установщик поднимет
sslip.io + Caddy автоматически. Если origin задан, но кнопки нет:
- домен должен быть привязан через
@BotFather→/setdomain(дляsslip.ioтолько хост, без порта); - публичный адрес должен открываться по HTTPS (проверьте Caddy/прокси перед
127.0.0.1:8787); - перезапустите бота после правки
.env:sudo systemctl restart stacksentry-bot; - сообщение
Не удалось поставить кнопку Mini Appв журнале означает отказ Telegram, чаще всего из-за неверного домена, HTTP вместо HTTPS или недоступного URL.
Подробнее в SECURITY.md и CHANGELOG.md.
- docs/COMPATIBILITY.md: ОС, init, пакеты, панели, протоколы, рестарт.
- docs/ARCHITECTURE.md: компоненты, поток данных, безопасность, расширение.
- docs/RELEASING.md: версии, проверка и установка обновлений.
- SUPPORT.md: куда обращаться и что приложить.
- SECURITY.md: политика и модель безопасности.
- CONTRIBUTING.md: сборка, проверки, PR.
- CHANGELOG.md: история изменений.
- Версия: SemVer в
stacksentry/__init__.py; видна в боте (/version). - GitHub Releases не публикуются: проверка и установка идут по
main. ПинUPDATE_SHA256иUPDATE_REFможно задать для доп. контроля. - Проверка обновлений: кнопка «🔄 Проверить обновления» в «Помощи», раздел
«Помощь» в Mini App,
sudo stacksentry-menu update-checkили/updatecheck. - Если обновление есть, в боте появляется кнопка «⬆️ Обновить StackSentry».
Она требует подтверждения и свежего TOTP (если 2FA включена), сохраняет
.envи состояние, затем перезапускает бота. - Ручное обновление:
sudo stacksentry-menu update(после настройки пина) или повторный запуск установщика с--sha256. Подробности и откат описаны в docs/RELEASING.md.
pip install -r requirements-dev.txt
ruff format --check .
ruff check .
mypy .
pytest -qТесты не требуют панели, Telegram и systemd: внешние вызовы подменяются.
CI гоняет Python 3.10 и 3.13, shellcheck, bash -n и visudo -cf.
- SECURITY.md: как сообщить об уязвимости и что уже защищено.
- CONTRIBUTING.md: окружение, обязательные проверки, стиль.
- SUPPORT.md: куда обращаться и что приложить.
- docs/: совместимость, архитектура, обновления.
- CHANGELOG.md: история изменений.
.env.example: все настройки с комментариями.- English README.
MIT, см. LICENSE.