Интеграция n8n с Telegram

В этой статье разберём, как связать n8n с Telegram: создать бота, принять запрос через Webhook и отправить пользователю ответ — текстом или файлом.

В каких случаях удобно использовать Telegram

Данная схема удобна, если вы уже давно пользуетесь Telegram и у вас там построена коммуникация с вашими клиентами. Также Telegram можно использовать как demo-доступ для новых клиентов, чтобы с минимальными усилиями продемонстрировать работу ваших ботов.

Что понадобится

  • Создать учётную запись my.telegram.org.
  • Созданный бот и API-ключ для него.
  • Виртуальный сервер в Европе для стабильной работы транспортного слоя Telegram.
  • Переменная окружения для хранения токена, например Telegram_BOT_TOKEN_LOGPARSER.

1. Создайте учётную запись Telegram API

Войдите в личный кабинет Telegram:

https://my.telegram.org/

Укажите ваш номер телефона, код входа придёт в Telegram.

Выберите API development tools, заполните форму и создайте ваш личный кабинет управления API-подключениями к Telegram.

Вам необходимо получить App api_id и App api_hash. Данные две настройки помогут вам настроить работу ваших ботов в дальнейшем.

На май 2026 года доступ к my.telegram.org для российских аккаунтов может быть нестабилен из-за сетевых ограничений и особенностей DNS. В некоторых случаях помогает явно указать адрес my.telegram.org в локальном файле hosts.

На вашем компьютере в файл hosts надо добавить запись:

149.154.167.220 my.telegram.org

Сохранить и перезагрузить компьютер.

Расположение файла:

C:\Windows\System32\drivers\etc\hosts

2. Создайте бота Telegram

В Telegram найдите @BotFather, должно быть не менее 8 млн подписчиков и синяя галочка. Отправьте ему следующие команды:

/start
/newbot
Namebot
Usernamebot

В ответ получите сообщение, что бот создан, и получите его API-ключ.

3. Создание буферной виртуальной машины VM Europe

Создаём промежуточный сервер для приёма сообщений в любой стране Европы. Провайдера выбирайте сами. Виртуальная машина нужна, чтобы вынести транспортный слой в отдельный внешний контур, не зависящий от пользовательских VPN-подключений и локальных сетевых особенностей.

1 ядро, 1 GB DDR, 50 GB SSD, Ubuntu 24.04 — более чем достаточно.

Установка базовых пакетов

cloud-init status --wait
apt update
apt upgrade -y
apt install -y curl jq ca-certificates gnupg rsync nano ufw python3-requests python3-flask

Docker устанавливаем на VM Europe, потому что Local Telegram Bot API удобнее держать отдельным контейнером.

apt remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc || true
apt update
apt install -y ca-certificates curl

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker

Рабочий каталог и файл окружения VM Europe

mkdir -p /opt/telegram-relay
cd /opt/telegram-relay

mkdir -p botapi-data relay-state buffer/Logparser/files buffer/Logparser/updates output-queue/{pending,processing,done,failed,suppressed}

chmod 700 /opt/telegram-relay/buffer

В файле окружения храним только параметры конкретного бота и общий секрет для связи с n8n.

sudo nano /opt/telegram-relay/.env
TELEGRAM_API_ID=<api_id_from_my_telegram_org>
TELEGRAM_API_HASH=<api_hash_from_my_telegram_org>
TELEGRAM_LOGPARSER_BOT_TOKEN=<bot_token_from_botfather>

ALLOWED_TELEGRAM_USER_IDS=<telegram_user_id_1>,<telegram_user_id_2>
LOGPARSER_MAX_FILE_MB=1500

N8N_RELAY_SHARED_SECRET=<random_64_hex_secret>
N8N_LOGPARSER_WEBHOOK_URL=https://automation.example.com:443/webhook/telegram-relay-logparser

TELEGRAM_OUTPUT_API_BIND=0.0.0.0
TELEGRAM_OUTPUT_API_PORT=444
chmod 600 /opt/telegram-relay/.env

Все токены, домены, секреты и внутренние адреса в примерах являются шаблонами. Не публикуйте реальные значения токенов, секретов и внутренних адресов в открытом доступе.

Local Telegram Bot API Server

Local Telegram Bot API Server нужен для работы с крупными файлами. В режиме local сервер возвращает путь к файлу на диске VM Europe, поэтому n8n не скачивает файл из Telegram и не упирается в ограничения cloud Bot API.

