How to Run a Telegram Bot on a VPS 24/7 (Python + Systemd Guide)

How to Run a Telegram Bot on a VPS 24/7 (Python + Systemd Guide)

A Telegram bot running on your laptop shuts down the moment you close the lid. A Telegram bot running on a VPS runs 24/7, responds to messages instantly at any hour, and doesn’t depend on your local machine being on. For any bot that needs to be reliably available β€” customer service bots, notification systems, automation tools, community management bots β€” a VPS is the right home.

This guide covers building a Python Telegram bot with python-telegram-bot, deploying it to Ubuntu VPS, and setting it up as a systemd service that restarts automatically on crashes and reboots.

What You’ll Build

  • A Python Telegram bot using the python-telegram-bot library
  • A systemd service that keeps it running 24/7
  • Automatic restart on crash
  • Log management so you can monitor bot activity
  • Environment variable management for the bot token

Requirements

  • Ubuntu VPS 22.04 or 24.04 LTS
  • Python 3.10+ installed
  • A Telegram bot token from @BotFather

πŸ’‘ VPS.DO Tip: A Telegram bot runs comfortably on VPS.DO’s entry-level plans β€” it uses minimal CPU and RAM. View Plans β†’


Step 1: Get Your Bot Token from BotFather

  1. Open Telegram and search for @BotFather
  2. Send /newbot
  3. Follow prompts to name your bot
  4. Copy the API token β€” it looks like: 7123456789:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw

Step 2: Set Up the VPS Environment

sudo apt update && sudo apt upgrade -y
sudo apt install python3 python3-pip python3-venv -y

# Create app directory
mkdir -p /var/bots/mybot
cd /var/bots/mybot

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install python-telegram-bot
pip install python-telegram-bot --upgrade

Step 3: Create Your Bot

nano /var/bots/mybot/bot.py
import logging
import os
from telegram import Update
from telegram.ext import (
    Application, CommandHandler, MessageHandler,
    filters, ContextTypes
)

# Configure logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO,
    handlers=[
        logging.FileHandler('/var/log/mybot.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# Get token from environment variable
BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')

# ─── Command Handlers ───────────────────────────────────────

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /start command"""
    user = update.effective_user
    await update.message.reply_html(
        f"πŸ‘‹ Hi {user.first_name}! I'm running 24/7 on VPS.DO.\n\n"
        f"Available commands:\n"
        f"/start - Show this message\n"
        f"/help - Get help\n"
        f"/status - Check bot status"
    )

async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /help command"""
    await update.message.reply_text(
        "I'm a Telegram bot running on a VPS.\n"
        "Use /status to check if I'm alive."
    )

async def status(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handle /status command"""
    import platform, psutil
    cpu = psutil.cpu_percent(interval=1)
    ram = psutil.virtual_memory().percent
    await update.message.reply_text(
        f"βœ… Bot is online\n"
        f"πŸ–₯️ OS: {platform.system()} {platform.release()}\n"
        f"πŸ“Š CPU: {cpu}%\n"
        f"πŸ’Ύ RAM: {ram}%"
    )

async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Echo all non-command messages"""
    await update.message.reply_text(
        f"You said: {update.message.text}\n"
        f"(Add your logic here)"
    )

async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE):
    """Log errors"""
    logger.error("Exception while handling update:", exc_info=context.error)

# ─── Main ────────────────────────────────────────────────────

def main():
    if not BOT_TOKEN:
        logger.error("TELEGRAM_BOT_TOKEN not set!")
        return

    app = Application.builder().token(BOT_TOKEN).build()

    # Register handlers
    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("help", help_command))
    app.add_handler(CommandHandler("status", status))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
    app.add_error_handler(error_handler)

    logger.info("Bot starting...")
    app.run_polling(allowed_updates=Update.ALL_TYPES)

if __name__ == '__main__':
    main()

Install psutil for the /status command

pip install psutil

Test the bot manually first

export TELEGRAM_BOT_TOKEN="your-bot-token-here"
python bot.py

Send /start to your bot in Telegram. If it responds, the bot works. Press Ctrl+C to stop.


Step 4: Create a Systemd Service

sudo nano /etc/systemd/system/mybot.service
[Unit]
Description=My Telegram Bot
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/bots/mybot
Environment="TELEGRAM_BOT_TOKEN=YOUR_BOT_TOKEN_HERE"
ExecStart=/var/bots/mybot/venv/bin/python bot.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
sudo chown -R www-data:www-data /var/bots/mybot
sudo systemctl daemon-reload
sudo systemctl enable mybot
sudo systemctl start mybot
sudo systemctl status mybot

You should see active (running). Your bot is now running 24/7. βœ…


Step 5: Monitor the Bot

View live logs

# Via systemd journal
sudo journalctl -u mybot -f

# Via log file
tail -f /var/log/mybot.log

Check if it’s running

sudo systemctl status mybot

Restart after code changes

sudo systemctl restart mybot

Step 6: Deploying Code Updates

nano ~/deploy-bot.sh
#!/bin/bash
echo "Deploying bot update..."
cd /var/bots/mybot
git pull origin main
source venv/bin/activate
pip install -r requirements.txt --quiet
sudo systemctl restart mybot
echo "Bot restarted βœ…"
sudo systemctl status mybot --no-pager
chmod +x ~/deploy-bot.sh

Step 7: Webhook Mode (Alternative to Polling)

Polling has the bot constantly check Telegram for updates. Webhook mode has Telegram push updates to your VPS β€” more efficient for high-traffic bots.

# In bot.py, replace app.run_polling() with:
app.run_webhook(
    listen="0.0.0.0",
    port=8443,
    url_path=BOT_TOKEN,
    webhook_url=f"https://yourdomain.com/{BOT_TOKEN}",
    cert='/etc/letsencrypt/live/yourdomain.com/fullchain.pem',
    key='/etc/letsencrypt/live/yourdomain.com/privkey.pem',
)

Webhook mode requires a domain with valid SSL. For most personal and small business bots, polling mode is simpler and perfectly adequate.


Popular Telegram Bot Use Cases on VPS

Use Case What it does
Customer support bot Auto-respond to FAQs, route to human agent
Server monitoring bot Send CPU/RAM/disk alerts to a Telegram channel
Price alert bot Monitor prices and notify when thresholds hit
Content scheduler Post scheduled messages to channels/groups
File conversion bot Accept files, process them, return results
VPS management bot Start/stop services, check status via Telegram

Final Thoughts

A Telegram bot on a VPS is one of the most practical automation tools you can build. It costs almost nothing to run (under 50 MB RAM, negligible CPU for most bots), is immediately accessible from any Telegram client, and with systemd managing the process, it runs reliably without any manual intervention.

VPS.DO’s entry-level KVM VPS plans are perfectly sized for hosting multiple Telegram bots alongside other applications.

Related articles:

Fast β€’ Reliable β€’ Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!