Перейти к основному содержимому
  1. Posts/
  2. Self-Hosting/

Gotify: свой собственный сервер push-уведомлений для гипервизора и не только

·2133 слов·11 минут· loading · loading · ·
Stilicho2011
Автор
Stilicho2011
Пишу о homelab, self-hosting, автоматизации и open-source решениях
Оглавление
Self-Hosting - This article is part of a series.
Part : This Article

Зачем свой сервер уведомлений
#

Если у вас есть хотя бы минимальная homelab, вы наверняка сталкивались с ситуацией, когда уведомления сыпятся практически отовсюду - из Proxmox, из PBS бэкапов, из систем безопасности и так далее. Всё это оседает одним общим потоком в вашем мессенджере, в моем случае, в личном Telegram-боте вперемешку с обычными сообщениями. Рано или поздно в этой куче теряется действительно важное, например, что диск не прошёл SMART-тест или что кто-то сканирует ваши порты. Да и просто это начинает восприниматься как информационный шум, на который мозг отказывается реагировать.

Решение - завести отдельное приложение только для того, что происходит в homelab.

Gotify - лёгкий self-hosted сервис именно для этого: простой, быстро разворачивается, гибко настраивается и не тянет за собой лишних зависимостей.

Note

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

Как устроен Gotify
#

Схема работы предельно простая и укладывается в одну картинку:

flowchart LR
    A1[Proxmox VE] -->|push| G((Gotify server))
    A2[CrowdSec] -->|push| G
    A3[Любой другой сервис
Linux / Windows] -->|push| G G --> W[Web UI] G --> AND[Официальный клиент Android] G --> IOS[Неофициальный клиент iOS
iGotify]
  • Applications - это приложения или сервисы, которые отправляют уведомления на сервер Gotify. Windows/Linux в описании сервиса - это лишь операционные системы, на которых эти приложения-отправители могут работать, сам Gotify-сервер при этом один и работает в Docker-контейнере.
  • Gotify server - центральный компонент, который принимает сообщения и раздаёт их подписанным клиентам.
  • Clients - то, чем вы читаете уведомления: веб-интерфейс, официальное приложение для Android или неофициальное (но рабочее) приложение iGotify для iOS/iPadOS, которое не указано на официальном сайте, потому что поддерживается энтузиастом, а не командой проекта.

Шаг 1. Установка через Docker Compose
#

Gotify можно развернуть бинарником или в Docker - второй вариант удобнее для тех, кто и так держит остальные сервисы в контейнерах.

Официальный docker-compose.yml спрятан на сайте проекта под настройкой docker run в сворачиваемом блоке. Ниже мой реальный рабочий файл - сразу вместе с алертером для Komodo, о котором расскажу в шаге 6, поэтому оба сервиса сидят в одной Docker-сети:

services:
  gotify:
    image: gotify/server
    container_name: gotify
    volumes:
      - /home/stilicho/docker/gotify:/app/data
    #ports:
    #  - "xxxx:80"
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - gotify
      - proxy
    environment:
      - TZ=${TZ}
      - GOTIFY_OIDC_ENABLED=true
      - GOTIFY_OIDC_ISSUER=${GOTIFY_OIDC_ISSUER}
      - GOTIFY_OIDC_CLIENTID=${GOTIFY_OIDC_CLIENTID}
      - GOTIFY_OIDC_CLIENTSECRET=${GOTIFY_OIDC_CLIENTSECRET}
      - GOTIFY_OIDC_REDIRECTURL=${GOTIFY_OIDC_REDIRECTURL}
      - GOTIFY_OIDC_LINK_BY_USERNAME=true
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.gotify.entrypoints=web"
      - "traefik.http.routers.gotify.rule=Host(`gotify.stilicho.ru`)"
      - "traefik.http.middlewares.gotify-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.gotify.middlewares=gotify-https-redirect"
      - "traefik.http.routers.gotify-secure.entrypoints=websecure"
      - "traefik.http.routers.gotify-secure.rule=Host(`gotify.stilicho.ru`)"
      - "traefik.http.routers.gotify-secure.tls=true"
      - "traefik.http.routers.gotify-secure.service=gotify"
      - "traefik.http.services.gotify.loadbalancer.server.port=80"
      - "traefik.docker.network=proxy"
  komodo-gotify:
    container_name: gotify-alerter
    image: foxxmd/komodo-gotify-alerter:latest
    environment:
      - GOTIFY_URL=${GOTIFY_URL}
      - GOTIFY_APP_TOKEN=${GOTIFY_APP_TOKEN}
    networks:
      - gotify
    ports:
      - "7000:7000"
    depends_on:
      - gotify

networks:
  gotify:
    external: true
  proxy:
    external: true

Все переменные вида ${TZ}, ${GOTIFY_OIDC_ISSUER} и так далее compose подставляет из файла .env, который должен лежать рядом с docker-compose.yml:

# Gotify / Authentik OIDC
TZ=Europe/Moscow
GOTIFY_OIDC_ISSUER=https://authentik.stilicho.ru/application/o/gotify/
GOTIFY_OIDC_CLIENTID=клиентский_id_из_Authentik
GOTIFY_OIDC_CLIENTSECRET=клиентский_секрет_из_Authentik
GOTIFY_OIDC_REDIRECTURL=https://gotify.stilicho.ru/auth/oidc/callback
GOTIFY_URL=https://gotify.stilicho.ru
GOTIFY_APP_TOKEN=токен_приложения_komodo_из_Gotify
Warning

GOTIFY_OIDC_CLIENTSECRET и GOTIFY_APP_TOKEN — полноценные секреты: первый даёт доступ к OIDC-клиенту в Authentik, второй позволяет слать сообщения в Gotify от имени приложения. Не коммитьте .env в git — добавьте его в .gitignore рядом с compose-файлом, а если секрет всё же засветился где-то (например, случайно попал в чат, лог или публичный репозиторий) — обязательно перевыпустите его: в Authentik пересоздайте OIDC client secret, в Gotify — удалите и заново создайте токен приложения.

Разберём, что здесь важно:

  • volumes - используется bind mount вместо именованного volume: путь на хосте прописан явно, так проще делать бэкапы.

  • ports - закомментирован: прямой доступ по порту отключён, наружу Gotify публикуется только через Traefik (см. блок labels ниже). Если Traefik не используется, раскомментируйте ports и уберите labels - тогда сервис будет доступен напрямую по http://<ip-сервера>:<порт>.

  • security_opt: no-new-privileges:true - если контейнер будет скомпрометирован, злоумышленник не сможет повысить привилегии и выбраться за его пределы.

  • networks: gotify и proxy - обе сети внешние (external: true), то есть compose их не создаёт сам, а ожидает, что они уже существуют. gotify - отдельная сеть только для Gotify и его алертера, proxy - общая сеть Traefik. Обе нужно создать заранее, если ещё не создавали их под другие сервисы:

    docker network create gotify
    docker network create proxy
  • TZ - часовой пояс из .env: Gotify работает с уведомлениями и должен понимать, когда именно что-то произошло.

  • GOTIFY_OIDC_* - включение SSO через внешнего провайдера (в моём случае Authentik), значения тоже из .env. Если у вас нет своего OIDC-провайдера, весь этот блок из четырёх переменных смело удаляйте - Gotify прекрасно работает и с обычной локальной парой логин/пароль. GOTIFY_OIDC_LINK_BY_USERNAME=true привязывает уже существующего локального пользователя Gotify к учётке из Authentik по совпадению имени, а не создаёт нового.

  • labels - стандартный набор для публикации через Traefik: HTTP-роутер с редиректом на HTTPS, HTTPS-роутер с TLS и балансировщик на внутренний порт 80 контейнера. Домен gotify.stilicho.ru замените на свой.

  • komodo-gotify - это уже алертер для Komodo из шага 6; он развёрнут в том же файле и в той же сети gotify, поэтому в Komodo эндпоинт можно указывать просто по имени контейнера, без IP. GOTIFY_URL и GOTIFY_APP_TOKEN тоже берутся из .env.

Поднимаем стек:

docker compose up -d

Сервис лёгкий и поднимается почти мгновенно - никаких зависимостей вроде отдельной базы данных ему не нужно (по умолчанию используется SQLite).

Tip

В переменные окружения можно сразу передать логин и пароль администратора (GOTIFY_DEFAULTUSER_NAME / GOTIFY_DEFAULTUSER_PASS), но удобнее и безопаснее просто зайти под дефолтным admin/admin и сменить пароль сразу через веб-интерфейс - так пароль не осядет в открытом виде в compose-файле.

Шаг 2. Первый вход и смена пароля
#

