راهنمای خرید و مقایسه

راه‌اندازی وب‌هوک ربات تلگرام با Nginx و SSL؛ از صفر تا دریافت اولین پیام

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۷ دقیقه

NginxSSLراهنمای خرید و مقایسهراه‌اندازی وب‌هوک رباتتلگرام با Nginx و SSL؛ ازصفر تا دریافت اولین پیاممجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

در روش Webhook، تلگرام هر پیام را با یک درخواست HTTPS به آدرس سرور شما می‌فرستد. برای راه‌اندازی، یک دامنه یا زیردامنه به سرور وصل کنید، با Certbot گواهی SSL بگیرید، در Nginx مسیر مخفی وب‌هوک را به برنامهٔ ربات روی 127.0.0.1 پراکسی کنید و با متد setWebhook آدرس و secret_token را به تلگرام معرفی کنید. تلگرام فقط به پورت‌های 443، 80، 88 و 8443 درخواست می‌فرستد.

Webhook چیست و چه فرقی با Polling دارد؟

ربات تلگرام دو راه برای دریافت پیام‌ها دارد. در روش Polling، برنامهٔ ربات مدام از سرورهای تلگرام می‌پرسد «پیام جدید داری؟». در روش Webhook، شما یک آدرس HTTPS به تلگرام می‌دهید و تلگرام هر پیام جدید را بلافاصله به آن آدرس می‌فرستد.

Webhook چند مزیت دارد: پاسخ‌گویی فوری‌تر، مصرف منابع کمتر (چون درخواست‌های بی‌نتیجهٔ مداوم وجود ندارد) و مقیاس‌پذیری بهتر، چون می‌توان چند نمونه از برنامه را پشت یک Load Balancer اجرا کرد. در مقابل، به دامنه، گواهی SSL و سروری نیاز دارد که از اینترنت در دسترس باشد. برای ربات‌های کوچک، Polling ساده‌تر است و راه‌اندازی آن را در اجرای ربات تلگرام با systemd توضیح داده‌ایم.

مسیر یک پیام در روش Webhook
پیامدرخواست HTTPSپراکسی داخلیکاربر تلگرامارسال پیامسرورهای تلگرامPOST به آدرس شماNginxHTTPS و مسیر مخفیبرنامهٔ ربات127.0.0.1:8080پیامدرخواست HTTPSپراکسی داخلیکاربر تلگرامارسال پیامسرورهای تلگرامPOST به آدرس شماNginxHTTPS و مسیر مخفیبرنامهٔ ربات127.0.0.1:8080
شکل ۱ تلگرام پیام را خودش به سرور شما می‌فرستد؛ برنامهٔ ربات پشت Nginx و دور از دسترس مستقیم اینترنت است.

پیش‌نیازها

  • سروری که از اینترنت در دسترس است و به سرورهای تلگرام دسترسی دارد. نکات انتخاب سرور در راهنمای سرور ربات تلگرام آمده است.
  • یک دامنه یا زیردامنه، مثلاً bot.example.com، که رکورد A آن به آی‌پی سرور اشاره می‌کند.
  • Nginx نصب‌شده و پورت‌های 80 و 443 باز در فایروال.
  • توکن ربات از BotFather.

تلگرام فقط به پورت‌های 443، 80، 88 و 8443 درخواست وب‌هوک می‌فرستد. ساده‌ترین انتخاب، 443 است که Nginx روی آن گوش می‌دهد.

قدم ۱: گواهی SSL

تلگرام وب‌هوک را فقط روی HTTPS می‌فرستد. با Certbot گواهی رایگان Let's Encrypt بگیرید:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d bot.example.com

جزئیات و رفع خطاهای صدور گواهی در آموزش Nginx و Let's Encrypt آمده است. گواهی خودامضا هم با ارسال فایل گواهی به تلگرام ممکن است، اما گواهی معتبر ساده‌تر و کم‌دردسرتر است.

قدم ۲: تنظیم Nginx

برنامهٔ ربات (مثلاً با پایتون، Node.js یا Go) را طوری اجرا کنید که فقط روی 127.0.0.1 و پورتی داخلی مثل 8080 گوش دهد. سپس Nginx را برای عبور درخواست‌های وب‌هوک تنظیم کنید:

server {
    listen 443 ssl;
    http2 on;
    server_name bot.example.com;
    # ssl_certificate lines added by certbot

    location /tg/d8f3a1c9e2b7 {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        client_max_body_size 20M;
    }

    location / { return 404; }
}

مسیر /tg/d8f3a1c9e2b7 را با یک رشتهٔ تصادفی خودتان جایگزین کنید. مسیر غیرقابل حدس، اولین لایهٔ محافظت در برابر درخواست‌های جعلی است. هر آدرس دیگری پاسخ 404 می‌گیرد. پس از ذخیره:

sudo nginx -t && sudo systemctl reload nginx
راه‌اندازی در چهار قدم
  1. دامنه و SSL

    رکورد A برای زیردامنه و گواهی با Certbot.

  2. پیکربندی Nginx

    مسیر تصادفی به برنامه روی 127.0.0.1.

  3. setWebhook

    آدرس و secret_token را به تلگرام معرفی کنید.

  4. getWebhookInfo

    خطای آخر و پیام‌های در صف را بررسی کنید.

شکل ۲ پس از این چهار قدم، اولین پیام باید فوراً به برنامهٔ ربات برسد.

قدم ۳: معرفی وب‌هوک به تلگرام

با متد setWebhook از Bot API، آدرس را به تلگرام بدهید. پارامتر secret_token رشته‌ای است که تلگرام در هدر X-Telegram-Bot-Api-Secret-Token هر درخواست می‌فرستد؛ برنامهٔ شما باید آن را بررسی کند و درخواست‌های بدون این هدر را رد کند:

curl -s "https://api.telegram.org/bot$BOT_TOKEN/setWebhook" \
  -d "url=https://bot.example.com/tg/d8f3a1c9e2b7" \
  -d "secret_token=$WEBHOOK_SECRET" \
  -d "drop_pending_updates=true"

توکن ربات و رمز وب‌هوک را در متغیرهای محیطی نگه دارید و در تاریخچهٔ خط فرمان یا مخزن کد ذخیره نکنید. گزینهٔ drop_pending_updates پیام‌هایی را که در زمان قطعی جمع شده‌اند دور می‌ریزد؛ اگر به آن‌ها نیاز دارید، حذفش کنید.

قدم ۴: بررسی وضعیت

curl -s "https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo"

در پاسخ، به این فیلدها دقت کنید:

  • url: آدرسی که ثبت شده است.
  • pending_update_count: تعداد پیام‌هایی که تلگرام نتوانسته تحویل دهد. اگر مدام بالا می‌رود، مشکلی وجود دارد.
  • last_error_message و last_error_date: آخرین خطایی که تلگرام هنگام ارسال دیده است؛ مهم‌ترین سرنخ عیب‌یابی.

پاسخ سریع بدهید

تلگرام انتظار دارد سرور شما سریع با کد 200 پاسخ دهد. اگر پردازش هر پیام طولانی است (مثلاً فراخوانی یک API کند یا پردازش فایل)، ابتدا پاسخ 200 را برگردانید و کار سنگین را در صف یا پس‌زمینه انجام دهید. اگر پاسخ دیر برسد یا خطا برگردد، تلگرام همان پیام را دوباره ارسال می‌کند و ممکن است پیام‌های تکراری پردازش کنید.

root@server: ~
$ curl -s https://api.telegram.org/bot$BOT_TOKEN/getWebhookInfo{"ok":true,"result":{"url":"https://bot.example.com/tg/...","has_custom_certificate":false,"pending_update_count":0,"max_connections":40,"ip_address":"203.0.113.10"}}$ 
شکل ۳ pending_update_count صفر و نبودن last_error_message یعنی وب‌هوک سالم کار می‌کند.

رفع خطاهای رایج

  • SSL error / certificate verify failed: گواهی ناقص است یا زنجیرهٔ گواهی کامل نیست. از fullchain.pem استفاده کنید، نه فقط cert.pem.
  • Connection timed out: سرور از بیرون در دسترس نیست؛ فایروال، پورت و رکورد DNS را بررسی کنید. اگر سرور در ایران است، ممکن است دسترسی سرورهای تلگرام به آن محدود باشد؛ در این صورت سرور خارج انتخاب مطمئن‌تری است.
  • Wrong response from the webhook: 404: مسیر در Nginx با آدرس ثبت‌شده یکی نیست.
  • 502 Bad Gateway: برنامهٔ ربات اجرا نمی‌شود یا روی پورت دیگری است؛ رفع خطای 502 را ببینید.
  • پیام‌ها تکراری می‌رسند: برنامه دیر پاسخ می‌دهد یا خطا برمی‌گرداند.
  • getUpdates کار نمی‌کند: وقتی وب‌هوک فعال است، Polling غیرفعال می‌شود. برای برگشت به Polling، متد deleteWebhook را فراخوانی کنید.

اجرای پایدار برنامه

برنامهٔ ربات را با systemd یا PM2 اجرا کنید تا پس از خطا یا ری‌استارت سرور، خودکار بالا بیاید. روش systemd در راهنمای سرویس‌های systemd و روش PM2 در Node.js و PM2 توضیح داده شده است. یک مسیر سلامت (Health Check) هم بسازید و با ابزار پایشی، در دسترس بودن آن را بررسی کنید.

برای میزبانی ربات، یک سرور خارج کوچک لینوکسی معمولاً کافی است؛ صفحهٔ سرور برای ربات تلگرام جزئیات بیشتری دارد.

امنیت وب‌هوک

