Перейти к содержимому

Хостинг

Бот — это постоянный процесс, который держит WebSocket-соединение с Gateway. Значит он должен где-то крутиться круглосуточно и автоматически подниматься после ребута / краша.

ВариантКогда подходитЦена
VPS (Timeweb, Selectel, Hetzner, DO)Один-два бота, полный контрольот 300 ₽/мес
Serverless (Cloudflare Workers, AWS Lambda)Боты без gateway — только webhooks или REST-cron. Полноценный бот там не живёт — они убивают долгие соединения$0-5/мес
PaaS (Railway, Fly.io, Render)Быстрый старт, деплой из git$5-10/мес
Своя инфра (Docker Swarm/K8s)Несколько ботов, мониторинг, роллинг-апдейтызависит

Самый надёжный дешёвый вариант. Арендуете VPS (1 CPU / 1 GB RAM хватит для любого одиночного бота), ставите Node и заводите systemd-юнит.

/opt/mybot/
├── src/
├── node_modules/
├── data/ ← SQLite здесь
├── .env ← FLOODILKA_BOT_TOKEN
└── package.json

Основные моменты:

  • Restart=always + RestartSec=5 — systemd поднимет бота после любого падения
  • NoNewPrivileges, PrivateTmp, ProtectSystem=strict — минимальная изоляция
  • Логи в /var/log/mybot.log — можно крутить logrotate’ом

Если вы уже живёте в docker — упаковываете бот в образ и деплоите:

FROM node:24-slim
WORKDIR /app
# Копируем только package.json и lockfile сначала — ради кеша
COPY package.json pnpm-lock.yaml* ./
RUN corepack enable && pnpm install --prod --frozen-lockfile
COPY src ./src
VOLUME ["/app/data"]
USER node
CMD ["node", "src/index.js"]

Быстро и без серверной возни:

  • Railwayrailway.app, подключаешь репозиторий, пушишь в main → деплой. FLOODILKA_BOT_TOKEN в Variables.
  • Fly.iofly deploy из CLI. fly secrets set FLOODILKA_BOT_TOKEN=....

Оба умеют persistent-volumes для SQLite-файла.

Что точно должно быть независимо от выбора

Заголовок раздела «Что точно должно быть независимо от выбора»

Бот упадёт. WebSocket разорвётся. Процесс закрешится. Любой хостинг-выбор должен давать автоматический restart — systemd, Docker restart: always, Railway auto-restart.

Не коммитьте .env в git. Токен живёт в secrets-управлении хостинга (systemd EnvironmentFile, Docker compose env, Railway Variables).

Если бот пишет в БД — убедитесь что volume переживает рестарт контейнера. Типовой просчёт: Docker-контейнер без volume → SQLite-файл стирается при каждом docker-compose up.

Минимум — пишите console.log со временем в stdout. Systemd/Docker сами сохранят. Для product-grade — см. Мониторинг.

function shutdown() {
console.log('shutting down...');
ws?.close(1000, 'shutdown');
db?.close();
process.exit(0);
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);

Без этого после systemctl stop процесс убьётся через KillMode=mixed и SQLite может остаться в неконсистентном состоянии.