- 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
.envfile with mode 600, passed to the process viaEnvironmentFilein 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 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: 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:
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 aiogramStep 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:
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:
echo 'BOT_TOKEN=123456789:AA...' > /opt/mybot/.env
chmod 600 /opt/mybot/.envStep 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:
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 mybotStep 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:
systemctl status mybot
journalctl -u mybot -fSend /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
cd /opt/mybot
git pull
.venv/bin/pip install -r requirements.txt
sudo systemctl restart mybotIf the bot keeps data in a database or files, take a backup before updating - the options are covered in the VPS backup guide.
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.
AMD Ryzen 9, NVMe and DDoS protection in Germany, Finland and Poland. Pay with crypto or card.
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.