aiogram / telegram-bot-api

Docker image of Telegram Bot API Server
https://hub.docker.com/r/aiogram/telegram-bot-api
153 stars 50 forks source link

API+Nginx for large files #10

Closed TopperBG closed 1 year ago

TopperBG commented 1 year ago

I'm trying hard to implement local telegram bot with TBA to serve larger than 20Mb files for Telegram bot based on PTB 13.9 Now I'm testing example stack API+Nginx but due to circumstances (apache2 vhost working on same machine) need to change port to 81. I've change it in docker-compose.yml

  nginx:
    image: nginx:1.19-alpine
    restart: always
    depends_on:
      - api
    volumes:
      - telegram-bot-api-data:/var/lib/telegram-bot-api
      - ./nginx:/etc/nginx/conf.d/
    ports:
      - "81:81"

and in Nginx default.conf:

upstream telegram-bot-api {
    server api:8081;
}

server {
    listen 81;
    server_name _;

Nevertheless I'm getting error_refused ? Am I missing something (noob in Nginx)

Edit: The stack IP should be public IP right? It's ok to setup telegram bot like: Updater(config["BOT_TOKEN"], use_context = True, base_url = "http://192.168.1.110:81/bot", base_file_url = "http://192.168.1.110:81/file/bot")

Edit: Nginx logs attached

192.168.1.110 - - [21/Mar/2023:06:35:44 +0000] "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1" 502 158 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"
2023/03/21 06:36:12 [error] 31#31: *21 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.110, server: telegram-bot-api.local, request: "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1", upstream: "http://192.168.1.110:8081/bot6225617464:<hidden-token>/sendMessage", host: "192.168.1.110:81"
192.168.1.110 - - [21/Mar/2023:06:36:12 +0000] "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1" 502 158 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"
2023/03/21 06:36:29 [error] 31#31: *23 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.110, server: telegram-bot-api.local, request: "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1", upstream: "http://192.168.1.110:8081/bot6225617464:<hidden-token>/sendMessage", host: "192.168.1.110:81"
192.168.1.110 - - [21/Mar/2023:06:36:29 +0000] "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1" 502 158 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"
2023/03/21 06:36:32 [error] 31#31: *25 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.110, server: telegram-bot-api.local, request: "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1", upstream: "http://192.168.1.110:8081/bot6225617464:<hidden-token>/sendMessage", host: "192.168.1.110:81"
192.168.1.110 - - [21/Mar/2023:06:36:32 +0000] "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1" 502 158 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"
2023/03/21 06:36:35 [error] 31#31: *27 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.110, server: telegram-bot-api.local, request: "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1", upstream: "http://192.168.1.110:8081/bot6225617464:<hidden-token>/sendMessage", host: "192.168.1.110:81"
192.168.1.110 - - [21/Mar/2023:06:36:35 +0000] "POST /bot6225617464:<hidden-token>/sendMessage HTTP/1.1" 502 158 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"
TopperBG commented 1 year ago

Things got resolved but anyway persist one strange behaviour. When made container only with TBA from that repo everythings are as intent to be - TELEGRAM_VERBOSITY, TELEGRAM_LOG_FILE or mainly TELEGRAM_LOCAL works and shown as command line options.

But when same things are added in example.yml to be build both TBA and Nginx seams that docker-entrypoint.sh isn't started as meant to be. Even described above options, the command line shows:

version: '3.7'

services:
  api:
    image: aiogram/telegram-bot-api:latest
    restart: always
    environment:
      TELEGRAM_API_ID: XXXXX
      TELEGRAM_API_HASH: XXXXXXXXXXXXXXXXX
      TELEGRAM_LOCAL: "true"
    volumes:
      - telegram-bot-api-data:/var/lib/telegram-bot-api

  nginx:
    image: nginx:1.19-alpine
    restart: always
    depends_on:
      - api
    volumes:
      - telegram-bot-api-data:/var/lib/telegram-bot-api
      - ./nginx:/etc/nginx/conf.d/
    ports:
      - "81:81"

volumes:
  telegram-bot-api-data:

telegram-bot-api --http-port 8081 --dir=/var/lib/telegram-bot-api --temp-dir=/tmp/telegram-bot-api --username=telegram-bot-api --groupname=telegram-bot-api That's not expected behaviour.

TopperBG commented 1 year ago

It seems problem become form Nginx config, logs shows dublication of paths:

2023/04/04 11:15:52 [error] 30#30: *15 open() "/var/lib/telegram-bot-api/TOKEN_ID:TOKEN_HASH/var/lib/telegram-bot-api/TOKEN_ID:TOKEN_HASH/documents/file_16.apk" failed (2: No such file or directory), client: 172.19.0.4, server: _, request: "GET /file/botTOKEN_ID%3ATOKEN_HASH//var/lib/telegram-bot-api/TOKEN_ID%3ATOKEN_HASH/documents/file_16.apk HTTP/1.1", host: "nginx:81"
172.19.0.4 - - [04/Apr/2023:11:15:52 +0000] "GET /file/botTOKEN_ID%3ATOKEN_HASH//var/lib/telegram-bot-api/TOKEN_ID%3ATOKEN_HASH/documents/file_16.apk HTTP/1.1" 404 154 "-" "Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)"

But this works flowlessly ? curl -i http://nginx:81/file/botTOKEN_ID:TOKEN_HASH/documents/file_16.apk

HTTP/1.1 200 OK Server: nginx/1.19.10 Date: Tue, 04 Apr 2023 14:31:01 GMT Content-Type: application/octet-stream Content-Length: 10066456 Last-Modified: Tue, 04 Apr 2023 06:26:47 GMT Connection: close ETag: "642bc327-999a18" Accept-Ranges: bytes

Warning: Binary output can mess up your terminal. Use "--output -" to tell Warning: curl to output it to your terminal anyway, or consider "--output Warning: " to save to a file.

mykolasolodukha commented 1 year ago

@TopperBG any idea how to solve this?

mykolasolodukha commented 1 year ago

@TopperBG I fixed that. I slightly changed the nginx configuration, removing the redundant part in the $uri, which is /var/lib/telegram-bot-api/. Here are the updated lines 29-32 of the default.conf file:

    location ~* \/file\/bot\d+:(.*) {
        rewrite ^/file\/bot[^/]+\/var\/lib\/telegram-bot-api(.*) /$1 break;
        try_files $uri @files;
    }

Hope that helps 🙂

TopperBG commented 1 year ago

Actualy my problem became not from wrong Nginx config or rewrite but I should realize that ones file was received I shouldn't .download it but use it localy eg:

localFile = context.bot.get_file(update.message.document.file_id)
file_path  = "/var/lib/telegram-bot-api/"+config["BOT_TOKEN"]+"/documents/" + localFile.file_path.split("/")[-1]
zvirja commented 7 months ago

In case anybody will be searching for the solution, this is my configuration with telegram-bot-api + nginx + Traefik.

docker-compose.yml

version: '3.7'

services:
  api:
    image: aiogram/telegram-bot-api:latest
    restart: always
    environment:
      TELEGRAM_API_ID: "<api>"
      TELEGRAM_API_HASH: "<hash>"
    volumes:
      - ./data:/var/lib/telegram-bot-api
    labels:
      traefik.enable: "true"
      traefik.http.routers.telegram-bot-api.rule: "Host(`myhost.com`) && PathPrefix(`/bot`)"
      traefik.http.routers.telegram-bot-api.entrypoints: "public"

  nginx:
    image: nginx
    restart: always
    volumes:
      - ./data:/var/lib/telegram-bot-api
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    labels:
      traefik.enable: "true"
      traefik.http.routers.telegram-bot-api-nginx.rule: "Host(`myhost.com`) && PathPrefix(`/file/`)"
      traefik.http.routers.telegram-bot-api-nginx.entrypoints: "public"

nginx.conf:

# use $sanitized_request instead of $request to hide Telegram token
log_format token_filter '$remote_addr - $remote_user [$time_local] '
                        '"$sanitized_request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';

server {
    listen 80;
    server_name _;

    chunked_transfer_encoding on;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;
    proxy_read_timeout 600;
    send_timeout 600;
    client_max_body_size 2G;
    client_body_buffer_size 30M;
    keepalive_timeout 0;

    set $sanitized_request $request;
    if ( $sanitized_request ~ (\w+)\s(\/bot\d+):[-\w]+\/(\S+)\s(.*) ) {
        set $sanitized_request "$1 $2:<hidden-token>/$3 $4";
    }
    access_log /var/log/nginx/access.log token_filter;

    location ~* \/file\/bot\d+:(.*) {
        rewrite ^/file\/bot(.*) /$1 break;
        try_files $uri @files;
    }

    location / {
        return 404;
    }

    location @files {
        root /var/lib/telegram-bot-api;
        gzip on;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 64 8k;
        gzip_http_version 1.1;
        gzip_min_length 1100;
    }
}

Hope that will help somebody to save their time 😉

shahradelahi commented 7 months ago

Hello @zvirja,

Thank you for the code snippets, I really appreciate it.

Your nginx config file handles file rewrites perfectly. However, for the rest of the requests, I am redirecting them to the API server itself using the following code:

    location / {
--      return 404;
++      proxy_pass http://api:8081;
    }

I hope this tip will be helpful for others as well.