В этой статье разберём, как связать n8n с Telegram: создать бота, принять запрос через Webhook и отправить пользователю ответ — текстом или файлом.
Данная схема удобна, если вы уже давно пользуетесь Telegram и у вас там построена коммуникация с вашими клиентами. Также Telegram можно использовать как demo-доступ для новых клиентов, чтобы с минимальными усилиями продемонстрировать работу ваших ботов.
Войдите в личный кабинет 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 В Telegram найдите @BotFather, должно быть не менее 8 млн подписчиков и синяя галочка. Отправьте ему следующие команды:
/start
/newbot
Namebot
Usernamebot В ответ получите сообщение, что бот создан, и получите его API-ключ.
Создаём промежуточный сервер для приёма сообщений в любой стране Европы. Провайдера выбирайте сами. Виртуальная машина нужна, чтобы вынести транспортный слой в отдельный внешний контур, не зависящий от пользовательских 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 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 сервер возвращает путь к файлу на диске 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 удаляем старый 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 держит 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' Для ответов 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-сервера.
В n8n создаём новый workflow для нового Telegram-бота. Этот workflow состоит из трёх частей: входной модуль, внутренняя бизнес-логика и выходной модуль. Внутреннюю бизнес-логику можно заменить на любую задачу; в этой статье настраиваем только транспортный вход и транспортный выход.
На 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 создаём 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 вызывает 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 вызывает 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.
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 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.
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-токены не попадают в пути файлов, файлы от неавторизованных пользователей не скачиваются, а вход и выход бота оформлены как отдельные транспортные модули.