0ralo
@0ralo
Python backend developer

Как настроить nginx для Django + telegram webhooks?

Короче 2 дня сижу уже, не могу ничего понять. У меня есть сайт там nginx + django + postgres + redis ... всё это по контейнерам раскидано и в компосе лежит.
docker-compose.yml
version: '3.7'

services:
    postgres:
        container_name: postgres
        build:
            context: docker/postgres
            dockerfile: Dockerfile
        environment:
            - POSTGRES_PASSWORD=testpass
        volumes:
            - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
        expose:
            - "5432"

    web:
        container_name: web
        build:
            context: deploy/
            dockerfile: Dockerfile
        volumes:
            - ./:/usr/src/app
        entrypoint: /usr/src/app/deploy/entrypoint.sh
        depends_on:
            - postgres
            - celery-worker

    nginx:
        container_name: nginx
        build:
            context: docker/nginx
            dockerfile: Dockerfile
        depends_on:
            - web
        ports:
            - "443:443"
            - "80:80"
        volumes:
            - ./static/:/static/
            - ./media/:/media/
            - ./data/certbot/conf:/etc/letsencrypt
            - ./data/certbot/www:/var/www/certbot

    certbot:
        container_name: certbot
        image: certbot/certbot
        volumes:
            - ./data/certbot/conf:/etc/letsencrypt
            - ./data/certbot/www:/var/www/certbot

    redis:
        container_name: redis
        image: "redis:alpine"
        expose:
            - "6379"
        restart: always

    celery-worker:
        container_name: celery-worker
        restart: always
        build:
            context: deploy
            dockerfile: Dockerfile
        entrypoint: /usr/src/app/deploy/celeryworker.sh
        volumes:
            - ./:/usr/src/app
        depends_on:
            - redis

    celery-beat:
        container_name: celery-beat
        restart: always
        build:
            context: deploy
            dockerfile: Dockerfile
        entrypoint: /usr/src/app/deploy/celerybeat.sh
        volumes:
            - ./:/usr/src/app
        depends_on:
            - redis
            - celery-worker

    flower:
        container_name: flower
        restart: always
        build:
            context: deploy
            dockerfile: Dockerfile
        entrypoint: /usr/src/app/deploy/flower.sh
        volumes:
            - ./:/usr/src/app
        ports:
            - "5555:5555"
        depends_on:
            - celery-worker


Сам сайт работает прекрасно статика, медиа сам джанго короче всё нормально. Но вот я хочу поставить на хостинг еще и вебхук бота телеграм. Для примера, пытался запустить хотябы эхо бота
main.py
import logging
from os import getenv

from aiohttp.web import run_app
from aiohttp.web_app import Application
from aiogram.types import Message, FSInputFile
from aiogram import Bot, Dispatcher
from aiogram.types import MenuButtonWebApp, WebAppInfo
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application

APP_BASE_URL = "https://0ralo.ru"
TELEGRAM_TOKEN = "42:Universe"  # Debug token

dispatcher = Dispatcher()


async def on_startup(bot: Bot, base_url: str):
	await bot.set_chat_menu_button(
		menu_button=MenuButtonWebApp(text="Open Menu", web_app=WebAppInfo(url=f"{base_url}/captcha"))
	)
	await bot.set_webhook(
		f"{base_url}/webhook",
		certificate=FSInputFile("/etc/letsencrypt/live/0ralo.ru/fullchain.pem") # <b>Эта строчка для теста, без нее и с ней результат одинаковый</b>
	)


async def on_shutdown(bot: Bot, base_url: str):
	await bot.delete_webhook()


def main():
	bot = Bot(token=TELEGRAM_TOKEN, parse_mode="HTML")
	dispatcher["base_url"] = APP_BASE_URL
	dispatcher.startup.register(on_startup)
	dispatcher.shutdown.register(on_shutdown)

	app = Application()
	app["bot"] = bot

	SimpleRequestHandler(
		dispatcher=dispatcher,
		bot=bot,
	).register(app, path="/webhook")
	setup_application(app, dispatcher, bot=bot)

	run_app(app, host="127.0.0.1", port=8001)


@dispatcher.message()
async def echo(message: Message):
	await message.answer(message.text)


if __name__ == "__main__":
	logging.basicConfig(level=logging.INFO)
	main()

Nginx конфиг дописал такой
nginx.conf
upstream web {
        server web:8000;
}

#От сюда
upstream bot{
        server 127.0.0.1:8001; # 0.0.0.0:8001 тоже пробовал
}
#До сюда

server {
        listen 80;
        server_name www.0ralo.site 0ralo.site;

        location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
                return 301 https://0ralo.ru$request_uri;
    }

}


server {
        listen 443 ssl;
        client_max_body_size 20M;
        server_name 0ralo.ru;

        ssl_certificate /etc/letsencrypt/live/0ralo.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/0ralo.ru/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
                proxy_pass http://web;
                proxy_redirect off;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

                location /static/ {
                alias /static/;
        }

        location /media/ {
                autoindex on;
                alias /media/;
        }
# И вот тут еще
        location /webhook {
                proxy_pass http://bot/webhook;
        }
#Всё
}

Дописанные блоки выделил #.
Но ничего не работает как я хотел. Для проверки открыл порт и потыкал GET через браузер по ip:8001. app бота видит запросы. Но когда обращаюсь через https://0ralo.ru/webhook то нгинкс ловит запрос, но не может донести до app бота. Получаю 502 bad gateway/ Сертификат получал через let's encrypt/ . Это вроде получается не самописный. Короче был бы рад помощи или наставления, как подружить nginx с aiohttp сервером который лежит рядом. Кстати очень важное уточнение. Nginx - лежит в контейнере, а бот (скрипт) лежит на хосте. Я пробовал запускать бота в докере, эффект такой-же.
nginx log
nginx            | 2023/01/07 18:03:10 [error] 22#22: *4 connect() failed (111: Connection refused) while connecting to upstream, client: 91.108.6.133, server: 0ralo.ru, request: "POST /webhook HTTP/1.1", upstream: "http://0.0.0.0:8001/webhook", host: "0ralo.ru"
nginx            | 91.108.6.133 - - [07/Jan/2023:18:03:10 +0000] "POST /webhook HTTP/1.1" 502 157 "-" "-" "-"
  • Вопрос задан
  • 1073 просмотра
Пригласить эксперта
Ответы на вопрос 1
fzfx
@fzfx
18,5 дм
попробуйте заменить
proxy_pass http://bot/webhook;
на
proxy_pass http://bot;
или на
proxy_pass http://bot/;
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы