diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..59dd1e6 --- /dev/null +++ b/README.en.md @@ -0,0 +1,109 @@ +# AlertBot + +[Русский](README.md) · **English** + +[![CI](https://github.com/EDeev/alertbot/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/alertbot/actions/workflows/ci.yml) +[![Docker](https://github.com/EDeev/alertbot/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/alertbot/actions/workflows/docker.yml) +[![Release](https://img.shields.io/github/v/release/EDeev/alertbot)](https://github.com/EDeev/alertbot/releases) +[![License](https://img.shields.io/github/license/EDeev/alertbot)](LICENSE) + +A Telegram bot for monitoring a small server fleet on top of Prometheus and Alertmanager: it sends +"problem / resolved" alerts and, on command, shows the state of servers, services and TLS certificates. + +**Status:** personal project, in production · watches the author's five servers + +```text +Серверы + +SPB +CPU 7% · RAM 41% · диск 38% · swap 0% +load 0.21 · аптайм 12д 4ч + +DORM · ⚠ диск +CPU 18% · RAM 63% · диск 87% · swap 2% · temp 52°C +load 1.40 · аптайм 3д 9ч +``` + +Sample /servers reply (illustrative values; the bot speaks Russian). + +**Stack:** Python 3.10+ · aiogram 3 · aiohttp · SQLite · Prometheus HTTP API · Alertmanager API v2 · Docker + +## Features + +- **Alerts:** polls Alertmanager every N seconds, deduplicates by fingerprint and immediately notifies + subscribers about new and resolved alerts. No rules of its own — whatever Alertmanager has +- **Watchdog:** if Alertmanager itself stops responding, the bot reports it once and again when + monitoring is back +- **`/servers`** — CPU, RAM, disk, swap, load, uptime and temperature per node, ⚠ above thresholds +- **`/services`** — which Prometheus targets are down +- **`/certs`** — days until TLS certificates expire, warning under 14 days +- **`/alerts`** — active alerts; `/alerts on|off` — subscription +- Access is limited to a list of Telegram IDs; everyone else is silently ignored + +## Quick start + +```bash +git clone https://github.com/EDeev/alertbot.git && cd alertbot +cp .env.example .env # bot token, IDs, Prometheus/Alertmanager URLs and tokens +docker compose up -d +``` + +Prebuilt image: `docker pull ghcr.io/edeev/alertbot` or `docker pull dcr.deev.su/edeev/alertbot`. + +## Installing without Docker + +```bash +python -m venv .venv && source .venv/bin/activate +pip install -r requirements.txt +cp .env.example .env +python bot.py +``` + +## Configuration + +| Variable | Purpose | +|---|---| +| `BOT_TOKEN` | bot token from @BotFather | +| `ALLOWED_IDS` | comma-separated Telegram IDs allowed to use the bot | +| `AM_ALERTS_URL`, `PROM_QUERY_URL` | Alertmanager `/api/v2/alerts` and Prometheus `/api/v1/query` | +| `AM_TOKEN`, `PROM_TOKEN` | tokens sent in the `Authorization: Bearer` header | +| `SERVERS_ORDER` | comma-separated node names as in the metrics' `server` label | +| `ALERT_POLL_SECONDS`, `ALERT_HTTP_TIMEOUT` | poll interval and request timeout | +| `ALERT_WATCHDOG_FAILURES` | failed polls in a row before reporting monitoring as unreachable (default 4) | +| `ALERTBOT_DB`, `ALERTBOT_LOG_FILE` | SQLite file and log file (empty means stdout only) | + +> [!IMPORTANT] +> Do not expose Prometheus and Alertmanager to the internet without authentication. The bot expects a +> reverse proxy that checks the `Authorization: Bearer …` token; see the nginx example in +> [docs/deploy.md](docs/deploy.md) (in Russian). + +## Deployment + +The bot runs on a separate VPS as a systemd unit. Prometheus and Alertmanager live on another server +behind nginx, which lets the bot in only with a token. GitHub Actions builds the Docker image on every +`v*` tag and publishes it to GitHub Packages and to `dcr.deev.su`. + +## Development + +```bash +pip install -r requirements-dev.txt +ruff check . && pytest +``` + +The tests need no network: Telegram and Prometheus are faked. They cover alert deduplication, +resolved notifications, the watchdog and report texts. + +## License + +MIT — see [LICENSE](LICENSE). + +## Author + +**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space) + +--- + +
+ ⭐ If you find this project useful, give it a star on GitHub! +

Made with ❤️ — deev.space

