Деплой на Timeweb Cloud Apps: гайд для Node-проекта
Timeweb Cloud — российский хостер с понятной панелью и приличной инфраструктурой. У них есть отдельный продукт Cloud Apps: PaaS-вариант, в котором ты привязываешь git-репозиторий, и платформа сама делает билд и деплой. Я катал на нём пару проектов; делюсь рабочей схемой и тонкостями.
Контекст: Node 20, TypeScript, бекенд на Express/Fastify или Astro SSR. Cloud Apps также отлично жуёт Next.js, статические сайты и Python-приложения.
Что такое Cloud Apps
Cloud Apps — это «как Vercel, только в Timeweb». Ты подключаешь репозиторий из GitHub/Gitlab, платформа сама собирает приложение и поднимает его. Не нужен VPS, не нужны systemd-юниты, не нужен ручной nginx. Платформа сама делает SSL, авто-перезапуск, деплой по push.
Что внутри:
- Cloud Apps крутит приложения в контейнерах с автоматическим масштабированием (вертикальным).
- Поддержка Node.js, Python, PHP, Go, Java, Docker.
- Бесплатный TLS на стандартный поддомен
*.twc1.net, привязка собственного домена. - Биллинг по часам работы конфигурации.
Когда подходит Cloud Apps
- Простые Node/Next-приложения без долгих фоновых задач.
- Маленькие команды, которые не хотят возиться с VPS.
- Прототипы и MVP, которые надо быстро задеплоить и показать.
Когда не подходит:
- Нужны фоновые воркеры, которые работают часами.
- Нужны WebSocket-соединения с долгой жизнью.
- Сложная сетевая конфигурация (private networks, отдельные подсети).
- Нужна полная контроль над окружением: тогда лучше обычный Cloud Server.
Подготовка проекта
Cloud Apps определяет тип приложения по содержимому репозитория. Для Node-проекта он смотрит на package.json и запускает то, что в scripts.start.
В package.json:
{
"name": "myapp",
"version": "1.0.0",
"engines": {
"node": ">=20.0.0 <21.0.0"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "node dist/server.js"
},
"dependencies": {
"express": "^4.21.0",
"pg": "^8.13.0"
},
"devDependencies": {
"typescript": "^5.4.0",
"@types/node": "^20.0.0"
}
}В engines.node указывай нужную версию. Cloud Apps подберёт ближайшую, доступную в их образах. Если ты на 22 — пиши 22, на 20 — 20.
На сервере приложение должно слушать порт из переменной PORT:
const port = Number(process.env.PORT ?? 3000);
app.listen(port, '0.0.0.0', () => console.log(`listening on ${port}`));Платформа подкидывает PORT динамически и пробрасывает с публичного 80/443 на этот порт.
Создание приложения
В панели Timeweb Cloud:
- Cloud Apps → Создать приложение.
- Подключить GitHub или Gitlab. Если репо приватное, авторизуешься через OAuth.
- Выбрать репозиторий и ветку (обычно main или master).
- Указать путь к проекту (если в репо несколько проектов в подкаталогах — здесь монорепы поддерживаются ограниченно).
- Выбрать тип фреймворка: Node.js.
- Выбрать конфигурацию (CPU/RAM). Стартовая 1 vCPU / 1 GB обычно хватает на простое API.
На этом шаге можно указать билд- и старт-команды, если автодетект промахнулся:
Build command: pnpm install --frozen-lockfile && pnpm build
Start command: node dist/server.jsПо умолчанию платформа берёт npm install и npm start. Если у тебя pnpm/yarn, обязательно перепиши.
Переменные окружения
В разделе «Окружение» приложения добавляешь все нужные переменные: DATABASE_URL, JWT_SECRET, ключи API. Они доступны в process.env на этапе билда и в рантайме.
Важный момент: в Cloud Apps секреты хранятся в зашифрованном виде, но они не защищены так, как менеджеры секретов уровня Vault. Для критически чувствительных данных я бы хранил их в Yandex Lockbox или отдельном self-hosted Vault и тащил оттуда при старте.
База данных
Cloud Apps не предоставляют собственную БД, но в Timeweb Cloud есть Managed Postgres, MySQL, Redis. Заводишь рядом с приложением, настраиваешь private network между ними, в переменные окружения подсовываешь connection string.
Например:
DATABASE_URL=postgres://user:pass@<managed-pg-host>:5432/dbname?sslmode=requireЕсли кладёшь рядом Redis для очередей — тот же подход с приватным IP в одной сети.
Свой домен
В разделе «Домены» приложения добавляешь домен, ставишь A-запись на IP, который покажет панель. Платформа сама выпишет Let's Encrypt-сертификат и будет его обновлять. У меня привязка домена обычно занимает минут 10–15 после прогрева DNS.
Для wildcard-сертификата нужен DNS-вызов; стандартного wildcard через панель нет, но app.example.ru и www.example.ru делаются легко.
Логи и мониторинг
В панели Cloud Apps есть вкладки:
- Логи: stdout/stderr приложения. На простых сценариях достаточно. На больших объёмах фильтрация и поиск ограничены, я отправляю важные логи во внешний агрегатор (Loki, ClickHouse) через push.
- Метрики: CPU, RAM, RPS, время ответа. Базовые графики, для подробной аналитики — добавляй OpenTelemetry или собственные метрики.
- События: рестарты, деплои, ошибки билда. Полезно для понимания «почему вдруг упало в 3 ночи».
Авто-деплой
По умолчанию Cloud Apps подписывается на webhook git-репозитория и при push в выбранную ветку запускает билд и деплой. Это удобно: коммит в main → через 2–3 минуты приложение обновлено.
Если хочется деплоить только из CI после прогона тестов — отключай авто-деплой и используй webhook от своего Gitea/GitHub Actions, который дёргает Cloud Apps API.
curl -X POST https://api.timeweb.cloud/api/v1/apps/<app_id>/deploy \
-H "Authorization: Bearer $TIMEWEB_TOKEN"Подводные камни
Долгий билд
На крупных проектах билд может идти 5–10 минут, и за это время Cloud Apps удерживает рабочий контейнер. Если ты деплоишь часто, имеет смысл оптимизировать билд: pnpm cache, меньше ненужных зависимостей, prebuilt artifacts.
Memory leak
Cloud Apps делает auto-restart, если контейнер упирается в лимит памяти. Это спасает, но скрывает реальную проблему. Если ты замечаешь периодические рестарты — это сигнал поискать утечку: heapdump, clinic.js, отдельный staging для нагрузочного теста.
Cron-задачи
Долго живущие cron-задачи в одной инстанции с веб-сервером — плохая идея. Если приложение перезапустится во время cron, ты пропустишь работу. Я разделяю: для cron-задач отдельное приложение или внешний планировщик, который зовёт endpoint на основном.
Holding state
На Cloud Apps инстанс может перезапускаться: после деплоя, при смене конфигурации, при обновлении платформы. Любое состояние в памяти потеряется. Кэши в памяти держи коротко, постоянное хранение — в БД или Redis.
Что я в итоге получаю
- API на ноде с git-deploy: коммит → продакшен.
- HTTPS из коробки.
- Базовые метрики и логи в панели.
- Не нужен VPS-уход: апдейты безопасности не моя забота.
Cloud Apps — приличный вариант для небольших Node-приложений, особенно если у тебя нет devops-ресурса. На моих проектах с трафиком до сотен RPS работает стабильно. Когда нужно масштабироваться или появляются нестандартные требования — переезд на Cloud Server с тем же Timeweb или на Yandex Cloud делается за пару дней. Главное — не закладываться на специфические фишки одной платформы и держать код переносимым.