Deploy a Telegram bot

An always-on Telegram bot — get a token, set it, and it's live.

A bot is a long-running worker: it talks out to Telegram and reacts to messages. Dockhold keeps it running and gives it a URL for a status page. This recipe is the whole path.

Start from the telegram-bot-starter template — click Use this template, then deploy it.

1. Get a bot token

In Telegram, message @BotFather, send /newbot, pick a name, and copy the token it gives you (looks like 123456789:AA...).

2. Deploy and set the token

  1. Connect the repo at the dashboard and deploy.
  2. Add BOT_TOKEN in the dashboard — use the Vault, since it's a secret — and restart.

Message your bot on Telegram: /start, /help, or any text, and it echoes back. Until the token is set, the app runs idle and its URL shows a "set BOT_TOKEN" status — it never crashes.

3. Add your own commands

Edit index.js with Telegraf:

bot.command("ping", (ctx) => ctx.reply("pong"));
bot.hears("hello", (ctx) => ctx.reply("hi there"));

Keep any API keys the bot uses in the Vault and read them from process.env.

How it works

The bot uses long polling (it asks Telegram for updates), so there's no webhook to configure. It also runs a small status server on 0.0.0.0:$PORT — Dockhold gives every app a URL, and this gives you something to hit instead of an error. Run it as a single instance: a polling bot scaled past one replica would handle every update twice.

High volume? Switch to webhook mode — have Telegram POST updates to your app's https://<your-app>.dockhold.app/ URL on $PORT instead of polling. Discord? Same shape — swap Telegraf for discord.js and use a DISCORD_TOKEN.

Troubleshooting

  • Bot doesn't respond / logs "401 Unauthorized": the BOT_TOKEN is missing or wrong. Set the exact token from BotFather in the Vault and restart.
  • Replies arrive twice: you're running more than one instance. A long-polling bot must be a single replica.

Next