Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

📢 Notify — Система экстренного оповещения

При воздушной тревоге, атаке на инфраструктуру или любом критическом событии — полноэкранное окно с захватом клавиатуры мгновенно появляется на всех экранах и не даёт его закрыть пока пользователь не подтвердит прочтение. Помимо тревог,уведомления отлично встраиваются в Ansible-плейбуки, Bash скрипты, Puppet манифесты: при установке ПО или обновлении ядра агент показывает попап снизу-справа с таймером.

Notify cross-platform

Автор: @PapaBorscht
Почта: me@ntfypush.ru
Сайт: papaborscht.github.io/Notify
Демо: papaborscht.github.io/Notify/demo

Платформа: GNU/Linux · Python 3.8+
Версия: 3.0
Лицензия: MIT


🚀 Быстрый старт

Установка панели управления:

cd /tmp wget https://github.com/PapaBorscht/Notify/archive/refs/heads/main.zip unzip main.zip cd /tmp/Notify-main/ bash install-panel.sh

Установка агента на хосте:

cd /tmp wget https://github.com/PapaBorscht/Notify/archive/refs/heads/main.zip unzip main.zip cd /tmp/Notify-main/ bash install-agent.sh

🪟 Windows Agent

win client

Агент уведомлений для рабочих станций Windows 10/11. Логика работы, формат запросов и типы окон полностью идентичны Linux-версии.

Установка

  1. Скачать установщик:

⬇️ NotifyAgent-Setup.exe

  1. Запустить от имени администратора
  2. Принять лицензионное соглашение и нажать Далее → Установить

Установщик автоматически:

  • Копирует агента в %LOCALAPPDATA%\NotifyAgent\
  • Прописывает автозапуск в реестре
  • Открывает порт 9988 в брандмауэре Windows
  • Запускает агента сразу после установки

Если агент уже установлен

При повторном запуске установщика появится меню:

  • Да — удалить агент с компьютера
  • Нет — переустановить (обновить)
  • Отмена — выйти без изменений

Проверка работы

netstat -an | findstr 9988

Строка LISTENING означает что агент работает и готов принимать уведомления. Иконка агента отображается в системном трее рядом с часами.

Нужен ли Python

Нет. Установщик содержит полностью автономный .exe — Python и дополнительные библиотеки на рабочих станциях не требуются.

Исходники и самостоятельная сборка

Исходный код агента и инструкция по сборке через PyInstaller находятся в папке win-client/.


💥 Доступ к панели управления

  • Адрес: http://localhost:8080
  • Логин: admin
  • Пароль: admin123

📸 Скриншоты

Панель управления

send

Добавляем хосты

Hosts

Полноэкранное уведомление — Информация

full 1

Уровень info — тёмно-синий фон. Занимает весь экран, блокирует работу до подтверждения. Заголовок, Markdown-текст и кнопка «Принял к сведению».

Полноэкранное уведомление — Тревога

Full 2

Уровень critical — тёмно-красный фон. Используется для экстренных событий: воздушная тревога, атаки на инфраструктуру, критические инциденты.

Всплывающий попап — отправка из панели

pop 2

Уровень info, тип popup — маленькое окно справа внизу. Не мешает работе пользователя, закрывается автоматически по таймеру с прогресс-баром.

Всплывающий попап — уровень Тревога

pop 1

Уровень warning, тип popup. Цветная полоска сверху и метка уровня меняются в зависимости от level.

Ansible — отправка уведомления из плейбука при установке ПО

ansible 1

Ansible плейбук выполняет POST на /api/ansible с X-API-Key. Попап появляется на рабочем столе пользователя пока идёт установка обновлений.

Ansible — уведомление об обновлении безопасности

ansible 2

Уровень warning — красная полоска. Пользователь видит уведомление и знает что компьютер нельзя выключать.


✨ Возможности

  • Два типа окон — полноэкранное (блокирует экран) и всплывающий попап (не мешает работе)
  • Три уровняinfo (синий), warning (оранжевый), critical (красный)
  • Markdown в тексте уведомлений — ## заголовки, **жирный**, > цитаты
  • Ansible интеграция — endpoint /api/ansible с X-API-Key, без браузерной авторизации
  • Параллельная рассылкаThreadPoolExecutor, настраиваемое число потоков
  • Веб-панель — управление хостами, шаблонами, историей, настройками
  • Трей-агент — иконка в системном трее, статус, счётчик, тест
  • Автозапуск — systemd user service + XDG autostart
  • Нет зависимостей кроме Python 3 и PyQt5

🏗 Архитектура

Notify Agent Architecture

Логика выбора типа окна

type в запросеlevelРезультат
fullscreenлюбойПолный экран
popupлюбойПопап снизу-справа
не указанcritical / warningПолный экран
не указанinfoПопап

🔧 Установка

Агент на рабочие станции

bash install-agent.sh

Скрипт автоматически:

  • Устанавливает PyQt5 если нет
  • Копирует файлы в /opt/notify-agent/
  • Настраивает systemd user service и XDG autostart
  • Запускает агента в активных X11-сессиях

Панель администратора

bash install-panel.sh