+
diff --git a/README.md b/README.md index 387773f..0f52757 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,109 @@ # AlertBot -Telegram-бот для мониторинга парка серверов поверх Prometheus + Alertmanager. Работает как -push-уведомитель («что-то сломалось / починилось») и как справочная панель по команде -(`/servers`, `/services`, `/certs`). +**Русский** · [English](README.en.md) + +[![CI](https://github.com/EDeev/alertbot/actions/workflows/ci.yml/badge.svg)](https://github.com/EDeev/alertbot/actions/workflows/ci.yml) +[![Docker](https://github.com/EDeev/alertbot/actions/workflows/docker.yml/badge.svg)](https://github.com/EDeev/alertbot/actions/workflows/docker.yml) +[![Release](https://img.shields.io/github/v/release/EDeev/alertbot)](https://github.com/EDeev/alertbot/releases) +[![License](https://img.shields.io/github/license/EDeev/alertbot)](LICENSE) + +Telegram-бот для мониторинга парка серверов поверх Prometheus и Alertmanager: присылает алерты +«проблема / в норме» и по команде показывает состояние серверов, сервисов и TLS-сертификатов. + +**Статус:** личный проект, работает · следит за пятью серверами автора + +```text +Серверы + +SPB +CPU 7% · RAM 41% · диск 38% · swap 0% +load 0.21 · аптайм 12д 4ч + +DORM · ⚠ диск +CPU 18% · RAM 63% · диск 87% · swap 2% · temp 52°C +load 1.40 · аптайм 3д 9ч +``` + +Пример ответа на /servers (значения условные). + +**Стек:** Python 3.10+ · aiogram 3 · aiohttp · SQLite · Prometheus HTTP API · Alertmanager API v2 · Docker ## Возможности -- **Алерты в реальном времени** — фоновая задача раз в N секунд опрашивает Alertmanager, - дедуплицирует по fingerprint и сразу шлёт «Проблема · …» / «В норме · …» подписанным - пользователям. Никаких собственных правил — подхватывает всё, что уже настроено в - Alertmanager, по лейблам, а не по именам целей. -- **`/servers`** — CPU, RAM, диск, swap, load, аптайм и (если есть hwmon-датчики) - температура по каждому узлу, с ⚠ при превышении порогов. -- **`/services`** — какие цели Prometheus сейчас `up`, какие нет. -- **`/certs`** — сколько дней осталось у каждого TLS-сертификата, с предупреждением при <14 дней. -- **`/alerts`** — список активных алертов сейчас; `/alerts on|off` — подписка/отписка. -- Доступ — по вайтлисту Telegram user id, все остальные тихо игнорируются. +- **Алерты:** раз в N секунд опрашивает Alertmanager, дедуплицирует по fingerprint и сразу пишет + «Проблема · …» и «В норме · …» подписчикам. Своих правил нет — всё, что настроено в Alertmanager +- **Сторож:** если сам Alertmanager перестал отвечать, бот один раз сообщает об этом и ещё раз — + когда мониторинг вернулся +- **`/servers`** — CPU, RAM, диск, swap, load, аптайм и температура по узлам, ⚠ при превышении порогов +- **`/services`** — какие цели Prometheus не отвечают +- **`/certs`** — дни до истечения TLS-сертификатов, предупреждение меньше чем за 14 дней +- **`/alerts`** — активные алерты; `/alerts on|off` — подписка +- Доступ — только для Telegram ID из списка, остальные молча игнорируются -## Требования - -- Python 3.10+ -- Свой Prometheus + Alertmanager с уже настроенными правилами алертов. -- Alertmanager и Prometheus должны быть доступны боту по HTTP — либо напрямую (если бот - крутится на той же машине), либо через reverse-proxy с токен-параметром в URL (так это - сделано в этом проекте — см. `AM_ALERTS_URL`/`PROM_QUERY_URL`/`AM_TOKEN`/`PROM_TOKEN` - в `.env.example`), чтобы не открывать сами Prometheus/Alertmanager в интернет без авторизации. - -## Установка +## Быстрый старт ```bash +git clone https://github.com/EDeev/alertbot.git && cd alertbot +cp .env.example .env # токен бота, ID, адреса и токены Prometheus/Alertmanager +docker compose up -d +``` + +Готовый образ: `docker pull ghcr.io/edeev/alertbot` или `docker pull dcr.deev.su/edeev/alertbot`. + +## Установка без Docker + +```bash +python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt cp .env.example .env -# заполнить .env своими значениями python bot.py ``` -## Переменные окружения +## Конфигурация -Все — в `.env.example`: +| Переменная | Назначение | +|---|---| +| `BOT_TOKEN` | токен бота от @BotFather | +| `ALLOWED_IDS` | Telegram ID через запятую, кому можно пользоваться ботом | +| `AM_ALERTS_URL`, `PROM_QUERY_URL` | Alertmanager `/api/v2/alerts` и Prometheus `/api/v1/query` | +| `AM_TOKEN`, `PROM_TOKEN` | токены, бот передаёт их в заголовке `Authorization: Bearer` | +| `SERVERS_ORDER` | имена узлов через запятую, как в лейбле `server` метрик | +| `ALERT_POLL_SECONDS`, `ALERT_HTTP_TIMEOUT` | период опроса и таймаут запросов | +| `ALERT_WATCHDOG_FAILURES` | после скольких неудачных опросов подряд сообщать о недоступности (по умолчанию 4) | +| `ALERTBOT_DB`, `ALERTBOT_LOG_FILE` | файл SQLite и файл лога (пусто — только stdout) | -- `BOT_TOKEN` — токен бота от @BotFather. -- `ALLOWED_IDS` — Telegram user id через запятую, кому разрешено пользоваться ботом. -- `AM_ALERTS_URL` / `PROM_QUERY_URL` / `AM_TOKEN` / `PROM_TOKEN` — адреса и токены до - Alertmanager API (`/api/v2/alerts`) и Prometheus API (`/api/v1/query`). -- `SERVERS_ORDER` — имена узлов через запятую, ровно как они указаны в лейбле `server` - у твоих метрик (`node_exporter` и т.п.) — определяет порядок и состав вывода `/servers`. -- `ALERT_POLL_SECONDS` / `ALERT_HTTP_TIMEOUT` — период опроса и таймаут запросов. +> [!IMPORTANT] +> Не открывайте Prometheus и Alertmanager в интернет без авторизации. Бот рассчитан на обратный прокси, +> который проверяет токен из заголовка `Authorization: Bearer …`, — пример для nginx в +> [docs/deploy.md](docs/deploy.md). -## Структура +## Развёртывание -``` -init.py # конфиг из переменных окружения, инициализация Bot/Dispatcher -sql.py # SQLite: подписчики на алерты, дедуп по fingerprint -handlers.py # команды бота + фоновый опрос Alertmanager -bot.py # точка входа +Бот работает на отдельном VPS как systemd-юнит. Prometheus и Alertmanager стоят на другом сервере +за nginx, который пускает бота только с токеном. Docker-образ собирает GitHub Actions на каждый тег +`v*` и публикует в GitHub Packages и в реестр `dcr.deev.su`. + +## Разработка + +```bash +pip install -r requirements-dev.txt +ruff check . && pytest ``` -Хранилище — один файл SQLite (`notifications.db`, путь по умолчанию задаётся при -инициализации `DatabaseManager`), без внешних зависимостей вроде Redis/Postgres. - -## Продакшен - -Юнит `systemd` — самый простой способ держать бота в фоне постоянно: - -```ini -[Unit] -Description=AlertBot -After=network.target - -[Service] -Type=simple -WorkingDirectory=/opt/alertbot -ExecStart=/opt/alertbot/venv/bin/python3 bot.py -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` +Тесты работают без сети: Telegram и Prometheus подменяются. Проверяются дедупликация алертов, +сообщения о возврате в норму, сторож и тексты сводок. ## Лицензия -MIT +MIT — см. [LICENSE](LICENSE). + +## Автор + +**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space) + +--- + +
+ ⭐ Если проект оказался полезным, поставьте звёздочку на GitHub! +

