Wie man einen Telegram-Bot hostet, der immer online ist
Folge dem auf deinem eigenen Server. Kostenlos starten, keine Karte nötig
Ein Telegram-Bot, der nur antwortet, während dein Laptop zufällig offen ist, ist noch kein Bot, es ist ein Skript. Die Lücke zwischen beiden ist dieselbe Lücke wie bei jedem anderen Always-on-Dienst: ein Prozess, der am Laufen bleibt, bei einem Absturz neu startet, und entweder weiterhin Telegram nach Updates fragt oder einen öffentlichen Ort hat, wohin Telegram sie senden kann. Diese Anleitung baut einen echten Bot mit python-telegram-bot, geht die eine Entscheidung durch, die für das Hosting tatsächlich zählt (Long-Polling versus ein Webhook), und behandelt das Dockerfile, die Restart-Policy und den Deploy-Weg, um ihn online zu halten.
Was du brauchst
- Python 3.10 oder neuer lokal installiert (python-telegram-bot 22.x braucht es).
- Ein Telegram-Account und @BotFather, um den Bot zu erstellen und ein Token zu bekommen.
- Docker lokal installiert, um das Image zu bauen und zu testen.
- Einen Server, um den Container auszuführen, oder einen Railyard-Account für die Abkürzung im letzten Abschnitt.
Schritt 1: Den Bot erstellen und ein Token holen
Öffne einen Chat mit @BotFather auf Telegram, sende /newbot, gib ihm einen Namen und einen Benutzernamen, der auf bot endet. BotFather antwortet mit einem Token, das wie 123456789:AAFkj2-examplenotrealtoken aussieht. Dieses Token ist die vollständige Zugangsdaten, um den Bot zu kontrollieren; es gehört in eine Umgebungsvariable, niemals in ein Repository committet.
Schritt 2: Den Bot schreiben
python-telegram-bot 22.8 ist das aktuelle Release auf PyPI. Installier es:
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("Hi. Send me anything and I'll echo it back.")
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()
Teste ihn lokal:
TELEGRAM_BOT_TOKEN=your-token-here python bot.py
Schreib dem Bot auf Telegram; /start und einfacher Text sollten beide innerhalb von ein, zwei Sekunden eine Antwort bekommen.
Schritt 3: Long-Polling versus ein Webhook, und warum das für das Hosting wichtig ist
application.run_polling() oben ist Long-Polling: Dein Bot fragt wiederholt Telegrams Server „irgendwas Neues für mich?” über eine HTTP-Verbindung, die Telegram offen hält und beantwortet, sobald ein Update existiert, dann fragt der Bot sofort wieder. Nichts an deinem Bot muss aus dem Internet erreichbar sein; er macht immer nur ausgehende Requests an Telegram, dieselbe Form wie die Discord-Gateway-Verbindung in einen Discord-Bot 24/7 hosten. Deshalb ist Long-Polling die richtige Standardwahl für „immer online”: Es braucht genau eine Sache, einen Prozess, der am Laufen bleibt und weiter fragt, nichts zu exponieren, keine Domain und kein Zertifikat.
Die Alternative, ein Webhook, dreht die Richtung um: Du registrierst eine öffentliche HTTPS-URL bei Telegram (application.run_webhook(...), lauschend auf einem Port, plus einen Aufruf, um die Webhook-URL auf Telegrams Seite zu setzen), und Telegram pusht jedes Update als HTTP-POST an diese URL in dem Moment, in dem es passiert, statt dass dein Bot fragt. Der wirklich ehrliche Tradeoff: Ein Webhook entfernt den konstanten Round-Trip des Pollings und kann marginal niedrigere Latenz haben, aber er ist eigentlich nicht einfacher zu hosten, es ist nur ein anderer Satz von Anforderungen. Er braucht eine echte Domain mit einem gültigen TLS-Zertifikat (Telegram verlangt HTTPS für Webhooks, selbstsigniert nur mit zusätzlichen Schritten, die die meisten Bots überspringen), und entscheidend, er braucht trotzdem einen durchgehend laufenden Prozess, um ihn zu empfangen: Ein Webhook ist HTTP-ausgelöst, nicht Request-ausgelöst-und-wieder-abgebaut, weil, falls an der registrierten URL niemand lauscht, wenn Telegram versucht, ein Update zuzustellen, dieses Update einfach verworfen wird. „HTTP-basiert” heißt hier nicht „funktioniert auf einer Scale-to-Zero-Plattform”, da der Bot trotzdem genau in dem unvorhersehbaren Moment erreichbar sein muss, in dem Telegram pusht.
Für einen Bot, den du selbst hostest, ohne bereits eine Domain und ein Zertifikat eingerichtet zu haben, ist Long-Polling die einfachere, ebenso „immer online”-Wahl, und die, auf der diese Anleitung aufbaut. Wechsel später zu einem Webhook, falls das Request-Volumen das wirklich rechtfertigt; die Handler-Funktionen (start, echo) ändern sich in beiden Fällen nicht, nur main() ändert sich.
Schritt 4: Das Dockerfile schreiben
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
Wie beim Dockerfile des Discord-Bots gibt es hier kein EXPOSE: Long-Polling macht nur ausgehende Verbindungen, es muss also nichts eingehende akzeptieren. Das Image läuft als erstellter, Non-Root-appuser statt als Root, das Python-Äquivalent zur node-User-Geschichte eines Node-Images.
Schritt 5: Restart-Policy und Logging
docker build -t my-telegram-bot .
docker run -d --name my-telegram-bot --restart unless-stopped \
-e TELEGRAM_BOT_TOKEN=your-token-here \
my-telegram-bot
--restart unless-stopped startet den Container nach einem Absturz oder einem Host-Reboot neu, ohne dass sich jemand per SSH einloggen muss. Der logging.basicConfig-Aufruf aus Schritt 2 schickt alles nach stdout, was Docker schon erfasst:
docker logs -f my-telegram-bot
Du solltest die INFO-Zeilen sehen, die python-telegram-bot selbst beim Start ausgibt (die bestätigen, dass es sich mit Telegrams API verbunden hat), und eine für jeden behandelten /start-Befehl oder jede echote Nachricht.
Die Abkürzung: mit Railyard
Zeig Railyard auf dasselbe Repository. Ein Dockerfile, das ein eigenständiges Image baut (kein Image, das ein bind-gemountetes Source-Verzeichnis erwartet, was Railyards Build-Erkennung automatisch überspringt), baut und läuft direkt; siehe Build-Methoden. Wie beim Discord-Bot ist das eine Worker-only-App ohne Web-Prozess, die Railyard genauso betreibt wie jede andere App, nur ohne angehängten Port; siehe Workers und geplante Jobs.
Füge TELEGRAM_BOT_TOKEN im Variables-Tab der App hinzu; es ist verschlüsselt und wird beim nächsten Deploy angewendet, ersetzt das -e-Flag aus Schritt 5. Siehe Variablen und Secrets. Lass Sleep when idle (unter Settings → General) für diesen Prozess aus: Ein ruhiger Chat kann über lange Strecken CPU-leerlaufend aussehen, während der Bot mitten im Long-Poll steckt und auf Telegrams Server-Antwort wartet, und genau dieses Warten sollte nicht unterbrochen werden.
Die Restart-Policy aus Schritt 5 ist keine Einstellung, die du separat konfigurierst, es ist, wie der Container jeder App standardmäßig auf Railyard läuft, dasselbe „es sei denn explizit gestoppt”-Verhalten. Logs sind der Logs-Tab auf der App-Seite, oder railyard logs my-bot --follow von der CLI.
Falls du stattdessen den Webhook-Ansatz aus Schritt 3 statt Long-Polling nutzen möchtest, deckt Railyards automatisches HTTPS (jede App bekommt sofort ein Zertifikat, eine eigene Domain fügt einen DNS-Record und einen Ownership-Check hinzu; siehe Domains und HTTPS) genau das eine Stück ab, das Webhooks sonst zur komplizierteren Self-Hosting-Option macht; die App würde dann einen kleinen Web-Prozess neben der Bot-Logik brauchen, um Telegrams POST-Requests zu empfangen, was eine echte Architekturänderung gegenüber der Worker-only-Form dieser Anleitung ist, nicht nur ein Einstellungs-Toggle.
Troubleshooting
Der Bot antwortet nicht, aber der Container läuft. Prüf zuerst docker logs auf einen Autorisierungsfehler; ein ungültiges Token schlägt bei Application.builder().token(token).build() oder kurz nach dem Start von run_polling() fehl, und dieser Fehler steht fast immer als Erstes im Log.
„Conflict: terminated by other getUpdates request.” Telegram erlaubt nur eine Long-Polling-Verbindung pro Bot-Token gleichzeitig. Das heißt, dass zwei Prozesse gleichzeitig mit demselben Token laufen, häufig ein lokaler Testlauf, der weiterläuft, während derselbe Bot auch deployt ist; stopp einen davon.
Der Container startet in einer Schleife neu. Prüf die ersten Zeilen von docker logs direkt nach einem Restart, nicht das Ende. Eine fehlende TELEGRAM_BOT_TOKEN-Umgebungsvariable (ein KeyError von os.environ["TELEGRAM_BOT_TOKEN"]) ist der häufigste sofortige Absturz bei einem frisch deployten Bot.
Nachrichten, die gesendet wurden, während der Bot offline war, kommen nie an. Telegram stellt Updates für einen kurz nicht erreichbaren Bot tatsächlich in eine Warteschlange und liefert sie, sobald das Polling wieder aufgenommen wird, für eine begrenzte Zeit, aber ein Bot, der über längere Zeit down ist, wird trotzdem verpassen, was außerhalb dieses Fensters liegt; das ist ein Grund, „immer online” als das eigentliche Ziel zu behandeln statt „meistens online”, kein Sicherheitsnetz, auf das man sich verlassen sollte.
FAQ
Long-Polling oder Webhook: was sollte ich tatsächlich nutzen? Long-Polling, für die meisten Bots, die von einer Person oder einem kleinen Team ohne bereits eingerichtete Domain und Zertifikat betrieben werden. Es braucht überhaupt nichts öffentlich Zugängliches. Wechsel nur zu einem Webhook, sobald Request-Volumen oder Latenz die zusätzlichen Domain-, Zertifikats- und Eingangs-Port-Anforderungen wirklich rechtfertigen.
Spielt python-telegram-bot oder node-telegram-bot-api eine Rolle für das Hosting? Nicht für irgendetwas in dieser Anleitung. node-telegram-bot-apis aktuelle Hauptversion (2.x) ist ein kompletter Neuentwurf der API gegenüber älteren Versionen, aber die Hosting-Form ist in beiden Fällen identisch: ein Always-on-Prozess, ein Dockerfile ohne exponierten Port für den Long-Polling-Fall, und eine Restart-Policy. Der Python- und Node-Code unterscheiden sich; was der Prozess braucht, um am Leben zu bleiben, nicht.
Kann ich den Bot kostenlos betreiben? Die Bibliothek ist kostenlos; ein Always-on-Prozess braucht Always-on-Compute, wofür ein serverloses Free-Tier generell nicht gebaut ist, da die meisten zwischen Requests auf null herunterskalieren. Eine kleine VPS für ein paar Dollar im Monat ist der realistische Boden für wirklich kontinuierliche Uptime.
Was passiert, wenn zwei Instanzen des Bots gleichzeitig mit demselben Token laufen? Telegrams Long-Polling-API lehnt eine zweite gleichzeitige getUpdates-Verbindung für dasselbe Bot-Token explizit mit dem „Conflict”-Fehler aus dem Troubleshooting-Abschnitt oben ab; nur eine Instanz kann die Polling-Verbindung gleichzeitig halten, by design, was auch bedeutet, dass du einen Long-Polling-Bot nicht horizontal skalieren kannst, wie du es bei einer Web-App würdest.
Brauche ich den Webhook-Modus, um viele Bots oder einen Bot mit vielen Nutzern zu betreiben? Nicht unbedingt nur wegen der Nutzerzahl; Long-Polling skaliert mit der Anzahl eingehender Nachrichten, nicht mit der Anzahl der Nutzer, die dem Bot folgen. Webhook-Modus wird attraktiver bei wirklich hohem Nachrichtenvolumen, wo der Polling-Round-Trip selbst nennenswerten Overhead hinzufügt, was eine höhere Hürde ist, als die meisten Bots erreichen.
Online zu bleiben, läuft für einen Telegram-Bot auf dieselben zwei Dinge hinaus wie für jeden anderen kontinuierlich laufenden Dienst: einen Prozess, der nicht von selbst stoppt, und einen, der zurückkommt, wenn ihn trotzdem etwas stoppt. Alles andere, einschließlich ob du Polling oder Webhooks wählst, ist ein Detail darauf.
Warum Leute sich dafür Railyard entscheiden
- Dein eigenes Cloud-Konto. Deploye auf DigitalOcean, Hetzner, Vultr, AWS, OVHcloud oder jedem Linux-Server per SSH, direkt von deinem Anbieter abgerechnet, ohne Aufschlag.
- Ein fester Preis pro Team. Free ist für immer kostenlos: ein Server plus ein Datenbankserver, drei Apps, keine Karte. Pro kostet 19 $ im Monat für bis zu fünf Server und unbegrenzte Apps. Team kostet 49 $ im Monat mit unbegrenzten Servern. Keine Kosten pro App, pro Deployment, pro Sitz oder pro Gigabyte.
- Templates mit einem Klick. Deploye Open-Source-Apps, wie Datenbanken, Analytics und Dev-Tools, mit einem Klick auf deinem eigenen Server.
- Verwaltete Datenbanken. Postgres, MySQL und Redis mit geplanten, wiederherstellungsgeprüften Backups und Point-in-Time-Recovery.
- Push-to-Deploy. Deploye von GitHub, GitLab oder der CLI, mit automatischem HTTPS und Releases ohne Ausfallzeit.