sudo nano /opt/telegram-relay/docker-compose.yml
services:
  telegram-bot-api:
    image: aiogram/telegram-bot-api:latest
    container_name: telegram-bot-api
    restart: unless-stopped
    env_file:
      - .env
    environment:
      TELEGRAM_API_ID: ${TELEGRAM_API_ID}
      TELEGRAM_API_HASH: ${TELEGRAM_API_HASH}
      TELEGRAM_LOCAL: "1"
      TELEGRAM_HTTP_IP_ADDRESS: "0.0.0.0"
      TELEGRAM_HTTP_PORT: "8081"
      TELEGRAM_VERBOSITY: "2"
    volumes:
      - ./botapi-data:/var/lib/telegram-bot-api
    ports:
      - "127.0.0.1:8081:8081"
cd /opt/telegram-relay
docker compose config >/tmp/telegram-compose-check.yml && echo COMPOSE_OK
docker compose pull
docker compose up -d
docker logs --tail=100 telegram-bot-api

Проверяем, что бот отвечает через локальный Bot API:

cd /opt/telegram-relay
source .env
curl -sS "http://127.0.0.1:8081/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/getMe" | jq

Перевод бота на Local Bot API

Перед работой через Local Bot API удаляем старый webhook и выполняем logOut из cloud Bot API. После этого updates должны идти через локальный сервер.

cd /opt/telegram-relay
source .env

curl -sS -X POST "https://api.telegram.org/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/deleteWebhook" \
  -d "drop_pending_updates=false" | jq

curl -sS -X POST "https://api.telegram.org/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/logOut" | jq

Проверяем получение сообщений:

curl -sS "http://127.0.0.1:8081/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/getUpdates?timeout=1&limit=10" | jq

Безопасный буфер файлов

Local Bot API может хранить файлы в каталогах, где в пути встречается токен бота. Такие пути нельзя передавать в n8n и нельзя публиковать в логах. Поэтому relay перекладывает файл в отдельный буфер.

/opt/telegram-relay/buffer/Logparser/files/<update_id>_<safe_file_name>

Перед отправкой задачи в n8n relay проверяет размер файла: размер на диске должен совпадать с file_size из Telegram. Если размер не совпадает, задача не отправляется.

Очистка временных файлов

Чтобы диск VM Europe не переполнился, включаем регулярную очистку. Раз в 6 часов удаляем файлы старше 12 часов из рабочего буфера и старые media-файлы из botapi-data. Служебные state/db-файлы Bot API не удаляем.

sudo nano /opt/telegram-relay/cleanup_relay_buffers.sh
#!/usr/bin/env bash
set -euo pipefail

BUFFER_ROOT="/opt/telegram-relay/buffer"
BOTAPI_ROOT="/opt/telegram-relay/botapi-data"

find "$BUFFER_ROOT" -type f -name '*.part.*' -mmin +60 -delete || true
find "$BUFFER_ROOT" -type f -mmin +720 -delete || true

for kind in documents photos videos voice audio animations thumbnails; do
  find "$BOTAPI_ROOT" -type f -path "*/${kind}/*" -mmin +720 -delete 2>/dev/null || true
done
chmod +x /opt/telegram-relay/cleanup_relay_buffers.sh
sudo nano /etc/systemd/system/telegram-relay-cleanup.timer
[Unit]
Description=Run Telegram relay cleanup every 6 hours

[Timer]
OnBootSec=10min
OnUnitActiveSec=6h
Persistent=true
Unit=telegram-relay-cleanup.service

[Install]
WantedBy=timers.target
sudo nano /etc/systemd/system/telegram-relay-cleanup.service
[Unit]
Description=Telegram relay cleanup

[Service]
Type=oneshot
ExecStart=/opt/telegram-relay/cleanup_relay_buffers.sh
systemctl daemon-reload
systemctl enable --now telegram-relay-cleanup.timer
systemctl list-timers --all | grep telegram-relay-cleanup

Входной relay VM Europe → n8n

Входной relay держит long polling к Local Telegram Bot API. Если сообщений нет, n8n не запускается. Если пришёл текст или файл, relay проверяет userId по allowlist, подготавливает payload и отправляет задачу в n8n webhook.

Неавторизованный пользователь может отправлять только текст. Если такой пользователь отправит файл, relay не вызывает getFile и не скачивает файл на диск. Это защищает VM Europe и n8n от несанкционированного доступа.

