Мониторинг у меня есть, а вот привычки смотреть в Grafana — нет. Дашборд красивый, но если он открыт только когда я о нём вспомнил, то он бесполезен. Алерт должен приходить туда, куда я реально смотрю — на телефон.

Почему не чат

Первая мысль была очевидной: завести чат и слать алерты туда. Я честно перебрал варианты.

  • Rocket.Chat, Mattermost — умеют push и дружат с Grafana из коробки,

но тянут за собой MongoDB или PostgreSQL и сотни мегабайт памяти.

  • Matrix — лёгкий и с настоящим push, но алерты в него придётся

заводить через бота-прослойку.

  • IRC — самый лёгкий, но у мобильных IRC-клиентов нет нормального push.
  • Telegram — проще всего, но сервер не open-source, а мне хотелось

держать уведомления у себя.

Я остановился на ntfy. Это опенсорс-сервер push-уведомлений: около пятнадцати мегабайт памяти, официальные приложения на iOS и Android и настоящий push. Не чат — канал уведомлений, и для алертов этого достаточно.

Первая засада: поддомен

ntfy нельзя повесить на подпуть вроде /ntfy/ — он требует, чтобы адрес не содержал пути. Значит, нужен отдельный поддомен. Я добавил запись:

ntfy.bagilov.tech  A  158.160.201.2

и выпустил на неё сертификат. Это сразу меняет правила: сервис живёт на своём хосте, а не внутри сайта.

Как устроена цепочка

Grafana alert ──webhook──▶ /api/alerts/grafana ──▶ ntfy ──▶ телефон

Grafana шлёт алерт вебхуком. Но у неё тело — это JSON, а на телефоне хочется видеть человеческий текст. Поэтому между ними стоит маленький relay: он разбирает JSON и публикует в ntfy уже готовое сообщение с заголовком и приоритетом.

На телефоне это выглядит так:

Grafana: firing
[firing] Backup not completed in 26h: No successful site backup in 26 hours

Доступ

Публично писать в топик нельзя просто так: я включил авторизацию и оставил только запись для Grafana и чтение для себя. Телефон входит под логином, Grafana публикует без секретов в конфиге.

Сам топик живёт здесь: ntfy.bagilov.tech/alerts.

Первый алерт

Первый алерт — про сам бэкап: «успешного бэкапа не было больше 26 часов». Скрипт бэкапа пишет статус в лог, Promtail отправляет его в Loki, а Grafana следит, что успешный статус был свежим. Если бэкап упал или не запустился — приходит уведомление.

Что понял

Self-hosted push — это не «поставил и забыл». Поддомен, сертификат, auth, и отдельно — настройка фоновых уведомлений, когда приложение закрыто. Но взамен я получил то, что хотел: алерты приходят на телефон, и всё это живёт у меня, а не у чужого сервиса.

P.S. получилось интересно и полезно