Развертывание на Yandex Cloud
Облачная версия Notifly целиком работает на serverless-сервисах Yandex Cloud: ни одного «всегда включённого» VM нет, оплата идёт только за реальный трафик и хранение.
Этот документ описывает, как устроен развёрнутый стенд и как воспроизвести его в своём фолдере.
Архитектура
Заголовок раздела «Архитектура»┌──────────────────────────────────────────────────────────────────────────┐│ Клиент ││ (браузер · Android · desktop · MCP-агент · cron · веб-сайт · SMTP) │└──────┬──────────────┬──────────────┬───────────────┬────────────────────┘ │ HTTPS REST │ WSS │ POST /script │ SMTP ▼ ▼ ▼ ▼┌──────────────────────────────────────────────────────────────────────────┐│ Yandex Cloud API Gateway (notifly-ws-gateway) ││ ─ /api/* → notifly-api (REST) ││ ─ /ws → notifly-ws-handler (WebSocket) ││ ─ /script/* → notifly-api (публичные web-script триггеры) │└──────┬─────────────────────┬──────────────────────────┬─────────────────┘ │ │ │ ▼ ▼ ▼┌──────────────┐ ┌──────────────────┐ ┌────────────────────────────┐│ notifly-api │ │ notifly-ws- │ │ notifly-email ││ (golang121) │ │ handler │ │ (Mail Trigger → Email Inbox)│└─────┬────────┘ │ (golang123) │ └──────────┬─────────────────┘ │ └──────┬───────────┘ │ │ │ │ ▼ ▼ ▼┌──────────────────────────────────────────────────────────────────────────┐│ YDB Serverless (notifly-db) ││ users · applications · clients · messages · webhooks · email_inboxes ││ web_scripts · heartbeats · monitors · mcp_tokens · channel_shares │└──────────────────────────────────────────────────────────────────────────┘ ▲ ┌──────────────────────────┴──────────────────────────┐ │ Object Storage notifly-ws-connections │ │ connections/<id>.json — состояние WebSocket-сессий │ └──────────────────────────────────────────────────────┘
Timer triggers (cron `* * * * ? *`): • notifly-heartbeat — проверяет просроченные heartbeat-ы • notifly-monitor — выполняет активные проверки HTTP/TCP/TLS/...| Компонент | Ресурс | Тип |
|---|---|---|
notifly-api | Cloud Function | REST + Web Script triggers |
notifly-ws-handler | Cloud Function | WebSocket-обработчик |
notifly-email | Cloud Function | приём писем через Mail Trigger |
notifly-heartbeat | Cloud Function | таймер-проверка heartbeat-ов |
notifly-monitor | Cloud Function | таймер-проверка активных мониторов |
notifly-ws-gateway | API Gateway | единая входная точка |
notifly-db | YDB Serverless | вся бизнес-логика |
notifly-ws-connections | Object Storage | состояние WebSocket-соединений |
Что отсутствует в облаке
Заголовок раздела «Что отсутствует в облаке»При миграции с self-hosted-версии сознательно исключены:
- Go-плагины (
.so) — runtime YC Functions их не поддерживает. См. Введение в плагины для альтернатив. - OIDC — авторизация только локальная (BasicAuth + Bearer-токены).
- Embed UI — фронтенд деплоится отдельно в bucket
app.notifly.ru. - Image upload — заглушка (выгрузка картинок в Object Storage — в roadmap).
- Fractional sort keys для сообщений — упрощено до строкового поля.
Подготовка
Заголовок раздела «Подготовка»Понадобятся:
- Yandex Cloud аккаунт с фолдером;
ycCLI (установка);- сервисный аккаунт с ролями
serverless.functions.admin,ydb.admin,storage.editor,api-gateway.admin; - статические ключи доступа сервисного аккаунта (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) — для S3 из Cloud Function; - IAM-токен (короткоживущий, 12 часов) — для самого деплоя.
Все секреты держатся в .env в корне репозитория и подгружаются через
set -a; source .env; set +a перед деплой-скриптами.
Шаги деплоя
Заголовок раздела «Шаги деплоя»1. Создать YDB и таблицы
Заголовок раздела «1. Создать YDB и таблицы»yc ydb database create notifly-db --serverless# .env: YDB_DSN=grpcs://ydb.serverless.yandexcloud.net:2135/?database=...
cd server_yago run ./cmd/initdb # создаёт схему + admin/adminСкрипт initdb идемпотентный: повторный запуск не сломает существующие
таблицы и не пересоздаст admin-а.
2. Создать S3-bucket для WebSocket
Заголовок раздела «2. Создать S3-bucket для WebSocket»yc storage bucket create --name notifly-ws-connections --max-size 10737418243. Деплой REST + WebSocket + API Gateway
Заголовок раздела «3. Деплой REST + WebSocket + API Gateway»cd server_yabash deploy/deploy.shСкрипт:
- Собирает zip с
notifly-api, заливает как Cloud Function; - Собирает zip с
notifly-ws-handler, заливает как Cloud Function; - Применяет единую OpenAPI-спецификацию к API Gateway
(REST
/{proxy+}+ WebSocket/ws).
Если перевыкатить
ws-handler/deploy.shотдельно — он перезапишет API Gateway WS-only спекой; чтобы вернуть REST, перезапуститеserver_ya/deploy/deploy.sh.
4. Деплой таймер-функций (heartbeat, monitor)
Заголовок раздела «4. Деплой таймер-функций (heartbeat, monitor)»cd server_yabash deploy/deploy_heartbeat.shbash deploy/deploy_monitor.shКаждый скрипт создаёт Cloud Function и навешивает на неё timer-trigger
с расписанием * * * * ? * (раз в минуту). Внутри функции делается
SELECT WHERE next_check_at <= now() по соответствующему индексу YDB.
5. Деплой email-функции (опционально)
Заголовок раздела «5. Деплой email-функции (опционально)»cd server_yabash deploy/deploy_email.shПосле деплоя в консоли Mail Trigger привяжите функцию notifly-email
к нужному ящику (<local>+<alias>@<domain>). Пользовательские ящики
управляются через Email Inbox — алиасы хранятся в YDB,
а Mail Trigger маршрутизирует письма уже по subaddress-части.
6. Деплой фронтенда
Заголовок раздела «6. Деплой фронтенда»cd admin_yanpm cinpm run buildbash deploy.sh # синхронизирует dist/ в bucket app.notifly.ruСм. также инструкции по деплою admin — во многом этот шаг уже автоматизирован.
Smoke-тест
Заголовок раздела «Smoke-тест»После деплоя запустите:
bash server_ya/deploy/smoke_test.shpython3 server_ya/deploy/ws_test.pyПроверяется:
GET /health→{"health":"green","database":"green"}POST /auth/local/login(Basic admin/admin)POST /application+POST /message×NGET /message,GET /application/{id}/messagewss://.../ws?token=<C...>— handshake101,ping → pong,statusсconnection_idиsource_ip.
Эксплуатация
Заголовок раздела «Эксплуатация»| Действие | Где смотреть |
|---|---|
| Логи функций | yc logging read --group-id <log-group> --format json |
| Метрики функций | Yandex Cloud Console → Cloud Functions → метрики |
| Состояние таблиц YDB | YDB UI или yc ydb yql ... |
| Активные WS-соединения | aws s3 ls s3://notifly-ws-connections/connections/ |
Расходы
Заголовок раздела «Расходы»Стенд оптимизирован под FREE-tier:
- YDB Serverless — Request Units, без always-on storage; индексы на
next_check_atдают O(1)-проверки в heartbeat/monitor таймерах. - Cloud Functions — оплата по millisec-execution. Функции просыпаются
только при активности (
POST /message, ping, cron). - Object Storage — несколько байт на каждое WebSocket-соединение
(
connections/<id>.json~200 байт). - API Gateway — оплата по запросам.
При нулевой активности Notifly не съедает ничего, кроме платы за зарезервированное место в YDB (~10 ₽/месяц на free-tier).