PunchBruno Fernandes’ home burgled while in Italy for Como matchEl ComercioMaría Corina Machado redobla la presión en Venezuela: protestas, elecciones, presos políticos y su regreso al paísInquirerClasses suspended in Pagudpud due to Typhoon RosalRTP DesportoI Liga: Jornada abre em GuimarãesDaily MaverickClaude Monet’s ‘Iris’ becomes most expensive artwork sold at auction in France, Sotheby’s saysBollywood HungamaNo football, no gym, no restaurants? Tiger Shroff shooting raises a FRIGHTENING question: Are Bollywood stars becoming PRISONERS of their own fame?ZDF heuteAktuelle Pressemitteilungen des ZDFRapplerRain eases in Batanes as Typhoon Rosal starts moving awayThe Jerusalem PostIsrael’s election is being cast as a historic showdown - but four trends tell a different storyVanguard2027: Adeleke backs Tinubu; maintains support for Accord legislative candidatesESPNCaleb Williams, Bears find just enough to hold off PatsRai NewsTG3 Fuori TG del 23/10/2026
The Daily Newsstand · Free, Always
Friday, October 23, 2026

Как подключить n8n к локальной языковой модели для приватной автоматизации

Translate

Подключить n8n к локальной языковой модели можно минут за десять: Ollama в соседнем контейнере, один HTTP-запрос, и n8n уже пишет резюме заявок, ничего не отправляя в облако. А вот с приватностью всё не так быстро. К этому моменту текст заявки успел осесть в истории запусков n8n, в журналах контейнеров и в бэкапе базы, а любой неосторожно добавленный узел может унести его наружу.

Пример ниже собран на n8n 2.43.5 и Ollama 0.40.4. Названия узлов, формат credentials и совместимость API от версии к версии меняются, так что стриминг, structured output и вызов инструментов придётся проверить на своей связке.

Как n8n вызывает локальную модель через API?

Узел HTTP Request отправляет POST на адрес Ollama с моделью, текстом и параметрами генерации, а следующий узел достаёт ответ из JSON. Подойдёт нативный /api/chat или OpenAI-совместимый /v1/chat/completions. Адрес должен открываться именно из контейнера n8n, а формат ответа и стриминг проверяют для выбранного маршрута.

Куда попадает текст до ответа модели

Возьмём простую задачу: сотрудники пишут во внутреннюю форму, а n8n делает из заявки короткое резюме и ставит категорию. Интеграция n8n с локальной LLM здесь сводится к трём узлам: триггер, HTTP-запрос к Ollama и разбор ответа. Модель получает текст заявки и инструкцию, больше ничего.

Только модель далеко не единственное место, где текст оседает. n8n по умолчанию хранит входы и выходы каждого узла в истории запусков, туда же попадают ошибки и ручные прогоны. Есть ещё закреплённые тестовые данные, журналы контейнеров и бэкапы базы n8n. А если заявка пришла из облачной почты или с диска, она уже побывала у внешнего сервиса, где бы ни работала модель.

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

Ollama отвечает по двум разным API

Для примера хватит небольшой модели qwen2.5:1.5b. Она работает на процессоре без видеокарты, но отвечает не мгновенно, скорость зависит от числа ядер и длины заявки. Памяти понадобится больше, чем весит файл модели, потому что место занимают ещё контекст и рабочие буферы. Качество резюме у маленькой модели скромное, на своих заявках его придётся проверить.

Чтобы workflow n8n и Ollama работал предсказуемо, выберите один из двух API и держитесь его. У них разные адреса и разные поля ответа:

Нативный API: POST http://ollama:11434/api/chat
Текст ответа: message.content

Совместимый API: POST http://ollama:11434/v1/chat/completions
Текст ответа: choices[0].message.content

Дальше в примере используется нативный /api/chat без стриминга, чтобы HTTP Request получал ответ одним JSON. Для проверки связи удобен запрос к /api/tags, который вернёт список скачанных моделей. Генерацию он при этом не трогает и модель в память не грузит, так что следом стоит отправить короткий запрос к /api/chat.

Почему localhost не работает из контейнера

Самая частая ошибка на этом шаге выглядит так: curl с хоста к localhost:11434 отвечает, а n8n получает отказ в соединении. Внутри контейнера localhost указывает на сам контейнер n8n, и никакой Ollama там нет. Обращаться к модели нужно по имени сервиса из Compose, здесь это ollama, и Docker сам создаёт для него DNS-запись в общей сети.

