umbot
    Preparing search index...

    Развертывание в продакшене

    После того как голосовой навык или чат-бот написан и протестирован локально, его нужно развернуть на сервере, чтобы платформы могли отправлять ему запросы. В этом руководстве мы рассмотрим полный цикл деплоя: от получения SSL-сертификата до настройки CI/CD.

    • Сервер с публичным IP-адресом
    • Доменное имя
    • SSL-сертификат (обязателен для Алисы, Маруси, Сбер SmartApp, Viber и других платформ)
    curl https://get.acme.sh | sh
    
    acme.sh --issue -d example.com -w /var/www/example
    

    Где:

    • example.com — ваш домен
    • /var/www/example — корневая директория сайта (должна быть доступна по HTTP для прохождения проверки)
    acme.sh --install-cert -d example.com \
    --key-file /etc/ssl/private/example.key \
    --fullchain-file /etc/ssl/certs/example.crt \
    --reloadcmd "sudo systemctl reload nginx"

    Добавьте в конфигурацию nginx:

    server {
        listen 443 ssl;
        server_name example.com;
    
        ssl_certificate /etc/ssl/certs/example.crt;
        ssl_certificate_key /etc/ssl/private/example.key;
    
        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $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;
        }
    }
    

    Перезагрузите nginx:

    sudo systemctl reload nginx
    

    Соберите проект:

    npm run build
    

    Запустите с помощью pm2 (рекомендуется для продакшена). Если pm2 не установлен, установите его:

    npm install -g pm2
    

    Запустите сам процесс:

    pm2 start dist/index.js --name "umbot-production"
    

    Для того чтобы после перезагрузки сервера приложение было доступно, выполните следующие команды:

    pm2 startup
    pm2 save

    Теперь ваш навык доступен по HTTPS и готов к подключению в консолях разработчика:

    • Яндекс.Диалоги
    • Сбер SmartApp (developers.sber.ru)
    • Маруся для разработчиков
    • Telegram BotFather, VK Callback API, Viber Bot Settings и др.
    bot.start('0.0.0.0', 3000);
    

    Смотри раздел: Универсальный webhook-обработчик в руководстве по платформам.

    При создании проекта через CLI с флагом --prod генерируется готовый Dockerfile.
    Соберите образ и запустите контейнер, передав токены через переменные окружения:

    docker build -t my-bot .
    docker run -p 3000:3000 -e ALISA_TOKEN=... -e TELEGRAM_TOKEN=... my-bot

    Если env в конфиге не настроен, фреймворк тихо подтянет известные переменные (TELEGRAM_TOKEN, ALISA_TOKEN, VK_TOKEN, ...) из окружения контейнера и дозаполнит ими токены — явно писать env: 'local' для этого не нужно. Если же env: 'local' указан, значения из окружения перезаписывают заданные токены.

    Шаблон .github/workflows/deploy.yml автоматически настраивает:

    • Сборку проекта,
    • Сборку Docker-образа,
    • Деплой на сервер через SSH.

    🔐 Безопасность: никогда не коммитьте .env в Git. Используйте GitHub Secrets.

    Для платформ без постоянного сервера (Алиса, Маруся, SmartApp) можно использовать serverless-функции.

    При создании проекта через CLI можно автоматически сгенерировать конфигурацию для Yandex Cloud Functions:

    npx umbot create from-flow flow.json --usecloud
    

    Это добавит в проект:

    • Экспорт handler в src/index.ts для обработки запросов Cloud Functions
    • scripts/deploy.js — деплой через yc CLI (запускается npm run deploy)
    • Справочный serverless.yml с конфигурацией функции (деплой его не читает — аргументы для yc собирает scripts/deploy.js)
    • Скрипты deploy и build в package.json

    Ручная настройка Cloud Function:

    import { Bot } from 'umbot';
    import { fullPlatforms } from 'umbot/plugins';

    const bot = new Bot();
    bot.use(fullPlatforms);
    bot.setAppConfig({ isLocalStorage: true });

    // Экспорт функции для Яндекс Cloud Functions
    export const handler = async (event: Record<string, unknown>) => {
    const content = typeof event.body === 'string' ? event.body : JSON.stringify(event.body ?? '');
    const headers = (event.headers ?? {}) as Record<string, unknown>;
    const result = await bot.webhookEvent(content, headers);
    return {
    statusCode: result.statusCode,
    headers: { 'Content-Type': 'application/json' },
    body: typeof result.body === 'string' ? result.body : JSON.stringify(result.body ?? ''),
    };
    };

    webhookEvent() — специальный метод для serverless-окружений: в отличие от run(), он сам определяет платформу по содержимому, проверяет подпись webhook (isCorrectQuery) и возвращает готовый HTTP-ответ { statusCode, body }. Именно этот код использует генератор from-flow --usecloud.

    В serverless isLocalStorage: true надёжно хранит данные только на Алисе, Марусе и SmartApp (состояние приходит в запросе). На Telegram/VK/MAX/Viber без DB-адаптера userData живёт в памяти экземпляра функции и теряется, когда вызов попадает в новый экземпляр, — для шагов диалога на чат-платформах подключите БД (например, MongoAdapter).

    Подробнее о serverless — в разделе Рецепты: Serverless.

    Перед запуском в продакшене убедитесь:

    • [ ] Сборка завершена успешноnpm run build без ошибок
    • [ ] Тесты пройденыnpm run test зелёный
    • [ ] Режим strict_prodbot.setAppMode('strict_prod')
    • [ ] Токены в переменных окружения — не в коде, не в .env в контейнере
    • [ ] MongoAdapter — вместо FileAdapter (FileAdapter хранит данные в памяти)
    • [ ] HTTPS настроен — обязателен для Алисы, Сбера, Viber
    • [ ] Webhook URL зарегистрирован — в консоли разработчика каждой платформы
    • [ ] error_log настроенbot.setAppConfig({ error_log: './logs' })
    • [ ] Preload выполнен — все медиафайлы предзагружены
    • [ ] rateLimiter подключенbot.use(rateLimiter())
    • [ ] PM2 или Docker — для автоматического перезапуска при падении
    • [ ] Мониторинг — логи доступны, метрики настроены