گرمای تابستان — همه‌چیز آب می‌شود، حتی قیمت‌های ما.−25%−۲۵٪ روی هر پلن سالانه، تا ۳۱ اوتدیدن پلن‌ها
EQVPS

یک بات تلگرام را ۲۴/۷ روی یک VPS اجرا کنید: aiogram، systemd، polling در برابر webhook

13 تیر 1405 · 6 دقیقه مطالعه · EQVPS Team

یک بات تلگرام با aiogram نوشتید، محلی تستش کردید، و کار می‌کند. حالا باید جایی زندگی کند که وقتی لپ‌تاپ را می‌بندید نخوابد. یک VPS کوچک خانه‌ی طبیعی است — اما شکافی هست بین python bot.py در یک نشست SSH و یک باتی که واقعاً در طول کرش‌ها، ری‌بوت‌ها، و افتادن اتصالتان بالا می‌ماند.

این نسخه‌ی محصولی است: یک virtualenv، توکنی که بیرون از کدتان نگه داشته می‌شود، یک سرویس systemd که بات را خودش زنده می‌کند، و پاسخی روشن به سؤالی که همه دیر یا زود می‌پرسند — polling یا webhook؟

چرا فقط روی لپ‌تاپ اجرایش نکنیم

یک بات به یک اتصال خروجی پایدار به تلگرام نیاز دارد. لپ‌تاپ شما می‌خوابد، برای به‌روزرسانی ری‌بوت می‌شود، و بین شبکه‌ها می‌پرد — هر کدام از این‌ها بات را می‌اندازد، و کاربران به دیوار سکوت می‌خورند. یک VPS آن اتصال را شبانه‌روز نگه می‌دارد. این کل دلیل جابه‌جاکردنش از دستگاه شماست، و همان دلیلی است که یک بات دیسکورد هم به یک سرور تعلق دارد.

اگر فقط سریع‌ترین مسیر ممکن «آنلاینش کن» را با یک بات مینیمال می‌خواهید، راهنمای گام‌به‌گام میزبانی یک بات تلگرام آن را پوشش می‌دهد. این نوشته یک سطح عمیق‌تر می‌رود: aiogram، مدیریت امن توکن، و دانستن اینکه کِی مقیاس بدهید.

بات، در یک virtualenv

با SSH وصل شوید و بات را در venv خودش ایزوله نگه دارید — بسته‌ها را سیستم‌گستر نصب نکنید، بعداً ارتقاءها و پاک‌سازی را به‌هم می‌ریزد:

sudo apt update && sudo apt install -y python3-venv
mkdir ~/tgbot && cd ~/tgbot
python3 -m venv venv && source venv/bin/activate
pip install -U aiogram

یک بات مینیمال aiogram 3 که توکنش را از محیط می‌خواند، نه از یک رشته‌ی هاردکدشده:

# bot.py
import asyncio, logging, os
from aiogram import Bot, Dispatcher
from aiogram.types import Message
from aiogram.filters import CommandStart

logging.basicConfig(level=logging.INFO)
dp = Dispatcher()

@dp.message(CommandStart())
async def start(m: Message):
    await m.answer("Alive and running on a VPS.")

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

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

توکن را بیرون از کدتان نگه دارید

هرگز توکن BotFather را داخل bot.py نچسبانید — یک push به یک ریپازیتوری عمومی و لو رفته. به‌جایش آن را در یک فایل env که فقط root می‌خواند بگذارید:

sudo tee /etc/tgbot.env >/dev/null <<'EOF'
BOT_TOKEN=123456:your-token-from-botfather
EOF
sudo chmod 600 /etc/tgbot.env

یک توکن لو‌رفته فقط یک /revoke در BotFather تا رفع‌شدن فاصله دارد — اما لو‌رفتن هر چیز دیگر روی یک دستگاه مشترک بدتر است. یک VPS اختصاصی برای بات صادقانه خانه‌ی امن‌تری برای توکن است تا لپ‌تاپ روزمره‌تان: اگر لو برود، یک توکن را می‌چرخانید، نه کل راه‌اندازی‌تان را.

بخشی که آن را زنده نگه می‌دارد: systemd