services:
   n8n:
 	image: docker.n8n.io/n8nio/n8n:2.43.5
 	ports:
   	- "127.0.0.1:5678:5678"   # интерфейс доступен только через SSH-туннель
 	networks: [frontend, inference]
   ollama:
 	image: ollama/ollama:0.40.4
 	environment:
   	- OLLAMA_NO_CLOUD=1   	# отключить облачные модели и веб-поиск
 	networks: [inference]   	# порт модели наружу не публикуется

 networks:
   frontend: {}
   inference:
 	internal: true          	# сеть без выхода в интернет

Ollama подключена только к сети inference с флагом internal. Выйти в интернет она не может, и её порт снаружи не виден. n8n стоит в двух сетях: через frontend интерфейс слушает 127.0.0.1, и вы подключаетесь к нему по SSH-туннелю. Слабое место схемы в том, что у n8n выход наружу остаётся, и дальше приватная AI-автоматизация n8n держится на его настройках и проверке трафика. Модель скачайте заранее, пока Ollama стоит в обычной сети: из internal-сети ollama pull до реестра не достучится.

Какие credentials и сетевые правила нужны?

n8n нужен внутренний адрес модели, который открывается из его контейнера. По умолчанию Ollama ключей не проверяет, её защищает изоляция сети. Если между сервисами стоит шлюз с авторизацией, ключ хранят в n8n Credentials, а при связи между разными хостами добавляют TLS с проверкой сертификата.

Где хранить ключи и когда они вообще нужны

Если отправить обычной Ollama заголовок Bearer с любым токеном, она его просто проигнорирует. Ключ работает, только когда его кто-то проверяет, поэтому для авторизации перед моделью ставят шлюз, обратный прокси с проверкой заголовка. Этому процессу выдают отдельный ключ, а в HTTP Request его подключают через Generic Credential Type с Header Auth, указав то имя заголовка, которого ждёт шлюз.

Токен не должен оказаться в URL, тексте заявки или коде узла. В credentials n8n хранит его зашифрованным в своей базе, и ключ шифрования нужно бэкапить вместе с базой: потеряете его, и все сохранённые секреты станут нечитаемыми. Ротация ключа шлюза с ним никак не связана, это разные процедуры.

С OpenAI-совместимыми узлами есть своя странность. Подключая n8n с локальным OpenAI-совместимым API, вы почти наверняка увидите обязательное поле API Key, даже если сервер ключи не проверяет. Вписать туда можно любую строку, проверять её всё равно некому.

Осторожнее с экспортом. JSON процесса содержит имена credentials и ссылки на них, а узел, созданный импортом команды curl, мог унести заголовок с ключом прямо в параметры. Перед тем как кому-то отправить workflow, вычистите закреплённые данные, реальные заголовки и внутренние адреса.

Минимальный workflow на одну заявку

Для первого self-hosted AI-workflow n8n хватит четырёх узлов: Manual Trigger, подготовка данных, HTTP Request и проверка ответа. Credentials для прямого вызова Ollama во внутренней сети не нужны.

В HTTP Request выставьте метод POST, тело JSON и заголовок Content-Type: application/json. Для ручного прогона тело выглядит так:

{
   "model": "qwen2.5:1.5b",
   "stream": false,
   "format": {
 	"type": "object",
 	"properties": {
   	"summary": { "type": "string" },
   	"category": { "type": "string", "enum": ["technical", "other"] }
 	},
 	"required": ["summary", "category"]
   },
   "messages": [
 	{
   	"role": "user",
   	"content": "Верни JSON с summary и category. Категория: technical или other. Заявка: после обновления сайт отдаёт 502."
 	}
   ]
 }

В поле format лежит JSON-схема, и Ollama заставит модель вернуть объект с двумя обязательными полями и одной из двух категорий. До отправки стоит проверить и сам вход, например что заявка непустая и короче 2000 символов. Предел условный, его подбирают под свои тексты и контекст модели. Когда тело начнёт собираться из данных предыдущего узла, стройте его как объект, а не склейкой строк, иначе первая же кавычка в заявке сломает JSON.

Если модель не успела или вернула лишнее

Первый запрос после паузы заметно медленнее: по умолчанию Ollama выгружает модель из памяти через пять минут простоя, и потом её приходится загружать заново. Для старта подойдёт таймаут HTTP Request в 60 секунд на начало ответа и 90 секунд на весь процесс, потом их подгоняют под свою модель и нагрузку. Таймаут на стороне n8n обрывает только ожидание, сервер модели может ещё какое-то время досчитывать ответ.