Сделано с ❤️ — deev.space

+
diff --git a/docs/deploy.md b/docs/deploy.md new file mode 100644 index 0000000..d0231b0 --- /dev/null +++ b/docs/deploy.md @@ -0,0 +1,58 @@ +# Развёртывание + +## Docker + +```bash +cp .env.example .env +docker compose up -d +docker compose logs -f bot +``` + +Подписки и состояние алертов хранятся в томе `data` (`/data/notifications.db`). + +## systemd + +```ini +[Unit] +Description=AlertBot +After=network.target + +[Service] +Type=simple +WorkingDirectory=/opt/alertbot +ExecStart=/opt/alertbot/venv/bin/python bot.py +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +## Обратный прокси перед Prometheus и Alertmanager (nginx) + +Бот отправляет токен в заголовке `Authorization: Bearer <токен>`. Пример проверки: + +```nginx +# в контексте http (например, /etc/nginx/conf.d/alertbot-auth.conf) +map $http_authorization $alertbot_auth_ok { + default 0; + "Bearer ВАШ_ТОКЕН" 1; +} + +# в server { ... } +location /prombot/ { + if ($alertbot_auth_ok = 0) { return 403; } + proxy_pass http://127.0.0.1:9090/; +} +location /ambot/ { + if ($alertbot_auth_ok = 0) { return 403; } + proxy_pass http://127.0.0.1:9093/; +} +``` + +## Что ожидается от Prometheus + +- у метрик node_exporter есть лейбл `server` с короткими именами узлов (как в `SERVERS_ORDER`); +- джобы node_exporter называются `node_*`; +- для `/certs` — blackbox exporter с метрикой `probe_ssl_earliest_cert_expiry`; +- температура берётся из `node_hwmon_temp_celsius` с `chip=~"pci.*"` (настоящие датчики).