--- title: "Cómo desplegar un bot de Telegram en Python en Ubuntu 24.04" description: "Crea un bot de Telegram con python-telegram-bot, instálalo en un entorno virtual en Ubuntu 24.04 y ejecútalo como servicio systemd seguro que arranca solo." category: "Casos de Uso" language: es source: https://cubepath.com/es/docs/casos-de-uso/bot-de-telegram-en-servidor-vps updated: 2026-09-25 --- # Cómo desplegar un bot de Telegram en Python en Ubuntu 24.04 Un bot de Telegram es un programa que recibe mensajes a través de la API de bots de Telegram y responde automáticamente: avisos, comandos de administración, atención al cliente o integraciones con otros servicios. Para que funcione las 24 horas necesita un servidor siempre encendido. En este tutorial crearás un bot con la librería `python-telegram-bot`, lo instalarás en un entorno virtual de Python en Ubuntu 24.04 y lo dejarás funcionando como servicio de systemd, con un usuario propio, el token fuera del código y reinicio automático. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Un bot sencillo funciona con 512 MB de RAM. - Un usuario no root con privilegios `sudo`. - Una cuenta de Telegram en el móvil o en el escritorio. El bot usa **long polling**: es el propio bot el que consulta periódicamente a Telegram si hay mensajes nuevos. Por eso no necesitas dominio, certificado TLS ni abrir ningún puerto en el firewall. ## Paso 1: Crear el bot con BotFather Los bots se registran hablando con [@BotFather](https://t.me/BotFather), el bot oficial de Telegram para gestionar bots. Ábrelo en Telegram y sigue estos pasos: 1. Envía `/newbot`. 2. Escribe el nombre visible del bot, por ejemplo `Mi Bot de Avisos`. 3. Escribe el nombre de usuario. Debe ser único y terminar en `bot`, por ejemplo `mi_avisos_bot`. BotFather responde con el token de acceso a la API: ```text Use this token to access the HTTP API: 123456789:AAH-your_bot_token_example ``` Guárdalo en un lugar seguro. Quien tenga el token controla el bot por completo; si se filtra, revócalo desde BotFather con `/revoke`. Comprueba desde el servidor que el token es válido llamando al método `getMe` de la API. Sustituye `your_bot_token` por el tuyo: ```bash curl -s https://api.telegram.org/botyour_bot_token/getMe ``` ```output {"ok":true,"result":{"id":123456789,"is_bot":true,"first_name":"Mi Bot de Avisos","username":"mi_avisos_bot",...}} ``` Si ves `"ok":false` con `Unauthorized`, el token está mal copiado. ## Paso 2: Crear un usuario de sistema para el bot El bot no necesita una shell ni acceso a tu usuario, así que se ejecutará con un usuario de sistema propio. Si el código tuviera un fallo aprovechable, el atacante quedaría limitado a lo que puede hacer ese usuario: ```bash sudo adduser --system --group --home /opt/telegram-bot --shell /usr/sbin/nologin telegrambot ``` Comprueba que se ha creado: ```bash id telegrambot ``` ```output uid=110(telegrambot) gid=111(telegrambot) groups=111(telegrambot) ``` ## Paso 3: Instalar Python y las dependencias Ubuntu 24.04 incluye Python 3.12, pero no permite instalar paquetes con `pip` fuera de un entorno virtual. Instala el módulo `venv`: ```bash sudo apt update sudo apt install python3-venv ``` Crea el entorno virtual dentro del directorio del bot, como el usuario `telegrambot`: ```bash sudo -u telegrambot python3 -m venv /opt/telegram-bot/venv ``` Instala la librería `python-telegram-bot`, que envuelve la API de Telegram con una interfaz asíncrona: ```bash sudo -u telegrambot /opt/telegram-bot/venv/bin/pip install python-telegram-bot ``` Comprueba la versión instalada: ```bash sudo -u telegrambot /opt/telegram-bot/venv/bin/python -c "import telegram; print(telegram.__version__)" ``` ```output 22.4 ``` Cualquier versión 21 o posterior sirve para el código de esta guía. ## Paso 4: Guardar el token en un archivo de entorno El token no debe estar escrito en el código: acabaría en el repositorio o en una copia de seguridad. Guárdalo en un archivo que systemd cargará al arrancar el servicio: ```bash sudo nano /etc/telegram-bot.env ``` ```ini TELEGRAM_BOT_TOKEN=your_bot_token ``` Deja el archivo legible solo por root. systemd lo lee como root antes de cambiar al usuario del servicio, así que el bot recibe la variable sin poder leer el archivo: ```bash sudo chown root:root /etc/telegram-bot.env sudo chmod 600 /etc/telegram-bot.env ``` ## Paso 5: Escribir el bot Crea el programa principal: ```bash sudo nano /opt/telegram-bot/bot.py ``` Este bot responde a `/start` y `/help`, devuelve tu ID de chat con `/id` y repite cualquier otro texto que le envíes: ```python #!/usr/bin/env python3 import logging import os from telegram import Update from telegram.ext import ( Application, CommandHandler, ContextTypes, MessageHandler, filters, ) logging.basicConfig( format="%(levelname)s %(name)s: %(message)s", level=logging.INFO, ) # httpx registra cada petición de polling; se silencia para no llenar el log logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger("bot") async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: user = update.effective_user await update.message.reply_text( f"Hola, {user.first_name}. Escribe /help para ver lo que sé hacer." ) async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text( "/start - saludo\n" "/id - muestra el ID de este chat\n" "Cualquier otro texto te lo devuelvo tal cual." ) async def chat_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text(f"ID de este chat: {update.effective_chat.id}") async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: await update.message.reply_text(update.message.text) async def on_error(update: object, context: ContextTypes.DEFAULT_TYPE) -> None: logger.error("Error procesando una actualización", exc_info=context.error) def main() -> None: token = os.environ["TELEGRAM_BOT_TOKEN"] app = Application.builder().token(token).build() app.add_handler(CommandHandler("start", start)) app.add_handler(CommandHandler("help", help_command)) app.add_handler(CommandHandler("id", chat_id)) app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo)) app.add_error_handler(on_error) logger.info("Bot iniciado, esperando mensajes") app.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` Puntos clave del código: - Cada `CommandHandler` asocia un comando a una función asíncrona. El `MessageHandler` con `filters.TEXT & ~filters.COMMAND` captura el texto que no es un comando. - `run_polling()` gestiona el bucle de consultas, los reintentos de red y la parada limpia cuando systemd envía `SIGTERM`. - Los logs van a la salida estándar, que systemd guarda en el journal. No hace falta configurar archivos de log ni rotación. - El manejador de errores registra las excepciones sin que el bot se caiga. Asigna el archivo al usuario del bot: ```bash sudo chown telegrambot:telegrambot /opt/telegram-bot/bot.py ``` ## Paso 6: Probar el bot manualmente Antes de crear el servicio, ejecútalo a mano para detectar errores. Este comando carga la variable del archivo de entorno y lanza el bot como `telegrambot`: ```bash sudo bash -c 'set -a; . /etc/telegram-bot.env; exec sudo -E -u telegrambot /opt/telegram-bot/venv/bin/python /opt/telegram-bot/bot.py' ``` ```output INFO bot: Bot iniciado, esperando mensajes INFO telegram.ext.Application: Application started ``` Abre el chat con tu bot en Telegram (`https://t.me/mi_avisos_bot`), pulsa **Iniciar** y envía `/start`, `/id` y un texto cualquiera. Deberías recibir las tres respuestas. Detén el bot con `Ctrl+C`. ## Paso 7: Ejecutar el bot como servicio systemd Para que el bot arranque con el servidor y se reinicie si falla, crea una unidad de systemd: ```bash sudo nano /etc/systemd/system/telegram-bot.service ``` ```ini [Unit] Description=Bot de Telegram Wants=network-online.target After=network-online.target [Service] Type=simple User=telegrambot Group=telegrambot WorkingDirectory=/opt/telegram-bot EnvironmentFile=/etc/telegram-bot.env Environment=PYTHONUNBUFFERED=1 ExecStart=/opt/telegram-bot/venv/bin/python /opt/telegram-bot/bot.py Restart=on-failure RestartSec=5 # Endurecimiento NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/opt/telegram-bot [Install] WantedBy=multi-user.target ``` Qué aporta cada bloque: - `EnvironmentFile` carga el token y `PYTHONUNBUFFERED=1` hace que los logs aparezcan en el journal al instante. - `Restart=on-failure` con `RestartSec=5` levanta el bot de nuevo si termina con error, por ejemplo tras un corte de red prolongado. - `ProtectSystem=strict` monta todo el sistema de archivos como solo lectura para el servicio, salvo `/opt/telegram-bot`, donde el bot podrá guardar datos (una base SQLite, por ejemplo). `ProtectHome=true` le oculta los directorios de los usuarios. Carga la unidad, actívala y arráncala: ```bash sudo systemctl daemon-reload sudo systemctl enable --now telegram-bot sudo systemctl status telegram-bot ``` ```output ● telegram-bot.service - Bot de Telegram Loaded: loaded (/etc/systemd/system/telegram-bot.service; enabled; preset: enabled) Active: active (running) since Thu 2026-09-25 11:02:37 UTC; 4s ago Main PID: 2841 (python) ``` Envía otro mensaje al bot desde Telegram para confirmar que responde con el servicio en marcha. ## Paso 8: Consultar los logs y actualizar el bot Sigue los logs en tiempo real: ```bash sudo journalctl -u telegram-bot -f ``` Para ver solo los errores de hoy: ```bash sudo journalctl -u telegram-bot -p err --since today ``` Cuando cambies el código de `bot.py`, reinicia el servicio para cargarlo: ```bash sudo systemctl restart telegram-bot ``` Para actualizar la librería a la última versión: ```bash sudo -u telegrambot /opt/telegram-bot/venv/bin/pip install --upgrade python-telegram-bot sudo systemctl restart telegram-bot ``` Si tu bot crece y usa más paquetes, guárdalos en un `requirements.txt` con versiones fijas y instálalos con `pip install -r requirements.txt`, para que una actualización no rompa el bot sin que lo sepas. ## Solución de problemas **`telegram.error.InvalidToken`**: el token del archivo `/etc/telegram-bot.env` es incorrecto o tiene espacios o comillas de más. La línea debe ser exactamente `TELEGRAM_BOT_TOKEN=` seguida del token. Tras corregirlo, reinicia el servicio. **`Conflict: terminated by other getUpdates request`**: hay dos procesos consultando con el mismo token. Suele ocurrir si dejaste el bot ejecutándose a mano en otra terminal o si el mismo token está en uso en tu equipo local. Comprueba los procesos con `pgrep -af bot.py` y deja solo uno. **`KeyError: 'TELEGRAM_BOT_TOKEN'`**: el servicio no ha cargado el archivo de entorno. Revisa la ruta en `EnvironmentFile` y ejecuta `sudo systemctl daemon-reload` después de editar la unidad. **El bot no responde en grupos**: por defecto los bots tienen activado el modo privacidad y en los grupos solo reciben comandos y respuestas a sus propios mensajes. Si necesitas que lea todo el texto del grupo, desactívalo en BotFather con `/setprivacy`. ## Conclusión Tienes un bot de Telegram en Python ejecutándose como servicio systemd en Ubuntu 24.04, con un usuario sin privilegios, el token fuera del código, el sistema de archivos protegido y reinicio automático ante fallos. Los logs quedan en el journal y actualizarlo es un solo reinicio. Como siguientes pasos, puedes: - Registrar la lista de comandos en BotFather con `/setcommands` para que Telegram los sugiera al escribir `/`. - Guardar datos de usuarios en una base SQLite dentro de `/opt/telegram-bot` o activar la persistencia integrada de la librería con `PicklePersistence`. - Programar mensajes periódicos con el `JobQueue` de `python-telegram-bot`, instalando el extra con `pip install "python-telegram-bot[job-queue]"`.