
به اشتراک بگذارید

به اشتراک بگذارید
میزبانی ربات بله یعنی اجرای همان برنامهای که به API پیامرسان وصل میشود، روی سروری که مدیریتش دست خودتان است. برای ربات روبیکا و ربات ایتا هم قاعده عوض نمیشود. پیامرسان فقط پیام را به شما میرساند؛ اجرای مداوم فرایند، گواهی TLS، لاگ و بالاآوردن دوباره بعد از خطا کار سرور شماست.
| پرسش | پاسخ کوتاه |
|---|---|
| چه چیزی روی سرور اجرا میشود؟ | فرایند ربات خودتان، نه زیرساخت پیامرسان |
| دریافت پیام با چه مدلی؟ | وبهوک برای تولید، دریافت دورهای برای توسعه |
| پیشنیاز وبهوک | دامنه، گواهی TLS معتبر، IP ثابت و یک وبسرور |
| نگهداری فرایند | سرویس systemd با ریاستارت خودکار و لاگ در journald |
| چه چیزی تأیید نشده | جزئیات API سه پیامرسان؛ مستنداتشان باز نشد |
💡 پیش از هر چیز، یک تفکیک ساده
ربات پیامرسان دو تکه دارد: سرور خود پیامرسان و فرایندی که شما مینویسید. تکه دوم باید جایی زنده بماند.
✅ تا وقتی ربات روی لپتاپ یا محیط موقت اجرا میشود، هر خواب رفتن سیستم یعنی قطع سرویس.
✅ سرور مجازی ایران وبداده امکان تست ساعتی رایگان دارد؛ همین مسیر استقرار را پیش از تصمیم روی یک سرور واقعی اجرا کنید.
بخش سخت این کار، نوشتن کد ربات نیست؛ زنده نگهداشتن آن و رساندن پیامها به آن است. در ادامه اول معماری ربات را باز میکنیم و دو مدل دریافت پیام را میسنجیم. بعد پیشنیازهای سرور را با فرمانهای صدور گواهی و تنظیم nginx میآوریم و آخر سر یک سرویس systemd مینویسیم. هر جا مستندات رسمی خود پیامرسان را نتوانستیم باز کنیم، همان را صریح نوشتهایم.
📌 آنچه در این مقاله میخوانید
◀️ معماری ربات پیامرسان روی سرور
◀️ انتخاب بین وبهوک و دریافت دورهای
◀️ پیشنیازهای سرور و گواهی TLS
◀️ استقرار با systemd، لاگ و ریاستارت

