ChimePort: свой центр уведомлений вместо очередного Telegram-бота

У меня дома и на работе хватает вещей, которым время от времени нужно что-нибудь сообщить. Мониторинг обнаружил недоступный сервер, Home Assistant заметил открывшуюся дверь, скрипт закончил резервное копирование. Вроде бы ничего сложного: отправить сообщение — и всё.

На практике почти всегда получается очередной бот в Telegram. Отдельный токен, отдельная настройка, иногда ещё и прокси, чтобы он нормально работал из нужной сети. Потом появляется второй сервис, третий, и начинаешь думать: а почему бы им всем не отправлять сообщения в одну свою систему?

Так у меня появился ChimePort — небольшой открытый self-hosted сервер уведомлений с веб-панелью, Android-приложением и Web Push для браузеров. Я уже развернул его у себя и проверил настоящую доставку и на телефон, и в Firefox. Значит, пора рассказать, что получилось.

ChimePort — логотип собственного центра уведомлений

Зачем мне понадобился ChimePort

Telegram сам по себе тут не виноват. Он неплохо справляется с сообщениями, но для автоматизации у него есть неудобная особенность: уведомления моего сервера оказываются привязаны к чужой инфраструктуре. Сначала нужно завести бота, потом получить токен, разобраться с доставкой, а в некоторых сетях — ещё и с доступом к API.

К тому же разные приложения живут своей жизнью. У мониторинга один бот, у домашней автоматизации другой, у случайного скрипта — третий. А я хочу гораздо более простую схему: есть канал «Серверы», есть канал «Дом», и любая программа, которой разрешено туда писать, отправляет событие по HTTP. Как его показать пользователю — уже задача ChimePort.

При этом я не собирался писать очередной мессенджер. Никаких переписок, групповых чатов и социализации. ChimePort — именно доставка системных и прикладных уведомлений. Источники публикуют события, пользователи их получают.

Как всё устроено

Серверная часть написана на Go, данные хранятся в SQLite. Для установки достаточно одного Docker-контейнера с постоянным томом данных и HTTPS reverse proxy перед ним. Не нужны отдельные PostgreSQL, Redis, брокер сообщений или внешний аккаунт.

Сначала администратор создаёт пользователя, каналы и источники. Источник получает токен с разрешением на конкретные каналы. Такой токен можно передать мониторингу, Home Assistant или собственному скрипту.

Дальше всё выглядит примерно так: программа делает HTTP-запрос в ChimePort, сервер проверяет токен и права, сохраняет сообщение в базу и сообщает о нём клиентам. Если клиент не был подключён, сообщение не пропадает — при следующем обращении он получит его из истории.

Мне важно было разделить хранение сообщения и попытку показать уведомление. Даже если телефон в этот момент без Интернета или браузерный push не дошёл, сам факт события остаётся в своей базе. Это, конечно, не гарантирует, что человек увидел уведомление, но хотя бы позволяет нормально синхронизироваться после сбоя.

Каналы, токены и обычные человеческие настройки

Изначально хотелось просто отправить JSON и увидеть сообщение. Но довольно быстро выяснилось, что даже для одного пользователя нужны некоторые удобства.

  • Каналы — чтобы события мониторинга, домашней автоматизации и других систем не смешивались в одну бесконечную ленту.
  • Отдельные токены источников — чтобы можно было ограничить доступ и при необходимости отозвать один токен, не ломая остальные интеграции.
  • Приоритеты — потому что сообщение о завершённом бэкапе и об отключившемся важном сервере всё-таки не одно и то же.
  • Тихие часы, звуки и вибрация в Android-клиенте — чтобы ночью телефон не радовался каждому штатному событию. Срочные сообщения могут обходить тихие часы.
  • История и прочтение — возможность открыть приложение позже и посмотреть, что происходило, вместо поисков старых сообщений в чате.

Есть и встроенная страница с примерами отправки: не нужно каждый раз вспоминать, как называется нужный endpoint и какой заголовок передавать.

Android и браузер: два разных клиента

С Android оказалось интереснее, чем хотелось бы. Показать уведомление, пока приложение открыто, довольно просто. Добиться внятной доставки при свёрнутом приложении, с учётом фоновых ограничений системы и энергосбережения, — совсем другая история.

Сейчас Android-клиент умеет работать с несколькими серверами, показывать системные уведомления, разделять прочитанные и непрочитанные события, настраивать каналы и тихие часы. Доставка зависит от устройства и ограничений ОС; обещать, что любой телефон всегда разбудится за долю секунды, было бы неправильно.

Для браузера я сделал PWA и Web Push. ChimePort можно установить как приложение, разрешить уведомления и получать их даже без открытой вкладки, если браузер и операционная система это поддерживают.

Здесь есть любопытный нюанс. Хотя сам ChimePort находится на моём сервере, браузерные фоновые уведомления доставляются через инфраструктуру производителей браузеров — например, Mozilla Push Service для Firefox. Содержимое передаётся в зашифрованном виде, но сам push-шлюз как транспорт никуда не исчезает. Полностью независимая от сторонних посредников система фоновых браузерных push в рамках обычного Web Push не получается.

Установка и обслуживание

ChimePort можно развернуть через Docker Compose или Portainer. В репозитории есть готовая конфигурация, документация по API, создание пользователей, резервные копии, восстановление и обновления. Образы сервера публикуются в GHCR для amd64 и arm64.

Я специально не хотел повторять ситуацию, когда приложение вроде бы работает, пока ничего не случилось, а после переустановки ОС приходится заново собирать его по памяти. Поэтому в комплект вошли проверяемые бэкапы SQLite вместе с ключами, документация по восстановлению и понятные сценарии обновления.

Веб-панель получила три темы — Ocean, Paper и Control. Это не самая важная часть сервиса, но пользоваться собственным инструментом каждый день приятнее, когда на него не больно смотреть.

Что сейчас и что дальше

На момент написания доступен сервер ChimePort v0.1.4, Android-приложение пока имеет статус alpha. Веб-панель, API, история, Android-уведомления и Web Push уже работают. До какого-нибудь большого публичного сервиса с тысячами пользователей тут далеко, да и такой цели пока нет: ChimePort прежде всего делался для собственных задач и тех, кому подходит такой способ доставки.

Из того, чем ещё стоит заняться, — расширить проверку браузерной совместимости, улучшать Android-клиент и интеграции. Но основное уже работает: событие отправляется, сохраняется на сервере и показывается пользователю.

Страница ChimePort на mirv.top — описание возможностей, установки и ссылок.
Исходный код на GitHub — сервер, веб-панель и Android-клиент (AGPL-3.0-only).
Релизы ChimePort — опубликованные версии и готовые сборки.
Инструкция для Portainer — если хочется запустить у себя.

Если попробуете — буду рад замечаниям. Особенно интересен опыт работы браузерных уведомлений на разных системах: у Firefox на Linux уже есть успешно проверенный сценарий, а с остальными устройствами ещё предстоит разобраться.

Оставить комментарий

Email не публикуется. Поля, отмеченные *, обязательны.