Открыть в браузере: http://localhost:8080
Логин: admin / Пароль: admin123

Проверка

# Агент слушает порт? ss -tlnp | grep 9988 # Тест напрямую curl -X POST http://127.0.0.1:9988 \ -H "X-Token: supersecrettoken123" \ -H "Content-Type: application/json" \ -d '{"title":"Тест","message":"## Работает!","level":"info"}'

🤖 Ansible интеграция

Простой вызов

curl -X POST http://notify-server:8080/api/ansible \ -H "X-API-Key: ansible-secret-key" \ -H "Content-Type: application/json" \ -d '{ "title": "⚠️ Обновление ядра", "message": "## Не выключайте компьютер!\n\nИдёт установка.", "level": "warning", "type": "popup", "timeout": 15, "hosts": ["192.168.1.10"] }'

Плейбук обновления ядра

--- - name: Обновление ядра hosts: workstations gather_facts: false become: yes tasks: - name: Уведомить — начало uri: url: "http://192.168.0.84:8080/api/ansible" method: POST headers: Content-Type: "application/json" X-API-Key: "ansible-secret-key" body_format: json body: title: "⚠️ Обновление ядра" message: "## Не выключайте компьютер!\n\nНачинается обновление." level: "warning" type: "popup" timeout: 15 hosts: - "{{ inventory_hostname }}" become: false - name: apt-get update command: apt-get update - name: update-kernel command: update-kernel -y - name: Уведомить — готово uri: url: "http://192.168.0.84:8080/api/ansible" method: POST headers: Content-Type: "application/json" X-API-Key: "ansible-secret-key" body_format: json body: title: "✅ Готово" message: "## Обновление завершено!\n\nПерезагрузка..." level: "info" type: "popup" timeout: 10 hosts: - "{{ inventory_hostname }}" become: false - name: Перезагрузка reboot: reboot_timeout: 300

Плейбук обновления пакетов

--- - name: Обновление пакетов hosts: workstations gather_facts: false become: yes tasks: - name: Уведомить — начало uri: url: "http://192.168.0.84:8080/api/ansible" method: POST headers: Content-Type: "application/json" X-API-Key: "ansible-secret-key" body_format: json body: title: "⚠️ Обновление пакетов" message: "## Не выключайте компьютер!\n\nНачинается обновление." level: "warning" type: "popup" timeout: 15 hosts: - "{{ inventory_hostname }}" become: false - name: apt-get update command: apt-get update - name: dist-upgrade command: apt-get dist-upgrade -y - name: Уведомить — готово uri: url: "http://192.168.0.84:8080/api/ansible" method: POST headers: Content-Type: "application/json" X-API-Key: "ansible-secret-key" body_format: json body: title: "✅ Готово" message: "## Обновление завершено!\n\nПакеты успешно обновлены." level: "info" type: "popup" timeout: 10 hosts: - "{{ inventory_hostname }}" become: false # - name: Перезагрузка (раскомментировать если нужно) # reboot: # reboot_timeout: 300

🤖 Bash интеграция, на примере обновления пакетов в RedOS

1 2 3

Пример скрипта с обратным отсчётом

#!/bin/bash # ================================================================ # notify-shutdown.sh # Обновляет пакеты, показывает обратный отсчёт и выключает АРМ # ================================================================ DELAY=60 # Общее время до выключения (секунд) STEP=10 # Интервал обновления попапа TOKEN="supersecrettoken123" AGENT="http://127.0.0.1:9988" notify() { local title="$1" msg="$2" level="$3" timeout="$4" curl -s -X POST "$AGENT" \ -H "X-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"title\":\"$title\",\"message\":\"$msg\",\"level\":\"$level\",\"type\":\"popup\",\"timeout\":$timeout}" \ > /dev/null } # ── 1. Обновить пакеты ────────────────────────────────────────── notify "🔄 Обновление пакетов" "## Идёт обновление системы\n\nНе выключайте компьютер..." "info" $DELAY dnf update-minimal -y # ── 2. Обратный отсчёт ───────────────────────────────────────── remaining=$DELAY while [ $remaining -gt 0 ]; do if [ $remaining -gt 30 ]; then level="warning" elif [ $remaining -gt 10 ]; then level="warning" else level="critical" fi notify \ "⚠️ Выключение через $remaining сек" \ "## Сохраните работу!\n\nКомпьютер выключится через **$remaining секунд**." \ "$level" \ $STEP sleep $STEP remaining=$((remaining - STEP)) done # ── 3. Финальное сообщение ────────────────────────────────────── notify "🔴 Выключение..." "## Компьютер выключается!\n\nДо свидания." "critical" 3 sleep 3 # ── 4. Выключить АРМ ─────────────────────────────────────────── /sbin/shutdown -h now

🎭 Puppet интеграция

Puppet автоматически раскладывает агент и скрипты на все машины.

Структура модуля

/etc/puppet/modules/notify/
├── manifests/
│   ├── init.pp          ← установка агента
│   └── shutdown.pp      ← скрипт выключения + cron
└── files/
    ├── agent.py
    ├── agent-start.sh
    └── notify-shutdown.sh