Откройте адрес, на котором развёрнут Gotify - в примере выше это домен через Traefik (https://gotify.stilicho.ru), а если вы раскомментировали ports вместо labels, то http://<ip-сервера>:<порт> - и войдите с логином admin и паролем admin.

Note

Если вы включили GOTIFY_OIDC_* (SSO через Authentik или другой провайдер), на странице входа появится дополнительная кнопка входа через SSO. Локальный admin/admin при этом никуда не пропадет - это отдельный, независимый способ входа.

Сразу после входа:

  1. Откройте раздел Users.
  2. Кликните на пользователя admin.
  3. Задайте новый пароль (или новое имя, если хотите) и сохраните.

Здесь же, при необходимости, можно создать дополнительных пользователей кнопкой Create User - с правами администратора или без, если вы хотите дать доступ кому-то ещё.

Шаг 3. Приложения и клиенты
#

В Gotify два независимых понятия, которые легко перепутать:

  • Apps - источники, которые отправляют уведомления. У каждого приложения свой токен и свой приоритет по умолчанию (от 0 до 10, где 10 - самое важное).
  • Clients - получатели, через которые вы читаете уведомления (веб-браузер, мобильное приложение). У каждого клиента тоже свой токен.

Создайте тестовое приложение:

  1. Перейдите в Apps → Create Application.
  2. Укажите имя, например Test, и при желании короткое описание.
  3. Задайте Default Priority - на этом этапе можно оставить среднее значение.
  4. Скопируйте появившийся токен приложения - он понадобится любому сервису, который будет слать сообщения через Gotify.

Для мобильного клиента процесс аналогичный, только в разделе Clients:

  1. Clients → Create, укажите название (например, по имени телефона).
  2. Скопируйте токен клиента.
  3. В приложении на телефоне (Android - официальный клиент, iOS/iPadOS - iGotify) укажите URL вашего сервера Gotify и этот токен.
Warning

Кнопка «Copy to clipboard» в интерфейсе Gotify не всегда срабатывает стабильно - если токен не скопировался, просто выделите и скопируйте его вручную.

Шаг 4. Уведомления от Proxmox VE
#

Начиная с Proxmox VE 8.x, поддержка Gotify встроена «из коробки» - отдельный агент не нужен.

  1. В интерфейсе Proxmox перейдите в Datacenter → Notifications → Notification Targets.
  2. Нажмите Add → Gotify.
  3. Задайте:
    • Name - произвольное имя цели, например homelab;
    • Server URL - адрес вашего сервера Gotify (https://gotify.example.com, или просто IP, если сервис не публикуется наружу);
    • API Token - токен приложения, созданного на предыдущем шаге (удобно сделать отдельное приложение, например Proxmox, с приоритетом 10).
  4. Нажмите Add - цель создана.
  5. Сразу же проверьте связь кнопкой Test: должно прийти тестовое сообщение, которое будет видно в All Messages в интерфейсе Gotify.

Дальше нужно создать Notification Matcher - правило, которое связывает события Proxmox с только что созданной целью:

  1. Datacenter → Notifications → Notification Matchers → Add.
  2. Название, например homelab-matcher, галочка Enable.
  3. В разделе правил нажмите Add, выберите тип Match Severity и оставьте отмеченными все уровни (info, notice, warning, error, unknown) - так уведомления будут приходить обо всём, что происходит в гипервизоре.
  4. В Target выберите созданную ранее цель (homelab).
  5. Сохраните.

Проверить работу проще всего на реальном событии - например, запустив ручной бэкап LXC-контейнера или виртуальной машины. В Gotify практически сразу появится сообщение с именем ноды, ID контейнера, статусом и длительностью операции.

Шаг 5. Уведомления от CrowdSec
#

Если у вас развёрнут CrowdSec (например, вместе с Traefik), уведомления о попытках сканирования портов или срабатывании бана - это ровно то, что не должно теряться среди прочего шума.

CrowdSec поддерживает Gotify через встроенный http-плагин. Есть один нюанс, из-за которого настройку легко сломать, - имя плагина в двух файлах обязательно должно совпадать.

  1. Зайдите в директорию, где развёрнут CrowdSec, в подпапку config.
  2. Откройте profiles.yaml и раскомментируйте (или добавьте) две строки:
    • notifications:
    • - http_default (название вашего http-плагина - по умолчанию http-default)
  3. В подпапке notifications откройте (или создайте) файл http.yaml. Обратите внимание на строку name: в начале файла - именно она должна дословно совпадать с тем, что вы указали в profiles.yaml.
  4. В том же http.yaml пропишите:
    • url: - адрес вашего сервера Gotify с указанием токена приложения (создайте для CrowdSec отдельное приложение в Gotify с максимальным приоритетом), формат URL и структура запроса указаны в официальной документации CrowdSec для http-плагина Gotify;
    • при копировании конфига с сайта обязательно проверьте пробелы и отступы YAML - одна лишняя или пропущенная буква, и контейнер запустится, но плагин уведомлений работать не будет.
  5. Перезапустите стек:
docker compose restart
Caution

Если название плагина в profiles.yaml и в http.yaml не совпадает (например, http-goify в одном файле и http-default в другом), CrowdSec запустится без единой ошибки в логах, но уведомления просто не будут приходить. Если у вас весь трафик проходит через связку Traefik → CrowdSec → Authentik, то от неработающих уведомлений эта цепочка не сломается - но вы просто не узнаете вовремя, что CrowdSec перестал нормально функционировать.

Проверить работу плагина без ложных срабатываний сложно - тестового события «изнутри» нет. Проще всего временно забанить свой же IP вручную через cscli decisions add - уведомление о бане должно прийти в Gotify почти мгновенно.

Шаг 6. Уведомления от Komodo
#

Если вы управляете стеками через Komodo (замена Portainer), у неё нет нативной поддержки Gotify - только тип оповещателя Custom, который отправляет вебхук на произвольный HTTP-эндпоинт. Роль «переводчика» между Komodo и Gotify берёт на себя небольшой сторонний сервис - komodo-gotify-alerter от разработчика FoxxMD. Он принимает вебхук от Komodo и пересылает его дальше в Gotify уже в виде обычного push-сообщения.

Сервис komodo-gotify уже описан в общем compose-файле на шаге 1 - он поднимается вместе с самим Gotify, в той же сети gotify, и слушает порт 7000. Напомню, какие переменные у него важны:

  • GOTIFY_URL и GOTIFY_APP_TOKEN - адрес вашего сервера Gotify и токен приложения; создайте для этого отдельное приложение в Gotify, например Komodo.
  • по желанию можно добавить GOTIFY_OK_PRIORITY, GOTIFY_WARNING_PRIORITY, GOTIFY_CRITICAL_PRIORITY - привязка приоритета Gotify-уведомления к уровню серьёзности алерта Komodo;
  • а также UNRESOLVED_TIMEOUT_TYPES и UNRESOLVED_TIMEOUT - удобная опция для шумных типов алертов вроде ServerCpu или ServerMem: если состояние вернулось в норму за указанное время (в миллисекундах), уведомление не отправляется вовсе. В моём файле их нет, но при желании добавляются в environment тем же способом, что и остальные переменные.

Дальше настройка полностью на стороне Komodo:

  1. В интерфейсе Komodo перейдите в Alerters → Create Alerter.
  2. Тип - Custom.
  3. В поле эндпоинта укажите адрес контейнера-алертера и порт 7000. Поскольку Gotify и алертер сидят в одной Docker-сети gotify, можно указать прямо имя контейнера: http://gotify-alerter:7000 (если Komodo запущена в другой сети - соответствующий IP хоста).
  4. При желании ограничьте Alert Types, которые должны попадать в Gotify.
  5. Сохраните и нажмите Test Alerter - тестовое сообщение должно прийти в Gotify так же, как и все остальные push-уведомления.
Tip

Так как в цепочке появляется ещё один HTTP-хоп (Komodo → алертер → Gotify), удобно завести под этот алертер отдельное приложение в Gotify с понятным названием и высоким приоритетом - тогда в общем списке сообщений сразу видно, что уведомление пришло именно от Komodo, а не от самого Docker-хоста.

Что ещё стоит подключить
#

Из всего, что умеет слать уведомления в Gotify «из коробки», для домашней инфраструктуры чаще всего критичны три сервиса:

  • Proxmox VE - статус бэкапов и события гипервизора (см. выше);
  • CrowdSec - попытки сканирования портов и срабатывания банов (см. выше);
  • Uptime Kuma - падение любого отслеживаемого сервиса; Gotify поддерживается им нативно, настройка аналогична - свой URL и токен приложения в разделе Notifications.

Всё остальное - уже опционально, но у Gotify достаточно большое community: на GitHub-странице contrib можно найти готовые плагины для Zabbix, MQTT, email-ingest, Slack и десятков других сценариев, либо написать свой на Go.

Note

Telegram и email пока не входят в число сервисов со встроенной поддержкой Gotify - если вам одновременно нужны и они, для них по-прежнему придётся настраивать отдельные интеграции.

Итог
#

Gotify закрывает узкую, но очень важную задачу: получать push-уведомления только о том, что происходит на собственной инфраструктуре, не смешивая их с личной перепиской. Развёртывание занимает несколько минут, конфигурация минимальна, а благодаря нативной поддержке в Proxmox VE, CrowdSec и Uptime Kuma можно быстро закрыть три самых критичных источника событий в домашней лаборатории.

Официальная документация проекта: gotify.net/docs Исходный код: github.com/gotify/server

Self-Hosting - This article is part of a series.
Part : This Article

Related

Dozzle: удобный просмотр логов Docker-контейнеров в реальном времени

·1373 слов·7 минут· loading · loading
Пошаговый обзор Dozzle - лёгкого self-hosted инструмента для просмотра логов Docker-контейнеров в реальном времени через веб-интерфейс. Установка через Docker Compose, настройка авторизации, мультихост-режим через агенты и рекомендации по безопасности docker.sock.

Diun: уведомления об обновлениях Docker-образов

··931 слово·5 минут· loading · loading
Подробная инструкция по установке и настройке Diun для отслеживания обновлений Docker-образов. Рассмотрены шаги по развертыванию, интеграции с уведомлениями и автоматизации мониторинга, чтобы своевременно обновлять контейнеры и повышать безопасность системы.