---
title: "How to run a Telegram bot on a VPS: Python, aiogram and systemd"
description: "Hosting a Telegram bot on an Ubuntu or Debian VPS: a Python venv, the token in .env, a systemd service with auto-restart, logs and updates. Plus a no-console option."
url: https://tihost.io/en/blog/telegram-bot-on-vps
language: en
section: "Guides"
published: 2026-09-24
updated: 2026-10-05
publisher: Tihost (https://tihost.io)
---

# How to run a Telegram bot on a VPS: Python, aiogram and systemd

> **In short:** To keep a bot online around the clock, run it on a VPS as a systemd service: the code lives in its own directory with a Python virtual environment, the token in a .env file with mode 600, and systemd brings the bot back after a crash or a server reboot. A polling bot needs no domain and no open ports; a small bot fits the $4.00-a-month configuration.

**Key takeaways:**

- A Telegram bot on a VPS runs as a systemd service with `Restart=always`: systemd restarts the bot 5 seconds after a crash and starts it again after a server reboot.
- A Telegram bot using polling needs no domain, TLS certificate or open ports; a webhook requires a domain with HTTPS and port 443 open.
- The Telegram bot token from @BotFather belongs in a `.env` file with mode 600, passed to the process via `EnvironmentFile` in the systemd unit - not in the code and not in git.
- A small Telegram bot that answers messages and uses a database fits a VPS with 1 vCPU and 2 GB of RAM; at Tihost that configuration starts at $4.00 a month.

## What server a bot needs

A bot that answers messages and talks to a database fits the smallest [Starter](https://tihost.io/en/blog/starter-vps) configuration - 1 vCPU and 2 GB of RAM for $4.00 a month. You need more if the bot processes media, holds thousands of concurrent chats, or shares the server with a database and a website. Load is visible in the panel - start small and move to a larger plan at any time.

Before installing, go through the [first server setup](https://tihost.io/en/blog/vps-first-setup): the commands below run as the `deploy` user with sudo, not as root.

## Step 1. Install Python and dependencies

The bot lives in `/opt/mybot` with its own virtual environment, leaving the system Python untouched:

```bash
sudo apt update
sudo apt install -y python3-venv git
sudo mkdir -p /opt/mybot
sudo chown deploy: /opt/mybot
cd /opt/mybot
python3 -m venv .venv
.venv/bin/pip install aiogram
```

## Step 2. Add the bot code

If the code is in a repository, `git clone` it into `/opt/mybot` and run `.venv/bin/pip install -r requirements.txt`. For a test, a minimal aiogram 3 bot will do - save it as `/opt/mybot/bot.py`:

`bot.py`:

```python
import asyncio
import os

from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message

dp = Dispatcher()


@dp.message(CommandStart())
async def start(message: Message) -> None:
    await message.answer("Bot is running on a VPS")


async def main() -> None:
    bot = Bot(os.environ["BOT_TOKEN"])
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())
```

## Step 3. Keep the token in .env

The @BotFather token must not end up in the code or in git. Put it in a file only the owner can read:

```bash
echo 'BOT_TOKEN=123456789:AA...' > /opt/mybot/.env
chmod 600 /opt/mybot/.env
```

## Step 4. Run the bot as a systemd service

systemd starts the bot when the server boots and restarts it 5 seconds after a crash. `EnvironmentFile` passes the token from .env into the process environment:

```bash
sudo tee /etc/systemd/system/mybot.service > /dev/null <<'EOF'
[Unit]
Description=Telegram bot
After=network-online.target
Wants=network-online.target

[Service]
User=deploy
WorkingDirectory=/opt/mybot
EnvironmentFile=/opt/mybot/.env
ExecStart=/opt/mybot/.venv/bin/python bot.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
```

## Step 5. Check the status and logs

The first command shows whether the service is running, the second streams the bot's log in real time:

```bash
systemctl status mybot
journalctl -u mybot -f
```

Send /start to the bot. If it stays silent, the log shows why: a wrong token, an import error or an exception in the code.

## How to update the bot

```bash
cd /opt/mybot
git pull
.venv/bin/pip install -r requirements.txt
sudo systemctl restart mybot
```

If the bot keeps data in a database or files, take a backup before updating - the options are covered in the [VPS backup guide](https://tihost.io/en/blog/vps-backup).

## Polling or webhook

With polling, the bot asks Telegram for new messages itself. It needs no domain, certificate or open ports, which makes it the best way to start. With a webhook, Telegram pushes updates to your HTTPS address: lower latency and fewer idle requests, but you need a domain with a certificate and port 443 open. Switching to a webhook makes sense once the bot has many users.

## No-console option: Tihost Deploy

If you would rather not set up systemd by hand, create a project on your Linux server under «My Projects» and point it at the code: a GitHub repository, uploaded files or an archive, or code pasted as text. Add the bot token under «Environment variables» - they are stored encrypted. Tihost Deploy handles the build, start and restarts. The subscription is $4.00 a month for the whole account, not per project.

**Launch a server in 2 minutes.** AMD Ryzen 9, NVMe and DDoS protection in Germany, Finland and Poland. Pay with crypto or card. [Order a Server](https://tihost.io/login)

## FAQ

### How much does it cost to host a Telegram bot on a VPS?

Servers start at $4.00 a month; paying for 12 months upfront gives 20% off. A polling bot needs no domain.

### The bot stops when I close SSH. Why?

A bot started straight from the terminal exits together with the SSH session. Run it as a systemd service - then the bot runs independently of SSH and comes back after a server reboot.

### Where do I see the bot's errors?

In the systemd journal: `journalctl -u mybot -f` streams the bot's output in real time.

### Can I run several bots on one VPS?

Yes, one VPS can run several bots. Give each bot its own directory, virtual environment and systemd service file with a unique name.

### Does a Telegram bot need a domain?

A Telegram bot using polling needs no domain. A domain with an HTTPS certificate is only needed for a webhook bot.

---

Updated 2026-10-05 · https://tihost.io/en/blog/telegram-bot-on-vps
