Hospedar bot do Telegram ou Discord 24/7 no Brasil (Node e Python)
Guia prático para hospedar bot do Telegram ou Discord 24/7 no Brasil: rode como worker no Upuai com git push, token em variável de ambiente, logs por processo e custo em Real, começando grátis.
Todo bot nasce igual: funciona perfeitamente no node bot.js do seu terminal e morre no momento em que você fecha o notebook. Hospedar um bot do Telegram ou Discord 24/7 é o passo que separa o script de fim de semana de um serviço que responde às 3 da manhã, quando você não está olhando.
O caminho clássico era ruim dos dois lados: VPS na mão (SSH, systemd ou PM2, plantão quando cai) ou uma PaaS gringa com fatura em dólar mais IOF por um processo que consome quase nada. E o velho atalho gratuito, que fazia o bot hibernar quando ninguém usava, deixou de existir faz tempo.
Este guia mostra o caminho que a gente considera o mais direto hoje: o bot como processo worker no Upuai, no ar com um git push, com o token guardado em variável de ambiente, logs por processo e a fatura em Real. Funciona igual para Node e Python, Telegram e Discord, e o plano Free não pede cartão. Todos os comandos e limites citados são os reais da plataforma, hoje.
Por que um bot não é um site (e por que isso muda o deploy)
A maioria dos tutoriais de deploy assume um app web: um servidor HTTP que escuta numa porta e responde requisições. Um bot típico é o oposto disso.
No modo mais comum (long polling), o bot abre a conexão de saída: ele fica perguntando aos servidores do Telegram ou mantendo o gateway do Discord aberto, esperando eventos. Não há porta pública, não há endpoint HTTP, não há health check pra responder. É um processo de longa duração que precisa de exatamente duas coisas: ficar de pé o tempo todo e voltar sozinho se cair.
Plataformas serverless e de site estático brigam com esse modelo, porque foram desenhadas pra função que executa e encerra. O que um bot pede é o modelo oposto: um container de longa duração, o mesmo que descrevemos no guia de deploy de Next.js para SSR.
No Upuai, isso tem nome: processo do tipo worker. Você declara num arquivo de config que o seu comando não é um servidor web, e a plataforma roda o processo num Kubernetes gerenciado, sem esperar porta nem health check HTTP. Se o processo morrer, o orquestrador o recoloca de pé. É essa declaração de uma linha que faz o deploy de bot deixar de ser gambiarra.
O que você precisa antes de começar
- O código do bot num repositório GitHub ou GitLab. Node ou Python, qualquer biblioteca (grammY, Telegraf, discord.js, python-telegram-bot, discord.py).
- O token do bot: no Telegram, o @BotFather te dá um com o comando
/newbot; no Discord, ele sai do Developer Portal, na aba Bot da sua aplicação. Guarde e nunca commite. - Uma conta no Upuai: o plano Free não pede cartão. Crie em app.upuai.com.br (login por GitHub OAuth ou código por e-mail).
Não precisa de Dockerfile nem YAML. O build usa o railpack, builder zero-config que detecta Node pelo package.json e Python pelo requirements.txt ou pyproject.toml.
Passo a passo: bot de Telegram em Node, no ar
Um bot mínimo com grammY, em bot.js:
import { Bot } from 'grammy'
const bot = new Bot(process.env.BOT_TOKEN)
bot.command('start', (ctx) => ctx.reply('No ar, 24/7.'))
bot.on('message', (ctx) => ctx.reply('Recebi: ' + ctx.message.text))
bot.start() // long polling: o bot abre a conexão, nenhuma porta necessária
O package.json só precisa da dependência e de nada especial de infra. O pulo do gato é o upuai.toml na raiz do repositório, declarando o processo como worker:
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json
[processes.bot]
command = "node bot.js"
# type é opcional: qualquer nome que não seja web/clock/cron/release é inferido como worker
Com o arquivo no repo, o deploy é o fluxo padrão da plataforma. Pelo dashboard: novo projeto em app.upuai.com.br, autorize o GitHub App, escolha o repositório e pronto. Ou pela CLI:
# macOS / Linux
brew tap saiph-ti/upuai-cli
brew install upuai
upuai login # uma vez por máquina (GitHub OAuth ou: upuai login --email)
upuai init \
--name meu-bot \
--repo sua-org/meu-bot \
--branch main \
--framework Node.js \
--yes
upuai deploy --wait --yes
O --wait bloqueia até o deploy chegar num status final. A partir daqui, todo git push na branch conectada rebuilda e sobe o bot sozinho, e o upuai rollback --to <id> --yes reverte se uma versão nova quebrar.
Ainda sem repositório git, ou querendo testar código local não commitado? O upuai up empacota o diretório atual e deploya direto (excluindo .git, node_modules e .env* automaticamente).
E em Python: bot de Discord com discord.py
O mesmo fluxo, trocando o runtime. Um bot mínimo em bot.py:
import os
import discord
intents = discord.Intents.default()
intents.message_content = True # habilite também no Developer Portal (intent privilegiada)
client = discord.Client(intents=intents)
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith("!ping"):
await message.channel.send("pong")
client.run(os.environ["BOT_TOKEN"])
Com discord.py no requirements.txt, o railpack detecta o projeto Python sem config extra. O upuai.toml muda uma linha:
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json
[processes.bot]
command = "python bot.py"
E o init recebe --framework Python em vez de Node.js. O resto (deploy, logs, variáveis) é idêntico. Detalhe do Discord: a intent de conteúdo de mensagem é privilegiada, então além da linha no código você precisa ativá-la na aba Bot do Developer Portal, senão o bot conecta mas não lê as mensagens.
O token em variável de ambiente, nunca no código
Token de bot em repositório é a forma mais rápida de ver seu bot respondendo coisas que você não escreveu. O caminho certo é variável de ambiente, e no Upuai isso é um comando:
upuai vars set BOT_TOKEN=123456:ABC-xxxxxxxx --yes
Três detalhes que valem saber:
- Escopo de runtime pra segredos:
upuai variables set BOT_TOKEN=xxx --scope runtimemantém o token fora da imagem de build. Pra bot, é o escopo certo. - Variáveis valem a partir do próximo deploy. Setou e quer aplicar agora?
upuai redeploy --yes. .envfora do deploy: noupuai up, o empacotamento exclui.env*automaticamente. No fluxo git, quem protege é o seu.gitignore: se o.envfoi commitado, ele está no repositório que o deploy puxa. Não commite.env.
Se o bot usa banco (fila de jobs, memória de conversa, contadores), upuai add --type database --engine postgres provisiona um Postgres gerenciado no mesmo projeto e injeta a DATABASE_URL no processo automaticamente. O mesmo vale pra Redis com --engine redis.
Polling ou webhook?
Os dois modos funcionam na plataforma, e a escolha muda a config:
- Long polling (recomendado pra começar): o bot puxa as atualizações. Não precisa de URL pública, não precisa de porta, roda como o worker que configuramos acima. É o modo dos exemplos deste guia e o mais simples de operar.
- Webhook: o Telegram (ou o Discord, em interações via HTTP) chama uma URL sua a cada evento. Nesse caso o bot é um servidor web: declare o processo como
web(nome[processes.web]), escute na porta que a plataforma injeta emPORT, e a URL públicahttps://seu-bot.upuai.com.brsai do deploy com SSL automático. Webhook faz sentido em volume alto de mensagens ou quando você quer o mesmo serviço respondendo HTTP pra outras coisas.
A regra prática: comece com polling; migre pra webhook quando tiver motivo medido, não por moda.
Logs, restart e o dia a dia do bot no ar
Bot 24/7 sem visibilidade é bot que você descobre que caiu pelo grupo reclamando. O dia a dia na CLI:
upuai ps # processos do serviço (tipo, réplicas, comando)
upuai logs -n 200 # últimas 200 linhas de runtime
upuai logs --process bot # filtra só o processo do bot
upuai logs --build # log do build (quando o deploy falha)
upuai restart --process bot --yes # reinicia só o bot
Dois avisos de quem já operou bot em produção:
- Não escale bot de polling pra mais de 1 instância. Duas réplicas com o mesmo token brigam: o Telegram rejeita conexões simultâneas de
getUpdatese o Discord entrega os mesmos eventos duas vezes, ou seja, resposta duplicada no chat. Uma instância de worker aguenta muito bot; se um dia precisar de mais, o caminho é webhook ou sharding, não réplica de polling. - Deixe o processo morrer em caso de erro fatal. Não engula exceções pra “manter vivo”: o processo que encerra com erro é reposto pelo orquestrador, e o motivo fica registrado no log. Um
try/catchglobal que silencia erro só transforma um crash visível num zumbi invisível.
Quanto custa rodar um bot 24/7 (em Real)
A conta é em Real, com pagamento por Pix ou boleto, sem cartão internacional, sem IOF, sem câmbio na fatura (a matemática de por que isso pesa está no comparativo de custo de cloud no Brasil).
| Plano | Preço/mês | Projetos | Serviços/projeto | Processos/serviço | Logs |
|---|---|---|---|---|---|
| Free | R$ 0 | 1 | 2 | 2 | 12h |
| Starter | R$ 19 | 2 | 3 | 3 | 24h |
| Pro | R$ 99 | 5 | 5 | 5 | 72h |
No anual, os planos pagos saem por 10 vezes o valor mensal, o que dá 2 meses grátis.
Pra um bot, na prática:
- Free cobre o bot inteiro: o bot é 1 serviço, e ainda sobra espaço pra 1 banco gerenciado (Postgres ou Redis) no mesmo projeto. Bot típico é leve, e o processo worker roda confortável nos recursos padrão do plano.
- Starter (R$ 19) entra quando você quer retenção maior de log, um segundo projeto ou um terceiro processo no mesmo serviço (bot + painel web +
clockde tarefas agendadas, por exemplo). - Pro (R$ 99) é território de quem opera vários bots ou bots com serviços em volta (painel web, API, filas).
Se você está comparando com as opções gringas de sempre, fizemos essa análise em detalhe em alternativa ao Railway no Brasil.
FAQ
O bot dorme ou hiberna no plano Free?
O modelo da plataforma é container de longa duração: o processo worker fica de pé, não é função serverless que congela entre invocações nem dyno que hiberna por inatividade. E se o processo cair, o Kubernetes gerenciado o recoloca no ar.
Preciso de Dockerfile?
Não. O railpack detecta Node pelo package.json e Python pelo requirements.txt/pyproject.toml e builda o container sozinho. Se você já tem um Dockerfile e prefere usá-lo, dá pra trocar o builder pra dockerfile no upuai.toml, mas pra bot é quase sempre desnecessário.
Posso rodar o bot e um site no mesmo repositório?
Sim, e é um caso clássico de multi-processo: declare [processes.web] pro site e [processes.bot] pro bot no mesmo upuai.toml. Um git push builda a imagem uma vez e sobe os dois processos compartilhando o mesmo build e as mesmas variáveis de ambiente.
Como o bot guarda estado (memória de conversa, fila, contadores)?
Com um banco gerenciado no mesmo projeto: upuai add --type database --engine postgres (ou --engine redis) provisiona a instância e injeta a string de conexão como variável de ambiente. No Free, bot + 1 banco cabem no limite de 2 serviços.
O deploy quebrou. Por onde começo?
upuai logs --build mostra o build, upuai logs --process bot mostra o runtime do bot. Os erros mais comuns de bot são token errado na variável de ambiente e dependência faltando no package.json/requirements.txt. Pra reverter uma versão ruim: upuai rollback --list e upuai rollback --to <id> --yes.
Do localhost ao 24/7
O resumo do caminho: código no repositório, upuai.toml com o processo declarado como worker, token em variável de ambiente e git push. O bot passa a viver num container gerenciado no Brasil, que fica de pé, volta sozinho quando cai e conta nos logs o que aconteceu. Sem VPS pra cuidar, sem dólar na fatura.
Crie sua conta grátis, sem cartão →
Referências úteis: a documentação do upuai.toml tem o esquema completo de processos, e a documentação da CLI a lista inteira de comandos.
Faça deploy no Brasil em 5 minutos
PaaS brasileira, preços em Real, infraestrutura LGPD-native.
Ver planosArtigos relacionados
Deploy de Next.js no Brasil: guia completo do git push à produção
Guia completo de deploy de Next.js no Brasil: conecte o repo, faça git push e coloque SSR, ISR e API routes em produção no Upuai — com variáveis de ambiente, domínio próprio e custos em Real.
Alternativa ao Railway no Brasil: opções em Real e servidor no país
Saiu do Railway por causa do dólar e da latência? Veja as alternativas com deploy git push, cobrança em Real e servidor no Brasil, e quando cada uma faz sentido.
O datacenter em Belo Horizonte: por que importa onde seus bits dormem
Onde sua aplicação roda fisicamente determina latência, custo, jurisdição e compliance. Conheça o datacenter Upuai em BH/MG e por que escolhemos esse lugar.