Установка агента — manifests/init.pp

class notify::agent { # Файлы агента file { '/opt/notify-agent': ensure => directory, mode => '0755', } file { '/opt/notify-agent/agent.py': ensure => present, source => 'puppet:///modules/notify/agent.py', mode => '0644', notify => Exec['restart-notify-agent'], } file { '/opt/notify-agent/agent-start.sh': ensure => present, source => 'puppet:///modules/notify/agent-start.sh', mode => '0755', } # XDG автозапуск file { '/etc/xdg/autostart/notify-agent.desktop': ensure => present, source => 'puppet:///modules/notify/notify-agent.desktop', mode => '0644', } # Переменные Qt для трея file { '/etc/profile.d/notify-agent.sh': ensure => present, content => "export QT_QPA_PLATFORMTHEME=\"\"\nexport QT_STYLE_OVERRIDE=\"\"\n", mode => '0644', } # Перезапустить агента если файлы изменились exec { 'restart-notify-agent': command => '/bin/bash -c "pkill -f agent.py; sleep 1"', refreshonly => true, } }

Скрипт выключения — manifests/shutdown.pp

class notify::shutdown { # Скрипт из files/ file { '/usr/local/bin/notify-shutdown.sh': ensure => present, source => 'puppet:///modules/notify/notify-shutdown.sh', mode => '0755', } # Cron — каждый день в 22:00 cron { 'notify-shutdown': ensure => present, command => '/usr/local/bin/notify-shutdown.sh', user => 'root', hour => '22', minute => '0', require => File['/usr/local/bin/notify-shutdown.sh'], } }

Применить на машины — site.pp

# Агент на все рабочие станции node /^workstation/ { include notify::agent include notify::shutdown } # Или на конкретные хосты node 'pc01.company.ru' { include notify::agent }

Применить вручную

# На всех агентах (запускается автоматически каждые 30 мин) puppet agent -t # Проверить без применения puppet agent -t --noop

📁 Структура проекта

notify-agent/
├── agent.py              # Агент — трей + HTTP + окна уведомлений
├── agent-start.sh        # Wrapper-скрипт запуска (ждёт X11, проверяет порт)
├── server.py             # Веб-сервер панели администратора
├── sender.py             # Отправщик (CLI + библиотека)
├── index.html            # SPA панель управления
├── notify-agent.service  # Systemd user service
├── install-agent.sh      # Установщик агента
├── install-panel.sh      # Установщик панели
├── test_notify.py        # Автотесты (50 тестов)
└── DOCUMENTATION.md      # Полная документация (16 разделов)

⚙️ Настройка

В server.py:

ADMIN_PASSWORD = "admin123" # Пароль веб-панели AGENT_TOKEN = "supersecrettoken123" # Токен агента (совпадает с agent.py) SEND_SETTINGS = { "max_workers": 50, # Потоков параллельно "send_timeout": 3, # Секунд ждать ответа от агента } ANSIBLE_SETTINGS = { "api_key": "ansible-secret-key" # API ключ для Ansible }

В agent.py:

PORT = 9988 # Порт HTTP сервера агента TOKEN = "supersecrettoken123" # Совпадает с server.py POPUP_DEFAULT_TIMEOUT = 8 # Секунд до закрытия попапа

🔧 Управление

# Агент (от пользователя) systemctl --user status notify-agent systemctl --user restart notify-agent tail -f /tmp/notify-agent-$(whoami).log # Панель (root) systemctl status notify-panel systemctl restart notify-panel journalctl -u notify-panel -f # Автотесты python3 test_notify.py

🧪 Автотесты

$ python3 test_notify.py

Ran 50 tests in 10.2s
OK

Всего тестов:  50
Прошло:        50
Провалено:     0
Ошибок:        0

Покрытие: логика агента, сессии, файлы данных, отправщик, все HTTP endpoints.


🖥 Кроссплатформенность

Протестировано на следующих дистрибутивах и окружениях рабочего стола:

ДистрибутивDEX11Wayland
ALT Linux p10 / p11 / СизифMATE✅ XWayland
RedOS 8.0.2MATE✅ XWayland
AstraLinux 1.8Fly
Ubuntu 22.04 / 24.04GNOME✅ XWayland
Debian 12XFCE / GNOME✅ XWayland
Win 10 \11

Wayland поддерживается через XWayland. Нативный Wayland (Layer Shell) в планах.


📋 Требования

КомпонентТребование
ОСALT Linux (Сизиф, p10, p11), RedOS 8.0.2, AstraLinux 1.8, Win 10-11 x64
Python3.8+
PyQt5apt-get install python3-module-pyqt5
DEMATE, KDE, XFCE, GNOME (X11 / XWayland)
СетьTCP порт 9988 (агент), 8080 (панель) можно поменять на свои

📄 Лицензия

MIT — используй свободно.

关于 About

Сервер уведомлений под Unix, отправка popup-сообщений, гибкая конфигурация.

语言 Languages

Python51.5%
HTML36.4%
Shell10.0%
Batchfile2.1%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
83
Total Commits
峰值: 39次/周
Less
More

核心贡献者 Contributors