سه لایهٔ محافظت را با هم به کار ببرید: مسیر تصادفی و غیرقابل حدس، بررسی هدر secret_token در برنامه و محدود کردن اندازهٔ درخواست. برای لایهٔ اضافه، می‌توانید در Nginx فقط محدودهٔ آی‌پی‌هایی را که تلگرام در مستندات رسمی برای ارسال وب‌هوک اعلام کرده، مجاز کنید. هرگز توکن ربات را در آدرس وب‌هوک قرار ندهید؛ این آدرس ممکن است در لاگ‌ها ذخیره شود و توکن لو برود.

چند ربات روی یک سرور

اگر چند ربات دارید، لازم نیست برای هرکدام سرور یا دامنهٔ جداگانه بگیرید. هر ربات می‌تواند مسیر مخفی و پورت داخلی خودش را داشته باشد و Nginx با بلوک‌های location جداگانه، درخواست‌ها را به برنامهٔ درست برساند. فقط دقت کنید هر ربات secret_token متفاوتی داشته باشد و منابع سرور برای مجموع ربات‌ها کافی باشد.

مقیاس‌پذیری: وقتی ربات شلوغ می‌شود

یکی از مزیت‌های وب‌هوک این است که با افزایش کاربران، به‌راحتی قابل گسترش است. چون هر به‌روزرسانی یک درخواست HTTP مستقل است، می‌توانید چند پردازهٔ برنامه را پشت Nginx اجرا کنید و بار را بینشان تقسیم کنید. در پایتون، اجرای برنامه با چند worker (مثلاً از طریق gunicorn یا uvicorn) و در Node.js استفاده از حالت cluster در PM2 همین کار را می‌کند. فقط مراقب باشید که وضعیت گفت‌وگوی کاربران در حافظهٔ یک پردازه نگه داشته نشود؛ آن را در پایگاه داده یا Redis ذخیره کنید تا هر پردازه بتواند به هر پیام پاسخ دهد.

پارامتر max_connections در setWebhook تعیین می‌کند تلگرام حداکثر چند درخواست هم‌زمان به سرور شما بفرستد. برای ربات‌های کوچک مقدار پیش‌فرض کافی است؛ برای ربات‌های پرکاربر آن را متناسب با ظرفیت برنامه بالا ببرید. اگر کارهای سنگین مثل پردازش فایل یا فراخوانی سرویس‌های کند دارید، آن‌ها را به صف پس‌زمینه بسپارید و به تلگرام بلافاصله پاسخ دهید تا درخواست‌ها انباشته نشوند.

انتقال از Polling به Webhook بدون قطعی

اگر ربات شما الان با polling کار می‌کند، انتقال را مرحله‌ای انجام دهید. ابتدا Nginx و گواهی را آماده و نسخهٔ وب‌هوکی برنامه را روی سرور اجرا کنید. سپس پردازهٔ polling را متوقف و بلافاصله setWebhook را فراخوانی کنید. تلگرام به‌روزرسانی‌های در صف را تا مدتی نگه می‌دارد، پس پیامی که در این فاصله ارسال شده از دست نمی‌رود. اگر مشکلی پیش آمد، با deleteWebhook به حالت polling برگردید. یادتان باشد که این دو حالت هم‌زمان کار نمی‌کنند: تا وقتی وب‌هوک فعال است، getUpdates خطا برمی‌گرداند.

برای میزبانی، سرور ایران با تأخیر کم برای کاربران داخلی و صورتحساب ساعتی گزینهٔ مناسبی برای آزمایش و اجرای ربات است؛ جزئیات بیشتر در صفحهٔ سرور برای ربات تلگرام آمده است.

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

Webhook بهتر است یا Polling؟

برای ربات‌های پرمخاطب و سرورهایی که دامنه و SSL دارند، Webhook کارآمدتر است. برای ربات‌های کوچک یا زمان توسعه، Polling ساده‌تر است و به دامنه نیاز ندارد. مقایسهٔ کامل در مقالهٔ مربوطه آمده است.

تلگرام به چه پورت‌هایی وب‌هوک می‌فرستد؟

فقط به پورت‌های 443، 80، 88 و 8443. اگر برنامهٔ شما روی پورت دیگری است، آن را پشت Nginx روی 443 قرار دهید.

چطور بفهمم وب‌هوک درست کار می‌کند؟

متد getWebhookInfo را فراخوانی کنید؛ اگر last_error_message خالی است و pending_update_count صفر یا نزدیک صفر می‌ماند، وب‌هوک سالم است.

چرا بعد از فعال‌سازی وب‌هوک، getUpdates خطا می‌دهد؟

این دو روش هم‌زمان کار نمی‌کنند. تا وقتی وب‌هوک فعال است getUpdates خطای Conflict می‌دهد؛ برای استفاده از Polling ابتدا deleteWebhook را اجرا کنید.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.