Каждый системный администратор и разработчик сталкивается с задачей оперативной доставки уведомлений: завершился ли ночной бэкап баз данных, упал ли Nginx, заблокировал ли CrowdSec атакующего или заканчивается место на диске VDS. Долгие годы стандартом де-факто оставались боты в Telegram или сторонние платформы вроде Pushover.
Однако в современных реалиях публичные платформы несут серьезные риски: Telegram Bot API подвержен задержкам, сетевым сбоям, блокировкам и спам-фильтрам, а Pushover стал платным с фиксированной стоимостью за каждое устройство. Отправка писем по SMTP через локальный почтовик часто натыкается на попадание в спам-листы или доставляется с задержкой в десятки минут.
Идеальным решением в 2026 году стал Ntfy — легковесный open-source сервис push-уведомлений на языке Go (свыше 22 000 звёзд на GitHub), который поднимается на собственном сервере в Docker Compose за 10 минут, потребляет символические 15–25 МБ оперативной памяти и позволяет отправлять алерты на мобильный телефон буквально одной строчкой curl из любого скрипта.
1. Почему Telegram и Pushover проигрывают Ntfy для алертинга
В отличие от тяжеловесных мессенджеров, архитектура Ntfy спроектирована специально для системных оповещений по протоколам HTTP/HTTPS, WebSockets и Server-Sent Events (SSE). Для отправки пуша не нужно регистрировать ботов, получать chat_id, генерировать длинные токены или парсить сложные JSON-ответы.
| Критерий сравнения | Telegram Bot API | Pushover | Self-Hosted Ntfy |
|---|---|---|---|
| Сложность отправки | Сложный URL, экранирование Markdown | REST API с API-токенами | curl -d "Текст" url/topic |
| Приоритеты и тревога | Только звук вкл/выкл | Поддерживаются (Emergency) | 5 уровней (пробивает режим «Не беспокоить») |
| Кнопки действий (Actions) | Inline-кнопки требуют серверного бота | Ограниченные ссылки | Прямой запуск HTTP-запросов и ссылок |
| Приватность данных | Логи на серверах третьих лиц | Закрытый проприетарный сервис | 100% контроль на вашем VDS |
| Стоимость | Бесплатно (с лимитами запросов) | $5 за каждое устройство | Бесплатно, без ограничений |
💡 Совет инженера:
В Ntfy каждый топик является обычной URL-строкой, например https://ntfy.example.com/alerts-prod. Если подписаться на этот топик в мобильном приложении, любое обращение методом POST или PUT мгновенно превратится во всплывающее push-уведомление на экране телефона без задержек.
2. Архитектура Ntfy и системные требования к серверу
Серверная часть Ntfy распространяется в виде единого скомпилированного бинарного файла на Go и официального контейнера binwiederhier/ntfy. Сервер не требует отдельных тяжелых СУБД вроде MySQL или PostgreSQL: для хранения очереди неотправленных сообщений и учетных записей используется встроенный легковесный SQLite (файлы cache.db и auth.db).
Для развертывания сервера подойдет любой базовый VDS на Linux (Ubuntu 22.04 / 24.04 LTS или Debian 12). Перед началом настройки убедитесь, что доменное имя (например, ntfy.yourdomain.ru) направлено на публичный IP-адрес вашего сервера через DNS А-запись. Выяснить текущий IP сервера можно встроенной утилитой SysKit Мой IP.
3. Развертывание Ntfy в Docker Compose с защитой портов
Создадим рабочую директорию проекта на сервере и выставим надежные права доступа. Согласно правилам системной безопасности, служебный порт контейнера связывается строго с локальным адресом 127.0.0.1, чтобы служба не была открыта в интернет в обход фаервола UFW:
sudo mkdir -p /opt/ntfy/{config,cache,auth}
sudo chown -R 1000:1000 /opt/ntfy
cd /opt/ntfy
Создадим конфигурационный файл сервера /opt/ntfy/config/server.yml. Обратите внимание на параметр behind-proxy: true — без него Ntfy будет видеть только локальный IP обратного прокси, что приведет к ложному срабатыванию rate limiting для всех клиентов:
# /opt/ntfy/config/server.yml
base-url: "https://ntfy.example.com"
listen-http: ":80"
behind-proxy: true
# Базы данных SQLite для кэша и пользователей
cache-file: "/var/cache/ntfy/cache.db"
# Срок хранения неотправленных сообщений (по умолчанию 12h, можно увеличить до 7d)
cache-duration: "7d"
auth-file: "/var/lib/ntfy/auth.db"
# Политика безопасности: закрываем топики от публики
auth-default-access: "deny-all"
enable-login: true
# Шлюз для пробуждения iOS-устройств через Apple APNs
upstream-base-url: "https://ntfy.sh"
Теперь подготовим манифест compose.yaml. Мы задаем лимиты памяти mem_limit: 256m и процессора cpus: 0.5 для предотвращения нештатных утечек в соответствии с рекомендациями Docker Compose Production Limits:
# /opt/ntfy/compose.yaml
services:
ntfy:
image: binwiederhier/ntfy:latest
container_name: ntfy
restart: unless-stopped
command: serve
mem_limit: 256m
cpus: 0.5
ports:
- "127.0.0.1:8080:80"
volumes:
- ./config/server.yml:/etc/ntfy/server.yml:ro
- ./cache:/var/cache/ntfy
- ./auth:/var/lib/ntfy
environment:
- TZ=Europe/Moscow
Запускаем контейнер в фоновом режиме:
docker compose up -d
Проверить локальный ответ сервера можно командой: curl -I http://127.0.0.1:8080/v1/health. Сервер должен вернуть статус HTTP/1.1 200 OK.
4. Настройка Reverse Proxy: Caddy 2 и Nginx с автопродлением SSL
Для безопасной передачи push-сообщений и работы мобильных приложений сервер обязан работать по защищенному протоколу HTTPS. Проверить статус открытости портов 80 и 443 можно с помощью утилиты SysKit Проверка портов онлайн.
Рассмотрим два самых надежных варианта настройки веб-сервера:
Вариант А: Быстрая настройка через Caddy 2 (Рекомендуется)
Веб-сервер Caddy 2 из коробки поддерживает автоматический выпуск TLS-сертификатов Let's Encrypt и потоковые протоколы. Добавьте в /etc/caddy/Caddyfile блок:
ntfy.example.com {
reverse_proxy 127.0.0.1:8080
}
Примените конфигурацию: sudo systemctl reload caddy. Caddy самостоятельно выпустит сертификат, настроит HTTP/2 и обеспечит бесперебойную передачу WebSockets без ручного вмешательства.
Вариант Б: Полная конфигурация Nginx для HTTPS и WebSockets
Если на вашем сервере используется Nginx, важно соблюдать два инженерных правила:
- Динамический апгрейд соединения: Нельзя жестко прописывать
proxy_set_header Connection "upgrade"для всех запросов, иначе обычные POST-публикации будут некорректно заявлять об апгрейде до сокетов. Используется стандартный маппинг$connection_upgrade. - Полноценный блок HTTPS: Конфигурация должна явно описывать защищенный виртуальный хост на порту 443 с SSL-сертификатами и редирект с порта 80.
Сначала убедитесь, что в файле /etc/nginx/nginx.conf внутри секции http { ... } присутствует маппинг переменной $connection_upgrade:
# /etc/nginx/nginx.conf (внутри блока http)
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
Выпустим первичный SSL-сертификат Let's Encrypt с помощью Certbot:
sudo certbot certonly --nginx -d ntfy.example.com
Теперь создадим полноценный production-конфиг /etc/nginx/sites-available/ntfy.conf с TLS-терминацией и проксированием в контейнер:
# /etc/nginx/sites-available/ntfy.conf
server {
listen 80;
server_name ntfy.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name ntfy.example.com;
# Пути к сертификатам Let's Encrypt
ssl_certificate /etc/letsencrypt/live/ntfy.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ntfy.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
# Корректный апгрейд до WebSockets только при наличии заголовка Upgrade
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Отключение буферизации для мгновенной доставки Server-Sent Events (SSE)
proxy_buffering off;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
Активируйте виртуальный хост и проверьте синтаксис Nginx:
sudo ln -s /etc/nginx/sites-available/ntfy.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Проверьте корректность цепочки шифрования через SysKit Проверка SSL-сертификата.
5. Закрытие сервера от публики: пользователи, токены и права доступа (ACL)
Поскольку мы указали в server.yml директиву auth-default-access: "deny-all", сервер полностью защищен от сторонних глаз: читать и публиковать сообщения без авторизации невозможно.
Создадим учетную запись главного администратора внутри запущенного контейнера:
docker exec -it ntfy ntfy user add --role=admin alex
Команда запросит пароль для пользователя. Для создания стойких учетных данных воспользуйтесь инструментом Генератор надежных паролей SysKit.
⚠️ Важное предупреждение:
Никогда не используйте основной пароль администратора внутри bash-скриптов и cron-задач! Если скрипт случайно утечет в лог или открытый репозиторий, посторонние получат контроль над сервером. Для автоматизации выпускаются изолированные токены доступа (Access Tokens).
Сгенерируем сервисный токен для автоматических скриптов с ограничением прав на запись в конкретный топик. В сценариях с повышенными требованиями безопасности токену можно задать срок жизни через флаг --expires (например, 90 дней), либо опустить его для создания бессрочного токена:
# Создаем служебного пользователя для скриптов
docker exec -it ntfy ntfy user add backup-bot
# Выдаем права только на запись в топик backups
docker exec -it ntfy ntfy access backup-bot "backups" write-only
# Генерируем сервисный токен со сроком действия 90 дней
docker exec -it ntfy ntfy token add --expires=90d backup-bot
Команда сгенерирует токен вида tk_a1b2c3d4e5f6.... Этот токен будет безопасно передаваться в HTTP-заголовке Authorization: Bearer tk_....
6. Отправка алертов через curl: теги, приоритеты, кнопки действий и вложения
Отправка уведомлений в Ntfy невероятно проста: базовый алерт отправляется обычной передачей тела запроса методом POST. При этом сервер поддерживает расширенные HTTP-заголовки, кардинально меняющие поведение пуша на смартфоне:
| HTTP-заголовок | Назначение | Пример значения |
|---|---|---|
Title: |
Заголовок уведомления жирным шрифтом | Резервное копирование VDS |
Priority: |
Важность (1–5: min, low, default, high, urgent) | urgent (пробивает беззвучный режим) |
Tags: |
Эмодзи и метки классификации через запятую | warning,rotating_light,fire |
Click: |
URL для перехода при нажатии на уведомление | https://grafana.example.com |
Actions: |
Интерактивные кнопки прямо в уведомлении | view, Открыть панель, https://... |
Рассмотрим пример отправки тревожного оповещения о критическом сбое базы данных с интерактивной кнопкой перехода:
curl -H "Authorization: Bearer tk_xxxxxxxxxx" \
-H "Title: Сбой подключения к PostgreSQL" \
-H "Priority: urgent" \
-H "Tags: rotating_light,database,skull" \
-H "Click: https://syskit.ru/port-checker" \
-H "Actions: view, Проверить доступность портов, https://syskit.ru/port-checker, clear=true" \
-d "Пул соединений переполнен! Служба PostgreSQL не отвечает более 60 секунд на VDS-01." \
https://ntfy.example.com/backups
Такое уведомление сразу зазвучит тревожной сиреной на телефоне, отобразит иконку черепа и мигалки, а по клику на кнопку откроет диагностический инструмент.
7. Готовые скрипты: мониторинг сбоев VDS и уведомления о бэкапах
Встроим Ntfy в реальные рабочие процессы системного администратора. Ниже представлен надежный bash-скрипт резервного копирования баз данных, отправляющий отчеты об успехе или немедленный алерт при возникновении любой ошибки.
Создадим файл /usr/local/bin/backup-and-notify.sh:
#!/usr/bin/env bash
set -Eeuo pipefail
# Конфигурация Ntfy
NTFY_SERVER="https://ntfy.example.com"
NTFY_TOPIC="backups"
NTFY_TOKEN="tk_your_secret_token_here"
# Универсальная функция отправки алертов
send_push() {
local title="$1"
local message="$2"
local priority="$3"
local tags="$4"
curl -fsSL -H "Authorization: Bearer ${NTFY_TOKEN}" \
-H "Title: ${title}" \
-H "Priority: ${priority}" \
-H "Tags: ${tags}" \
-d "${message}" \
"${NTFY_SERVER}/${NTFY_TOPIC}" > /dev/null || true
}
# Перехват непредвиденных сбоев скрипта
trap 'send_push "❌ Авария скрипта бэкапа" "Скрипт аварийно прерван на строке $LINENO!" "urgent" "fire,warning"' ERR
echo "Запуск создания резервной копии..."
START_TIME=$(date +%s)
# Пример операции бэкапа: архивация рабочей директории
BACKUP_FILE="/tmp/backup-$(date +%Y%m%d).tar.gz"
tar -czf "${BACKUP_FILE}" /opt/ntfy/config
DURATION=$(( $(date +%s) - START_TIME ))
FILE_SIZE=$(du -h "${BACKUP_FILE}" | cut -f1)
# Уведомление об успешном завершении
send_push "✅ Бэкап VDS успешно создан" "Архив: ${FILE_SIZE}, время: ${DURATION} сек. Файл сохранен в хранилище." "low" "white_check_mark,floppy_disk"
# Удаление временного архива
rm -f "${BACKUP_FILE}"
Выдаем права на исполнение только суперпользователю: sudo chmod 750 /usr/local/bin/backup-and-notify.sh. Теперь при добавлении задачи в cron любые инциденты будут немедленно приходить на ваш смартфон.
Аналогичным образом Ntfy легко связывается с утилитами умного шифрованного бэкапа Restic и Autorestic на VDS или мониторингом серверов в панели Beszel.
8. Настройка мобильных приложений для Android и iOS
Для приема оповещений установите официальный клиент Ntfy на смартфон. Архитектура доставки уведомлений на мобильных платформах имеет важные технические различия:
- Android: Клиент доступен в Google Play и каталоге F-Droid. На Android приложение может постоянно удерживать прямое фоновое WebSocket-соединение с вашим VDS либо использовать открытый стандарт UnifiedPush. Это позволяет получать уведомления моментально и автономно, вообще не обращаясь к серверам Google (Google Play Services).
- iOS (iPhone / iPad): Операционная система Apple жестко запрещает сторонним приложениям держать постоянные фоновые сетевые соединения для экономии батареи. Доставка пушей на iOS реализована следующим образом:
- При публикации сообщения ваш VDS отправляет служебный запрос
poll_requestна шлюзntfy.sh(параметрupstream-base-url: "https://ntfy.sh"). Запрос содержит только хэш топика и системный ID сообщения. - Шлюз
ntfy.shчерез Firebase (FCM) и Apple Push Notification service (APNs) передает сигнал «пробуждения» на ваш iPhone. - Приложение Ntfy просыпается в фоне и напрямую с вашего VDS скачивает тело сообщения, заголовок и вложения.
- При публикации сообщения ваш VDS отправляет служебный запрос
Шаги подключения мобильного клиента к собственному серверу:
- Откройте приложение Ntfy и перейдите в Настройки (Settings) → Сервер по умолчанию (Default server).
- Укажите адрес вашего сервера:
https://ntfy.example.com. - В разделе Управление аккаунтами (Manage accounts) нажмите «Добавить пользователя» и укажите ваш логин и пароль администратора.
- Нажмите кнопку
+на главном экране и введите имя топика (например,backups).
После этого проверьте работу из терминала VDS — push-уведомление появится на экране смартфона за долю секунды!
9. Резюме и чек-лист готовности
Развертывание собственного сервера Ntfy решает ключевую проблему системного администрирования: получение надежного, мгновенного и независимого от сторонних мессенджеров канала критических оповещений.
Готовы развернуть собственный сервер уведомлений?
Для надежного мониторинга и круглосуточной доставки алертов Ntfy требуется стабильный виртуальный сервер с быстрым NVMe-накопителем, статическим IP-адресом и аптаймом 99.98%.
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud — Быстрые NVMe VDS
Идеальная платформа для self-hosted сервисов и легковесных контейнеров: порты 80/443 открыты, мгновенный аптайм и канал до 1 Гбит/с.
Selectel — Надежные облачные серверы
Корпоративная инфраструктура уровня Tier III с гарантированной доступностью 99.98% для критически важных серверов мониторинга и алертов.
Beget — Простота и стабильность
Удобная панель управления с готовым Docker в один клик, автоматическая сетевая маршрутизация и круглосуточная поддержка.