هر ربات پیامرسان از سه جزء ساخته میشود: سرور API که خود پیامرسان اداره میکند، فرایند ربات شما که روی سرور خودتان اجرا میشود، و مسیری که پیام را از اولی به دومی میرساند. تنها جزء کامل در اختیار شما، دومی است؛ پس پایداری ربات همانجا تعیین میشود.
تصور کنید ربات مثل اپراتوری است که پشت یک خط داخلی نشسته و پیامرسان نقش مرکز تلفن را دارد؛ اگر اپراتور سر جایش نباشد، مرکز تلفن کاری از پیش نمیبرد. کار اصلی استقرار هم همین است: کد شما باید بینظارت و روزهای متوالی سر پا بماند.
هر پاسخ ربات یک رفتوبرگشت شبکه تا API پیامرسان دارد؛ هرچه این مسیر کوتاهتر باشد، گفتوگوهای چندمرحلهای روانتر پیش میرود. محل میزبانی زیرساخت بله، روبیکا و ایتا را در هیچ سند قابل استنادی پیدا نکردیم، پس آن را از پیشفرض نگیرید. کار درست این است که زمان پاسخ همان API را از روی یک سرور مجازی ایرانی و از روی گزینههای دیگر اندازه بگیرید.
🔸 نکته فنی؛ مصرف منابع ربات متوازن نیست
ترافیک ورودی ربات کوچک است، اما خروجی وقتی ربات فایل یا گزارش میفرستد سنگین میشود.
پس منابع را بر اساس کاری که ربات با هر پیام میکند بسنجید، نه تعداد کاربر.
در مدل وبهوک، سرور پیامرسان هر پیام تازه را به یک نشانی HTTPS روی سرور شما میفرستد. در مدل دریافت دورهای، برنامه شما مرتب از API میپرسد «پیام جدیدی هست؟». برای سرویس واقعی وبهوک درستتر است و دریافت دورهای برای توسعه.
مکانیزم هر دو مدل را بهروشنی میتوان در مستندات Bot API تلگرام دید. پیامها با درخواست POST روی HTTPS به نشانی اعلامشده فرستاده میشوند، و در تلگرام تا وقتی وبهوک فعال است، متد دریافت دورهای چیزی تحویل نمیدهد. همان مستندات پورتهای مجاز وبهوک تلگرام را ۴۴۳، ۸۰، ۸۸ و ۸۴۴۳ و بازه اتصال همزمان را ۱ تا ۱۰۰ با پیشفرض ۴۰ اعلام میکند (مستندات Bot API تلگرام). این اعداد و این رفتار متعلق به تلگرام است و آن را به حساب بله، روبیکا یا ایتا نگذارید.
⚠️ چیزی که در این اجرا تأیید نشد
مستندات توسعهدهنده بله، روبیکا و ایتا از این محیط باز نشد (پاسخ نداد یا با robots بسته بود). پس هیچ اندپوینت، نام متد، سهمیه نرخ یا پورتی برای این سه پیامرسان در متن نیامده است.
✅ کاری که باید بکنید: پورت مجاز، سهمیه نرخ و روش ثبت وبهوک را از مستندات رسمی و پنل توسعهدهنده همان پیامرسان بردارید.
❌ کاری که نکنید: کپیکردن اعداد تلگرام یا یک نمونه کد اینترنتی به جای مستندات رسمی.
| معیار | وبهوک | دریافت دورهای |
|---|---|---|
| تأخیر پاسخ | کمترین؛ تحویل بهمحض رسیدن پیام | وابسته به فاصله هر درخواست |
| پیشنیاز شبکه | دامنه، گواهی TLS و پورت باز ورودی | فقط دسترسی خروجی به API |
| هزینه پردازشی وقتی پیامی نیست | نزدیک صفر | درخواست پیوسته و بیحاصل |
| رفتار در قطع موقت | بسته به سیاست خود پیامرسان | برنامه بعد از وصلشدن ادامه میدهد |
| مناسب برای | سرویس واقعی روی سرور ثابت | توسعه و تست سریع |
رباتهایی که با دریافت دورهای نوشته شدهاند، معمولاً بدون تغییر منطق به وبهوک منتقل میشوند؛ فقط لایه ورودی عوض میشود. برای همین در میزبانی ربات بله و دو پیامرسان دیگر، از روز اول لایه دریافت پیام را از منطق پاسخ جدا نگه دارید. برای هر ربات هم فقط یک مصرفکننده پیام فعال بگذارید: پیش از آزمایش محلی، وبهوک را از پنل همان پیامرسان بردارید و بعد از پایان کار دوباره ثبتش کنید.

برای دریافت وبهوک به چهار چیز نیاز دارید: یک زیردامنه که به IP سرور اشاره کند، یک گواهی TLS معتبر برای همان زیردامنه، یک IP ثابت و یک وبسرور. وبسرور درخواست پیامرسان را میگیرد و به فرایند ربات میدهد.
نقطه شروع میزبانی ربات بله روی سرور، یک زیردامنه اختصاصی مثل bot.example.ir است که رکورد A آن روی IP سرور نشسته باشد. اگر IPv6 هم دارید، رکورد AAAA را اضافه کنید. سرور مجازی ایران وبداده IP مستقیم دارد که از اینترنت بینالملل هم در دسترس است و IPv4 و IPv6 را پشتیبانی میکند؛ همین برای یک نقطه پایانی وبهوک کافی است.
گواهی رایگان از Let’s Encrypt برای این کار کافی است، اما باید روش صدور را درست انتخاب کنید. طبق مستندات Let’s Encrypt، چالش HTTP-01 فقط روی پورت ۸۰ انجام میشود و تا ۱۰ ریدایرکت را دنبال میکند. همین چالش گواهی wildcard صادر نمیکند و اگر پورت ۸۰ بسته باشد، شکست میخورد. چالش DNS-01 گواهی wildcard میدهد و برای سروری که وبسرورش عمومی نیست مناسب است، اما به یک ارائهدهنده DNS با API نیاز دارد. چون نگهداشتن اعتبارنامه کامل DNS روی وبسرور ریسک دارد، دسترسی را محدود بدهید (مستندات Let’s Encrypt درباره انواع چالش). همین مستندات تصریح میکند DNS-01 برای IP اعتبارسنجی نمیکند.
برای مسیر ساده، در فایل /etc/nginx/conf.d/bot.conf یک بلوک سرور روی پورت ۸۰ بسازید که فقط پوشه چالش را سرو کند و بقیه را به HTTPS بفرستد.
server {
listen 80;
server_name bot.example.ir;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
بعد گواهی را با کلاینت رسمی ACME بگیرید. طبق مستندات certbot، فرم فرمان با افزونه webroot، آزمایش تمدید و بررسی زمانبندی تمدید اینهاست.
sudo certbot certonly --webroot -w /var/www/html -d bot.example.ir
sudo certbot renew --dry-run
systemctl list-timers | grep -i certbot
فرایند ربات را روی ۱۲۷.۰.۰.۱ و یک پورت داخلی bind کنید و nginx را جلوی آن بگذارید. طبق مستندات nginx، دستور proxy_pass نشانی سرور پشتی را تعیین میکند و هدرهای Host و Connection پیشفرض بازنویسی میشوند (مستندات ماژول proxy در nginx)؛ پس Host اصلی را صریح ست کنید. پیشفرض proxy_read_timeout همان مستندات ۶۰ ثانیه است؛ برای پاسخهای طولانی، کار سنگین را به یک سرویس worker جدا بسپارید.
server {
listen 443 ssl;
server_name bot.example.ir;
ssl_certificate /etc/letsencrypt/live/bot.example.ir/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bot.example.ir/privkey.pem;
client_max_body_size 20m;
location /hook-9f3a7c2b/ {
proxy_pass http://127.0.0.1:8080/hook/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
sudo nginx -t && sudo systemctl reload nginx
نشانی وبهوک را حدسنزدنی بگذارید؛ یک مسیر طولانی و تصادفی بهجای /hook. برای ربات دوم، یک location دیگر با پورت داخلی جداگانه اضافه کنید. اگر پیامرسان هدر امنیتی اختصاصی میفرستد، آن را فعال و در برنامه بررسی کنید؛ مستندات تلگرام چنین هدری دارد.
تا وقتی نشانی وبهوک را به پیامرسان اعلام نکنید، هیچ درخواستی به سرور نمیرسد. روش این اعلام در هر پیامرسان متفاوت است و چون مستندات رسمی این سه باز نشد، نام متد و قالب درخواستش را نمینویسیم. نشانی کامل HTTPS را از پنل توسعهدهنده همان پیامرسان ثبت کنید و بعد با لاگ nginx مطمئن شوید درخواست میرسد.
⚠️ سه تنظیمی که ربات را آسیبپذیر میکند
❌ اجرای فرایند ربات با کاربر root یا شنیدن مستقیم روی ۰.۰.۰.۰ بدون وبسرور جلو.
❌ خاموشکردن بررسی گواهی در سمت برنامه برای «رفع سریع خطا»؛ این کار خطا را پنهان میکند، نه حل.
❌ محدودکردن فایروال به رنج IP حدسی پیامرسان؛ تا وقتی رنج رسمی اعلامشده در دست ندارید، نتیجهاش قطع تحویل است.

در میزبانی ربات بله و هر ربات پیامرسان دیگر، فرایند را بهعنوان یک سرویس systemd اجرا کنید. اینطور با بالا آمدن سرور خودش شروع میشود، بعد از خطا دوباره اجرا میشود و لاگش در journald جمع میشود.
یک کاربر سیستمی بدون شل بسازید، محیط مجازی پایتون را با venv بالا بیاورید و فایل تنظیمات حساس را فقط برای همان کاربر خواندنی کنید.
sudo useradd -r -s /usr/sbin/nologin -d /srv/bot botuser
sudo install -d -o botuser -g botuser /srv/bot
sudo -u botuser python3 -m venv /srv/bot/.venv
sudo -u botuser /srv/bot/.venv/bin/pip install -r /srv/bot/requirements.txt
sudo install -o botuser -g botuser -m 600 /dev/null /srv/bot/.env
sudo chown -R botuser:botuser /srv/bot
توکن و تنظیمات حساس را در همان فایل.env بگذارید و با EnvironmentFile به سرویس بدهید، نه در کد و نه در مخزن گیت. نسخه کتابخانهها را هم در فایل نیازمندیها قفل کنید. تنظیم پایه سیستمعامل و فایروال در این مقاله نمیگنجد؛ اگر سرور را تازه گرفتهاید، راهنمای خرید و انتخاب سرور مجازی لینوکس ترتیب کارهای اولیه را میدهد.
فایل یونیت را در /etc/systemd/system/bot.service بسازید.
[Unit]
Description=Messenger bot worker
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=exec
User=botuser
Group=botuser
WorkingDirectory=/srv/bot
EnvironmentFile=/srv/bot/.env
ExecStart=/srv/bot/.venv/bin/python -m bot
Restart=on-failure
RestartSec=5
NoNewPrivileges=yes
ProtectSystem=full
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
چند انتخاب در این فایل عمدی است. طبق مستندات systemd، مقدار Restart میتواند no، on-success، on-failure، on-abnormal، on-watchdog، on-abort یا always باشد و پیشفرضش no است. مقدار on-failure بعد از خروج با کد غیرصفر، کشتهشدن با سیگنال، تایماوت عملیات یا تایماوت watchdog سرویس را دوباره بالا میآورد؛ در حالی که always حتی بعد از خروج سالم هم ریاستارت میکند. پیشفرض RestartSec برابر ۱۰۰ میلیثانیه است. همان مستندات تأکید میکند ریاستارتها تابع محدودیت نرخ StartLimitIntervalSec و StartLimitBurst هستند (مستندات systemd.service). این دو کلید در مستندات systemd.unit زیر [Unit] آمدهاند، نه [Service]؛ در جای اشتباه نادیده میشوند و محدودیت نرخ اعمال نمیشود.
انتخاب Type=exec هم از همان مستندات میآید. در Type=simple سرویس بلافاصله بعد از fork «شروعشده» حساب میشود. پس systemctl start ممکن است موفق گزارش دهد، در حالی که فایل اجرایی اجرا نشده یا کاربر وجود ندارد. مستندات برای سرویسهای بلندمدت Type=exec را توصیه میکند، چون همین خطاها را میگیرد. سه خط آخر بخش سرویس هم سختسازی است و در مستندات systemd.exec آمده: جلوگیری از گرفتن دسترسی بالاتر، خواندنیکردن /usr و /etc و دادن /tmp جدا. سطح سختگیرانهترش ProtectSystem=strict است که کل سیستم فایل را خواندنی میکند و مسیرهای لازم را با ReadWritePaths باز میکنید.
sudo systemctl daemon-reload
sudo systemctl enable --now bot.service
systemctl status bot.service
لاگ سرویس بدون هیچ تنظیم اضافه در journald مینشیند. طبق مستندات journalctl، گزینه -u خروجی را به یک یونیت محدود میکند و -f خطوط تازه را پیوسته چاپ میکند. گزینه –since بازه زمانی میگیرد؛ هم تاریخ کامل و هم کلیدواژههایی مثل yesterday یا زمان نسبی. گزینه -p هم بر اساس سطح پیام فیلتر میکند و یک سطح، همان سطح و سطوح مهمتر را شامل میشود (مستندات journalctl).
journalctl -u bot.service -f
journalctl -u bot.service --since -1h -p err
journalctl -u nginx --since today -p warning
ترتیب عیبیابی را ثابت نگه دارید: اول وضعیت سرویس و لاگ خودش، بعد لاگ دسترسی nginx، سپس تاریخ انقضای گواهی و آخر وضعیت ثبت وبهوک. اگر در لاگ nginx هیچ درخواستی نیست، مشکل در سرور شما نیست.
اجرای ربات بله، ربات روبیکا و ربات ایتا روی یک سرور درست است، به شرط جدا بودنشان: هر ربات یک کاربر سیستمی، یک پورت داخلی، یک یونیت و یک فایل محیطی جدا. اینطور خطای یکی بقیه را از کار نمیاندازد.
بیشترین زمان از دست رفته در استقرار ربات، کارهای زیرساختی است؛ مثل نصب دوباره سیستمعامل بعد از یک اشتباه یا دسترسی به کنسول وقتی شبکه رفته. پنل اختصاصی سرور مجازی ایران وبداده ریبوت، نصب مجدد سیستمعامل، حالت Rescue، کنسول VNC و اسنپشات و بازگردانی را در اختیار خودتان میگذارد؛ ارتقای منابع و تغییر IP هم بدون تیکت است. فعالسازی سرور به احراز هویت نیاز دارد و استفاده از آن برای VPN و پروکسی مجاز نیست.
پرسشهایی که پیش از استقرار بیشتر پرسیده میشود
مستندات تلگرام امکان بارگذاری گواهی عمومی self-signed را دارد، اما این را برای بله، روبیکا و ایتا از مستندات رسمیشان نتوانستیم تأیید کنیم. مسیر مطمئن، یک گواهی معتبر رایگان با تمدید خودکار است.
دادن یک عدد کلی گمراهکننده است. ربات پرسشوپاسخ متنی سبک است، اما رباتهایی که فایل میسازند یا پایگاه داده سنگین دارند چند برابر منابع میخواهند. با کم شروع کنید و بر اساس مصرف واقعی ارتقا بدهید.
دو علت شایع است: فرایند بدون سیاست ریاستارت بعد از یک خطا بالا نیامده، یا گواهی TLS منقضی شده است. سیاست Restart و تمدید خودکار گواهی هر دو را میپوشاند.
زیر بخش [Unit]. مستندات systemd.unit هر دو کلید StartLimitIntervalSec و StartLimitBurst را در همین بخش توضیح داده و در [Service] نادیده گرفته میشوند. سرویسی که به سقف بخورد، تا پایان بازه یا اجرای systemctl reset-failed بالا نمیآید.
در تلگرام نه؛ مستندات صریح میگوید تا وقتی وبهوک فعال است، متد دریافت دورهای چیزی تحویل نمیدهد. رفتار بله، روبیکا و ایتا را تأیید نکردهایم، اما قاعده سالم این است که برای هر ربات فقط یک مصرفکننده پیام فعال باشد.
لاگ دسترسی nginx را ببینید. اگر درخواست ثبت شده و پاسخ ۵xx گرفته، مشکل در برنامه شماست؛ اگر هیچ درخواستی ثبت نشده، ایراد در ثبت وبهوک، دامنه، گواهی یا سمت پیامرسان است.
سندی که محل میزبانی زیرساخت این سه سرویس یا سیاستشان نسبت به مبدأ درخواست ربات را روشن کند، به دست نیامد. پس به حدس تکیه نکنید؛ زمان پاسخ API را از هر دو گزینه اندازه بگیرید.
جمعبندی؛ آنچه میزبانی ربات بله را پایدار میکند دو تصمیم، سرنوشت ربات را روی سرور تعیین میکند: مدل دریافت پیام و روش نگهداری فرایند. برای سرویس واقعی وبهوک را انتخاب کنید و پیشنیازهایش را کامل فراهم کنید: یک زیردامنه، گواهی TLS معتبر با تمدید خودکار، IP ثابت و nginx جلوی برنامه. فرایند ربات را با کاربر بدون شل و یک سرویس systemd اجرا کنید؛ ریاستارت را روی on-failure بگذارید، محدودیت نرخ را زیر [Unit] بنویسید و لاگ را با journalctl بخوانید. برای چند ربات، جداسازی کاربر، پورت و سرویس از خطای زنجیرهای جلو میگیرد. درباره API بله، روبیکا و ایتا هم یک قاعده را رعایت کنید: نام متد، سهمیه نرخ، پورت مجاز و روش ثبت وبهوک را فقط از مستندات رسمی و پنل توسعهدهنده همان پیامرسان بردارید. مستندات این سه پیامرسان در زمان نوشتن این مقاله باز نشد؛ به همین دلیل هیچ عددی از این دست در متن نیامده است. بقیه کار همان کارهای کلاسیک سروری است: پشتیبانگیری پیش از هر تغییر بزرگ و اندازهگیری مصرف واقعی.
🚀 اجرای ربات روی سرور ایران
برای اجرای ربات پیامرسان داخلی، سروری با IP مستقیم، پنل مدیریتی و امکان اسنپشات کار را ساده میکند. امکان تست ساعتی رایگان هم هست تا پیش از تصمیم، همین مسیر استقرار را روی سرور واقعی اجرا کنید.
اگر سوالی داشتید، در بخش نظرات با ما در ارتباط باشید.
منابع