Я Logparser, создан для обработки архивов логов.

К сожалению, ты пока не авторизован для использования моих функций. Напиши команде проекта, чтобы тебе открыли доступ.

Контракт входной задачи, которую relay отправляет в n8n:

{
  "source": "telegram_europe_relay",
  "bot": "logparser",
  "updateId": 123456789,
  "messageId": 10,
  "userId": "<telegram_user_id>",
  "chatId": "<telegram_chat_id>",
  "login": "@username",
  "text": "текст сообщения или Empty",
  "hasFile": true,
  "files": [
    {
      "kind": "file",
      "name": "storage_logs.zip",
      "size": 123456789,
      "mimeType": "application/zip"
    }
  ]
}

Если есть файл, relay отправляет в n8n multipart/form-data: поле payload содержит JSON, поле file содержит бинарный файл.

curl -i -sS -X POST "${N8N_LOGPARSER_WEBHOOK_URL}" \
  -H "X-Relay-Secret: ${N8N_RELAY_SHARED_SECRET}" \
  -F 'payload={"source":"telegram_europe_relay","bot":"logparser","chatId":"<chat_id>","hasFile":true};type=application/json' \
  -F 'file=@/opt/telegram-relay/buffer/Logparser/files/123456789_storage_logs.zip'

Output API VM Europe ← n8n

Для ответов n8n не обращается напрямую к api.telegram.org. Он отправляет запрос в Output API на VM Europe. Output API проверяет общий секрет, проверяет bot token и передаёт сообщение или файл в Local Telegram Bot API.

Output API удобно делать очередью: n8n быстро получает ok: true, а фактическая отправка файла в Telegram выполняется worker-ом на VM Europe.

VM_EUROPE_TELEGRAM_API_BASE_URL=https://relay.example.net:444

Output API принимает только методы, которые нужны для ответа бота: sendMessage, sendDocument, sendPhoto и при необходимости sendMediaGroup. Порт 444 закрывается allowlist-ом по IP основного n8n-сервера.

4. Настройка входа и выхода в n8n

В n8n создаём новый workflow для нового Telegram-бота. Этот workflow состоит из трёх частей: входной модуль, внутренняя бизнес-логика и выходной модуль. Внутреннюю бизнес-логику можно заменить на любую задачу; в этой статье настраиваем только транспортный вход и транспортный выход.

Переменные окружения n8n

На n8n-сервере добавляем переменные, которые нужны входному и выходному модулю.

N8N_RELAY_SHARED_SECRET=<same_random_64_hex_secret>
VM_EUROPE_TELEGRAM_API_BASE_URL=https://relay.example.net:444
TELEGRAM_LOGPARSER_BOT_TOKEN=<bot_token_from_botfather>
N8N_DEFAULT_BINARY_DATA_MODE=filesystem
N8N_FORMDATA_FILE_SIZE_MAX=2048
N8N_PAYLOAD_SIZE_MAX=2048

После изменения .env контейнер n8n нужно пересоздать.

cd /path/to/n8n
sudo docker compose up -d --force-recreate n8n

Входной модуль n8n

В n8n создаём production webhook. Это единственная точка входа для VM Europe.

HTTP Method: POST
Path: telegram-relay-logparser
Production URL: https://automation.example.com:443/webhook/telegram-relay-logparser
Response mode: Immediately

Сразу после Webhook ставим Code-ноду проверки секрета и нормализации входа.

const headers = $json.headers || {};
const got = String(headers['x-relay-secret'] || headers['X-Relay-Secret'] || '');
const expected = String($env.N8N_RELAY_SHARED_SECRET || '');

if (!expected || got !== expected) return [];

let body = $json.body || {};
let payload = body.payload;

if (typeof payload === 'string') {
  try {
    payload = JSON.parse(payload);
  } catch {
    payload = {};
  }
}

const data = payload && Object.keys(payload).length ? payload : body;

return [{
  json: { ...data, relaySecretOk: true },
  binary: $binary
}];

После этой ноды workflow получает одинаковую структуру независимо от того, пришёл только текст или текст с файлом.

userId=<telegram_user_id>
chatId=<telegram_chat_id>
text=<message_text>
hasFile=true|false
files=[...]
binary.file=<входной файл, если он был>

Модуль сохранения входного файла

Если VM Europe отправила файл, n8n получает его как binary. Нельзя читать большие файлы целиком через getBinaryDataBuffer. Входная Code-нода должна использовать filesystem binary storage и перекладывать файл в рабочую папку.

