Comment héberger un bot Telegram toujours en ligne
Suivez ça sur votre propre serveur. Commencer gratuitement, sans carte
Un bot Telegram qui ne répond que lorsque votre ordinateur est ouvert n’est pas encore un bot, c’est un script. L’écart entre les deux est le même que pour n’importe quel autre service toujours actif : un processus qui continue de tourner, qui redémarre s’il plante, et qui soit continue de demander des mises à jour à Telegram, soit a un endroit public où Telegram peut les envoyer. Ce guide construit un vrai bot avec python-telegram-bot, parcourt la seule décision qui compte vraiment pour l’héberger (long polling contre webhook), et couvre le Dockerfile, la politique de redémarrage et le chemin de déploiement pour le garder en ligne.
Ce qu’il vous faut
- Python 3.10 ou plus récent installé en local (python-telegram-bot 22.x l’exige).
- Un compte Telegram et @BotFather pour créer le bot et obtenir un token.
- Docker installé en local, pour construire et tester l’image.
- Un serveur pour faire tourner le conteneur, ou un compte Railyard pour le raccourci de la dernière section.
Étape 1 : créer le bot et obtenir un token
Ouvrez une conversation avec @BotFather sur Telegram, envoyez /newbot, donnez-lui un nom et un nom d’utilisateur se terminant par bot. BotFather répond avec un token qui ressemble à 123456789:AAFkj2-exempleirreel. Ce token est l’identifiant complet pour contrôler le bot ; il va dans une variable d’environnement, jamais committé dans un dépôt.
Étape 2 : écrire le bot
python-telegram-bot 22.8 est la version actuelle sur PyPI. Installez-le :
python -m venv venv
source venv/bin/activate
pip install "python-telegram-bot==22.8"
bot.py :
import logging
import os
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Bonjour. Envoyez-moi n'importe quoi et je vous le renverrai.")
async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text(update.message.text)
def main() -> None:
token = os.environ["TELEGRAM_BOT_TOKEN"]
application = Application.builder().token(token).build()
application.add_handler(CommandHandler("start", start))
application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
application.run_polling(allowed_updates=Update.ALL_TYPES)
if __name__ == "__main__":
main()
Testez-le en local :
TELEGRAM_BOT_TOKEN=votre-token-ici python bot.py
Envoyez un message au bot sur Telegram ; /start et n’importe quel texte simple devraient tous les deux recevoir une réponse en une seconde ou deux.
Étape 3 : long polling contre webhook, et pourquoi ça compte pour l’hébergement
application.run_polling() ci-dessus, c’est du long polling : votre bot demande en boucle aux serveurs de Telegram « y a-t-il du nouveau pour moi ? » via une connexion HTTP que Telegram garde ouverte et à laquelle il répond dès qu’une mise à jour existe, puis le bot redemande immédiatement. Rien dans votre bot n’a besoin d’être accessible depuis Internet ; il ne fait que des requêtes sortantes vers Telegram, la même forme que la connexion à la gateway Discord dans héberger un bot Discord 24 heures sur 24. C’est pour ça que le long polling est le bon choix par défaut pour « toujours en ligne » : ça n’a besoin que d’une chose, un processus qui continue de tourner et de demander, sans rien à exposer, aucun domaine, et aucun certificat.
L’alternative, un webhook, inverse le sens : vous enregistrez une URL HTTPS publique auprès de Telegram (application.run_webhook(...), qui écoute sur un port, plus un appel pour définir l’URL du webhook côté Telegram), et Telegram pousse chaque mise à jour vers cette URL comme un POST HTTP au moment où elle se produit, au lieu que votre bot la demande. Le compromis vraiment honnête : un webhook élimine l’aller-retour constant du polling et peut être légèrement plus rapide, mais ce n’est pas réellement plus simple à héberger, c’est un ensemble d’exigences différent. Il faut un vrai domaine avec un certificat TLS valide (Telegram exige HTTPS pour les webhooks, autosigné seulement avec des étapes supplémentaires que la plupart des bots évitent), et surtout, ça a quand même besoin d’un processus toujours actif pour le recevoir : un webhook est déclenché par HTTP, pas déclenché-puis-détruit par requête, parce que si rien n’écoute à l’URL enregistrée au moment où Telegram essaie de livrer une mise à jour, cette mise à jour est simplement perdue. « Basé sur HTTP » ne veut pas dire « fonctionne sur une plateforme qui réduit à zéro » ici, puisque le bot doit quand même être actif au moment exact et imprévisible où Telegram pousse.
Pour un bot que vous hébergez vous-même sans déjà avoir un domaine et un certificat configurés, le long polling est le choix le plus simple, et tout aussi « toujours en ligne », et c’est celui autour duquel ce guide est construit. Passez à un webhook plus tard si le volume de requêtes le justifie vraiment ; les fonctions de gestion (start, echo) ne changent pas, seule main() change.
Étape 4 : écrire le Dockerfile
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN useradd --create-home appuser
USER appuser
CMD ["python", "bot.py"]
requirements.txt :
python-telegram-bot==22.8
Comme pour le Dockerfile du bot Discord, il n’y a pas de EXPOSE ici : le long polling ne fait que des connexions sortantes, donc rien n’a besoin d’en accepter une entrante. L’image tourne en tant qu’appuser non root créé explicitement, l’équivalent Python de l’histoire de l’utilisateur node pour une image Node.
Étape 5 : politique de redémarrage et logs
docker build -t my-telegram-bot .
docker run -d --name my-telegram-bot --restart unless-stopped \
-e TELEGRAM_BOT_TOKEN=votre-token-ici \
my-telegram-bot
--restart unless-stopped redémarre le conteneur après un crash ou un redémarrage de la machine hôte, sans que personne se connecte en SSH. L’appel logging.basicConfig de l’Étape 2 envoie tout vers stdout, que Docker capture déjà :
docker logs -f my-telegram-bot
Vous devriez voir les lignes INFO que python-telegram-bot émet lui-même au démarrage (confirmant qu’il s’est connecté à l’API de Telegram) et une pour chaque /start ou message renvoyé en écho.
Le raccourci : avec Railyard
Pointez Railyard vers le même dépôt. Un Dockerfile qui construit une image autonome (pas une qui attend un répertoire source monté par lien, que la détection de build de Railyard ignore automatiquement) se construit et tourne directement ; voir les méthodes de build. Comme pour le bot Discord, c’est une application uniquement-worker sans processus web, que Railyard fait tourner comme n’importe quelle autre, simplement sans port attaché ; voir Workers et tâches planifiées.
Ajoutez TELEGRAM_BOT_TOKEN sous l’onglet Variables de l’application ; c’est chiffré et appliqué au prochain déploiement, remplaçant le drapeau -e de l’Étape 5. Voir Variables et secrets. Laissez Sleep when idle (sous Settings → General) désactivé pour ce processus : une conversation calme peut sembler inactive côté CPU pendant de longues périodes alors que le bot est en plein long polling, attendant une réponse des serveurs de Telegram, et c’est exactement cette attente qui ne doit pas être interrompue.
La politique de redémarrage de l’Étape 5 n’est pas non plus un réglage à configurer séparément, c’est juste la façon dont tourne le conteneur de chaque application sur Railyard par défaut, le même comportement sauf-arrêt-explicite. Les logs se trouvent dans l’onglet Logs de la page de l’application, ou via railyard logs my-bot --follow depuis la CLI.
Si vous préférez l’approche webhook de l’Étape 3 plutôt que le long polling, le HTTPS automatique de Railyard (chaque application reçoit un certificat immédiatement, un domaine personnalisé ajoute un enregistrement DNS et une vérification de propriété ; voir domaines et HTTPS) couvre la seule partie qui rend autrement les webhooks plus compliqués à héberger soi-même ; l’application aurait alors besoin d’un petit processus web en plus de la logique du bot pour recevoir les requêtes POST de Telegram, ce qui est un vrai changement d’architecture par rapport à la forme uniquement-worker de ce guide, pas juste un bouton à cocher.
Dépannage
Le bot ne répond pas, mais le conteneur tourne. Vérifiez d’abord docker logs pour une erreur d’autorisation ; un token invalide échoue à Application.builder().token(token).build() ou peu après le début de run_polling(), et cette erreur est presque toujours la première chose dans le log.
« Conflict: terminated by other getUpdates request ». Telegram n’autorise qu’une seule connexion en long polling par token de bot à la fois. Ça veut dire que deux processus tournent avec le même token simultanément, souvent une exécution locale de test laissée en marche pendant que le même bot est aussi déployé ; arrêtez-en un.
Le conteneur redémarre en boucle. Vérifiez les premières lignes de docker logs juste après un redémarrage, pas la fin. Une variable d’environnement TELEGRAM_BOT_TOKEN manquante (une KeyError venant de os.environ["TELEGRAM_BOT_TOKEN"]) est la cause de crash immédiat la plus fréquente pour un bot fraîchement déployé.
Les messages envoyés pendant que le bot était hors ligne n’arrivent jamais. Telegram met bien en file les mises à jour pour un bot brièvement injoignable et les livre une fois le polling repris, pour une durée limitée, mais un bot hors ligne pendant une période prolongée manquera quand même ce qui dépasse cette fenêtre ; c’est une raison de traiter « toujours en ligne » comme le vrai objectif plutôt que « généralement en ligne », pas comme un filet de sécurité sur lequel compter.
FAQ
Long polling ou webhook : lequel utiliser vraiment ? Le long polling, pour la plupart des bots gérés par une personne ou une petite équipe sans domaine ni certificat déjà en place. Il n’a besoin de rien d’accessible publiquement. Passez à un webhook seulement une fois que le volume de requêtes ou la latence le justifie vraiment, vu les exigences supplémentaires de domaine, certificat et port entrant.
python-telegram-bot ou node-telegram-bot-api : est-ce que ça change quelque chose pour l’hébergement ? Pas pour quoi que ce soit dans ce guide. La version majeure actuelle de node-telegram-bot-api (2.x) est une refonte complète de son API par rapport aux anciennes versions, mais la forme d’hébergement est identique dans les deux cas : un processus toujours actif, un Dockerfile sans port exposé pour le cas du long polling, et une politique de redémarrage. Le code Python et Node diffère ; ce dont le processus a besoin pour rester vivant ne diffère pas.
Peut-on faire tourner le bot gratuitement ? La bibliothèque est gratuite ; un processus toujours actif a besoin d’un calcul toujours actif, ce pour quoi un niveau gratuit serverless n’est généralement pas conçu, puisque la plupart réduisent à zéro entre les requêtes. Un petit VPS à quelques dollars par mois est le plancher réaliste pour une disponibilité vraiment continue.
Que se passe-t-il si deux instances du bot tournent en même temps avec le même token ? L’API de long polling de Telegram rejette explicitement une deuxième connexion getUpdates concurrente pour le même token de bot avec l’erreur « Conflict » de la section de dépannage ci-dessus ; une seule instance peut détenir la connexion de polling à la fois, par conception, ce qui veut aussi dire qu’on ne peut pas faire d’extension horizontale d’un bot en long polling comme on le ferait pour une application web.
Ai-je besoin du mode webhook pour faire tourner beaucoup de bots ou un bot avec beaucoup d’utilisateurs ? Pas nécessairement juste à cause du nombre d’utilisateurs ; le long polling évolue selon le nombre de messages qui arrivent, pas selon le nombre d’utilisateurs qui suivent le bot. Le mode webhook devient plus intéressant à un volume de messages vraiment élevé où l’aller-retour du polling lui-même ajoute un surcoût significatif, ce qui est une barre plus haute que ce qu’atteignent la plupart des bots.
Rester en ligne, pour un bot Telegram, revient aux deux mêmes choses que pour n’importe quel autre service tournant en continu : un processus qui ne s’arrête pas de lui-même, et un qui revient quand quelque chose l’arrête quand même. Tout le reste, y compris le choix entre polling et webhook, n’est qu’un détail par-dessus ça.
Pourquoi les gens choisissent Railyard pour ça
- Votre propre compte infonuagique. Déployez sur DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou n'importe quel serveur Linux par SSH, facturé directement par votre fournisseur, sans majoration.
- Un prix fixe par équipe. L'offre gratuite est gratuite pour toujours : un serveur plus un serveur de base de données, trois applications, sans carte. Pro coûte 19 $ par mois pour jusqu'à cinq serveurs et un nombre illimité d'applications. Team coûte 49 $ par mois avec des serveurs illimités. Aucuns frais par application, par déploiement, par siège ou par gigaoctet.
- Des gabarits en un clic. Déployez des applications open source, comme des bases de données, des outils d'analyse et des outils de développement, sur votre propre serveur en un clic.
- Des bases de données gérées. Postgres, MySQL et Redis, avec des sauvegardes planifiées, vérifiées par restauration, et la récupération à un point dans le temps.
- Déploiement par push. Déployez depuis GitHub, GitLab ou la CLI, avec HTTPS automatique et des mises en production sans interruption.