این همان چیزی است که یک باتی که اجرا می‌شود را از یک باتی که در حال اجرا می‌ماند جدا می‌کند. سرویس را بسازید:

# /etc/systemd/system/tgbot.service
[Unit]
Description=Telegram bot (aiogram)
After=network-online.target
Wants=network-online.target

[Service]
User=botuser
WorkingDirectory=/home/botuser/tgbot
EnvironmentFile=/etc/tgbot.env
ExecStart=/home/botuser/tgbot/venv/bin/python bot.py
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

آن را به‌عنوان یک کاربر غیر-root اجرا کنید (botuser بالا)، نه root — اگر بات روزی به خطر افتاد، می‌خواهید محصور شده باشد. بعد:

sudo systemctl daemon-reload
sudo systemctl enable --now tgbot

Restart=always با RestartSec=3 یعنی یک کرش — یک به‌روزرسانی بد از تلگرام، یک exception مدیریت‌نشده، یک OOM — بات را در سه ثانیه برمی‌گرداند به‌جای اینکه آن را مرده رها کند تا وقتی متوجه شوید. زنده تماشایش کنید:

journalctl -u tgbot -f

این کل راه‌اندازی لاگ شماست. بدون فایل لاگ برای چرخاندن، بدون ابزار اضافی — journald همین‌حالا آن را دارد.

به‌روزرسانی بدون درام downtime

وقتی کد را تغییر می‌دهید یا aiogram را بالا می‌برید:

cd ~/tgbot && source venv/bin/activate
pip install -U aiogram          # if upgrading the library
sudo systemctl restart tgbot
journalctl -u tgbot -n 30 --no-pager   # confirm it came back clean

ری‌استارت بات را برای یکی دو ثانیه چشمک می‌زند. برای یک بات polling این برای کاربران نامرئی است — تلگرام به‌روزرسانی‌ها را صف می‌کند و به‌محض اتصال دوباره‌ی بات تحویلشان می‌دهد.

polling در برابر webhook — نسخه‌ی صادقانه

این تصمیمی است که مردم بیش‌ازحد درباره‌اش فکر می‌کنند. اینجا نسخه‌ی ساده است:

Polling (start_polling، که کد بالا استفاده می‌کند) باعث می‌شود بات از تلگرام روی یک اتصال طولانی‌عمر بپرسد «چیز جدیدی هست؟». به هیچ‌چیز جز اینترنت خروجی نیاز ندارد — بدون دامنه، بدون TLS، بدون پورت ورودی باز. پشت NAT خوب اجرا می‌شود. برای اکثریت قاطع بات‌ها، این درست است و باید همین‌جا بایستید.

Webhook باعث می‌شود تلگرام به‌روزرسانی‌ها را به شما push کند، که یعنی باید یک endpoint عمومی HTTPS در معرض بگذارید. این به یک دامنه و یک پورت ورودی قابل‌دسترس نیاز دارد — پس یا یک IP عمومی اختصاصی یا یک reverse proxy جلویش. راه‌اندازی بیشتر، چیزهای بیشتری که خراب می‌شوند. سودش تأخیر کمتر و سربار کمتر در مقیاس بزرگ است — هزاران کاربر هم‌زمان، حجم به‌روزرسانی سنگین.

قانون عملی: با polling روی یک پلن NAT شروع کنید. فقط وقتی به webhook بروید که واقعاً از polling بزرگ‌تر شده باشید — و اگر رفتید، آنجاست که یک IP اختصاصی جایش را توجیه می‌کند، چون به آن endpoint ورودی HTTPS نیاز دارید.

اجرایش چقدر خرج دارد

یک بات polling سبک است. روی long-poll تلگرام بی‌کار می‌ماند و به پیام‌ها واکنش نشان می‌دهد، پس دستگاه عمدتاً منتظر است:

ثبت‌نام فقط با ایمیل است و با USDC یا USDT روی Base یا Ethereum پرداخت می‌کنید — بدون کارت، بدون کارت شناسایی. یک کارت هم کار می‌کند، اما on-ramp حداقل حدود ۲۷ دلاری دارد، پس برای یک پلن ۳ دلاری روان‌تر است که یک‌بار یک موجودی کوچک شارژ کنید و بگذارید تمدیدها از آن برداشت کنند. فقط CPU است، یک دیتاسنتر در آلمان — برای یک بات بی‌اهمیت، ارزش دانستن دارد اگر به یک GPU یا یک منطقه‌ی خاص نیاز داشتید.