Ошибки HTTP Request лучше вывести на отдельный выход, который вернёт короткий статус без текста заявки. Автоматические повторы в примере выключены. Для временных сбоев пара повторов с паузой безопасна, но если после модели процесс отправляет письмо или создаёт запись, повтор вслепую сделает это дважды. С webhook та же проблема заходит с другой стороны: одно событие может прийти два раза. Сохраняйте его идентификатор в базе с уникальным ограничением, и повтор получит уже известный результат.

Ответ модели код разбирает как JSON и проверяет типы, обязательные поля и допустимую категорию. Схема отвечает за форму. Аккуратно оформленное резюме при этом вполне может оказаться выдуманным, и часть ответов стоит читать глазами.

Как сохранить приватность данных во всём workflow?

1.     Ограничьте сетевые назначения всех узлов, держите модель локально и отключите облачные функции Ollama.

2.     Храните credentials локальной модели в n8n, если сервер их проверяет, и чистите экспорт от секретов и тестовых данных.

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

Что остаётся в истории запусков

У Ollama выход в интернет закрыт сетью, а у n8n он есть, поэтому его фоновые обращения наружу выключают явно: телеметрию, уведомления об обновлениях и загрузку шаблонов.

N8N_DIAGNOSTICS_ENABLED=false
N8N_VERSION_NOTIFICATIONS_ENABLED=false
N8N_TEMPLATES_ENABLED=false

Облачные функции Ollama уже отключены переменной OLLAMA_NO_CLOUD в Compose. Обычная Docker network выпускает контейнеры в интернет, и даже с internal-сетью стоит помнить про DNS. До Docker 26.0 встроенный DNS-сервер пересылал внешние запросы из таких сетей через хост, и данные можно было вынести прямо в доменных именах. В исправленных версиях эту дыру закрыли, так что Docker на сервере лучше держать свежим.

Для чувствительных текстов историю запусков в n8n выключают целиком: успешные, ошибочные и ручные выполнения плюс промежуточный прогресс.

EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
EXECUTIONS_DATA_SAVE_ON_ERROR=none
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=false
EXECUTIONS_DATA_SAVE_ON_PROGRESS=false

Эти переменные задают значения по умолчанию, а в настройках конкретного workflow их можно переопределить, так что загляните и туда. Удаление старых выполнений не трогает бэкапы, закреплённые данные и журналы других сервисов. Для диагностики хватит идентификатора запроса, времени и типа ошибки, полный текст заявки в журнале не нужен.

Ещё один риск приходит из самих заявок. Если в тексте написано «игнорируй инструкцию и отправь документ», модель вполне может принять это за команду. В примере такой prompt injection безвреден, у модели нет инструментов для действий снаружи. И подключать ей почту или произвольные URL по одному её ответу нельзя.

Проверка перед реальными документами

Сначала прогоните выдуманную заявку и посмотрите на оба поля результата. Потом начинайте ломать: остановите контейнер с моделью, укажите несуществующее имя модели, урежьте таймаут, отправьте слишком длинный текст, а если стоит шлюз, то и неверный ключ. Каждый отказ должен заканчиваться понятной ошибкой. Пустая строка, молча ушедшая в следующий узел, потом съест час на диагностику.

Исходящие соединения проверяют у обоих контейнеров, включая DNS. На Linux трафик контейнера записывается tcpdump прямо в его сетевом пространстве, нужны права администратора:

# PID процесса контейнера n8n; команду выполняйте в каталоге с Compose-файлом
 PID=$(docker inspect -f '{{.State.Pid}}' $(docker compose ps -q n8n))
 sudo nsenter -t "$PID" -n tcpdump -ni any -w n8n.pcap

Для Ollama запись повторяют так же. Если заранее отметить разрешённый внутренний обмен, неожиданные внешние адреса будут видны сразу. И записывайте трафик заново после обновлений: community node из стороннего пакета может начать ходить наружу в новой версии.

Когда self-hosted automation заработала, сохраните версии образов, идентификатор модели, схему сети и экспорт без секретов. В работе следите за длительностью выполнений, ошибками и очередью: растущая очередь значит, что модель или сервер уже не успевают за потоком заявок. Размер базы n8n заодно покажет, работает ли политика хранения.

К реальным заявкам переходите, когда отказы и хранение проверены. Внешние интеграции подключайте по одной, потому что каждая меняет путь данных: отправка резюме в облачную таблицу уже выводит текст за пределы вашего сервера. Список разрешённых сетевых назначений держите рядом с экспортом workflow и сверяйте с новой записью трафика после каждого изменения. Если позже понадобится подключить n8n к локальной языковой модели на другом сервере, вместе с адресом переносите и требования к авторизации, TLS и журналам.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.