/home/node/.n8n/tmp/telegram_relay_inbox/logparser

На выходе входного модуля бизнес-логика получает локальный путь:

files[0].localPath=/home/node/.n8n/tmp/telegram_relay_inbox/logparser/123456789_storage_logs.zip

Дальше любую внутреннюю обработку строим вокруг localPath. Например, Logparser распаковывает архив, анализирует логи и формирует файл отчёта. Этот этап не зависит от Telegram.

Выходной модуль n8n: отправка текста

Чтобы отправить пользователю текст, n8n вызывает Output API на VM Europe.

POST ${VM_EUROPE_TELEGRAM_API_BASE_URL}/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/sendMessage
Header: X-Relay-Secret: <shared_secret>
Body form-data:
  chat_id=<telegram_chat_id>
  text=<answer_text>

Пример проверки с n8n-сервера:

curl -sS -X POST "${VM_EUROPE_TELEGRAM_API_BASE_URL}/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/sendMessage" \
  -H "X-Relay-Secret: ${N8N_RELAY_SHARED_SECRET}" \
  -d "chat_id=<telegram_chat_id>" \
  --data-urlencode "text=Проверка отправки через VM Europe"

Выходной модуль n8n: отправка файла

Чтобы отправить пользователю файл, n8n вызывает sendDocument через Output API. Файл берётся из локального пути, который сформировала бизнес-логика.

POST ${VM_EUROPE_TELEGRAM_API_BASE_URL}/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/sendDocument
Header: X-Relay-Secret: <shared_secret>
Body multipart/form-data:
  chat_id=<telegram_chat_id>
  document=@/path/to/result_file.docx
  caption=<optional_caption>

Если файл большой, лучше чтобы Output API на VM Europe принимал задачу в очередь и сразу возвращал n8n ответ ok: true. Тогда n8n не ждёт фактическую отправку файла в Telegram и не падает по timeout.

Минимальная схема workflow в n8n

Webhook telegram-relay-logparser
  -> Check relay secret and normalize payload
  -> Save incoming binary to localPath
  -> Your business workflow
  -> Prepare answer text or result file
  -> Send via VM Europe Output API

Проверка входа из VM Europe

cd /opt/telegram-relay
source .env

curl -i -sS --connect-timeout 10 --max-time 30 \
  -X POST "${N8N_LOGPARSER_WEBHOOK_URL}" \
  -H "X-Relay-Secret: ${N8N_RELAY_SHARED_SECRET}" \
  -H "Content-Type: application/json" \
  --data '{"source":"test","bot":"logparser","userId":"<telegram_user_id>","chatId":"<telegram_chat_id>","text":"ping","hasFile":false,"files":[]}'

Ожидаемый ответ: HTTP 200. Если получаем 404, workflow не активирован или path отличается. Если timeout, проблема в доступности n8n по HTTPS.

Проверка вывода через VM Europe

curl -sS -X POST "${VM_EUROPE_TELEGRAM_API_BASE_URL}/bot${TELEGRAM_LOGPARSER_BOT_TOKEN}/sendMessage" \
  -H "X-Relay-Secret: ${N8N_RELAY_SHARED_SECRET}" \
  -d "chat_id=<telegram_chat_id>" \
  --data-urlencode "text=Проверка обратного канала"

Если сообщение пришло в Telegram, значит обратный канал n8n → VM Europe → Telegram работает.

Мониторинг

journalctl -u telegram-relay.service -f
journalctl -u telegram-output-api.service -f
curl -sS https://relay.example.net:444/health

Если n8n execution завершился успешно, но пользователь не получил файл, проверяем очередь Output API и логи VM Europe. В очередной схеме ok: true для n8n означает, что задача принята на отправку, а не что Telegram уже доставил файл пользователю.

Итоговая схема

Пользователь Telegram
  -> VM Europe + Local Telegram Bot API
  -> input relay
  -> n8n webhook на 443
  -> внутренняя логика бота
  -> VM Europe Output API на 444
  -> Local Telegram Bot API
  -> пользователь Telegram

В результате n8n не зависит от VPN-приложений и не обращается напрямую к Telegram. Telegram-токены не попадают в пути файлов, файлы от неавторизованных пользователей не скачиваются, а вход и выход бота оформлены как отдельные транспортные модули.

5. Поздравляю, ваш бот интегрирован с Telegram!

Made on
Tilda