نتیجه‌ی صادقانه

یک بات تلگرام یکی از ارزان‌ترین چیزهایی است که می‌توانید خودمیزبانی کنید: یک دستگاه ۳ دلاری، یک واحد systemd، و polling به شما یک باتی می‌دهد که در طول کرش‌ها و ری‌بوت‌ها بدون بچه‌داری کردن شما آنلاین است. فقط وقتی به یک webhook و یک پلن بزرگ‌تر دست ببرید که مقیاس واقعاً مجبورتان کند — نه چون یک آموزش به شما گفت webhookها «بهترند». دستگاه کوچک را بگیرید، توکن را در یک فایل env نگه دارید، بگذارید systemd آپتایم را مدیریت کند، و — پیش از هر چیز — چک‌لیست امنیتی VPS جدید را اجرا کنید تا خود دستگاه قفل شود.


آماده‌ی میزبانی مال خودتان؟ یک بات تلگرام به‌سختی از منابع استفاده می‌کند — پلن Nano (۳ دلار در ماه) آن را ۲۴/۷ بدون دردسر اجرا می‌کند.

سؤالات متداول

polling یا webhook — کدام را باید استفاده کنم؟

با polling شروع کنید. از هر دستگاهی با اینترنت خروجی کار می‌کند — بدون دامنه، بدون پورت باز، بدون TLS — و برای اکثر بات‌ها کاملاً کافی است. فقط وقتی که در مقیاس بزرگ اجرا می‌کنید (هزاران کاربر) یا به کمترین تأخیر ممکن نیاز دارید به webhook سوییچ کنید؛ یک webhook به یک endpoint عمومی HTTPS نیاز دارد، که یعنی یک دامنه و یک پورت ورودی قابل‌دسترس (یک IP اختصاصی، یا یک reverse proxy)، پس اجزای متحرک بیشتری دارد. برای ۹۵٪ بات‌ها، polling روی یک VPS کوچک پاسخ درست است.

آیا برای یک بات تلگرام به IP اختصاصی یا دامنه نیاز دارم؟

برای polling نه — بات فقط تماس‌های خروجی به تلگرام می‌گیرد، پس یک پلن NAT با SSH پورت‌فوروارد کافی است. فقط اگر به حالت webhook سوییچ کنید به یک endpoint عمومی HTTPS نیاز دارید (دامنه + پورت ورودی، یعنی یک IP اختصاصی یا reverse proxy). اکثر بات‌ها هرگز به آن نیاز ندارند.

یک بات aiogram چه اندازه VPS نیاز دارد؟

کوچک‌ترین. یک بات polling عمدتاً منتظر long-poll تلگرام است، پس ۱ vCPU / ۱ گیگابایت (یک Nano سه‌دلاری) اکثر بات‌ها را راحت مدیریت می‌کند. فقط وقتی بزرگ‌تر شوید که خود بات کار سنگین انجام می‌دهد — یک پایگاه‌داده، پردازش رسانه، یا یک مدل محلی — که شما را به‌سمت ۲ گیگابایت (۵ دلار) یا بیشتر هل می‌دهد.

چطور بات را پس از خروج از سیستم در حال اجرا نگه دارم؟

آن را به‌عنوان یک سرویس systemd با Restart=always اجرا کنید. اگر در ترمینالتان راه بیندازید وقتی SSH بسته شود می‌میرد؛ زیر systemd از خروج جان سالم به‌در می‌برد، در کرش ری‌استارت می‌شود، و بعد از ری‌بوت برمی‌گردد. این خط بین یک دمو و چیزی است که می‌توانید به آن تکیه کنید.

← بازگشت به وبلاگ← پلن‌ها و قیمت‌ها

نظرات

هنوز نظری نیست. اولین نفر باشید.

یک نظر بگذارید

نظرات پیش از نمایش بررسی می‌شوند.