В чем основная проблема: если вы деплоите self‑hosted n8n (или любое Node.js‑приложение) в Docker и пытаетесь подключить GigaChat API то, скорее всего, натнетесь на ошибку SSL‑верификации. Статья о том, как это починить правильно, а не костылём с отключением всех сертификатов безопасности NODE_TLS_REJECT_UNAUTHORIZED=0, который советуют на каждом втором форуме.
Бонусом будет история про галлюцинацию, из‑за которой GigaChat начал называть всех клиентов «Иваном».
Контекст: что мы строили
Self‑hosted стек на VPS:
• n8n в Docker — оркестратор воркфлоу
• PostgreSQL в Docker — база данных (сессии, лиды, кэш)
• GigaChat API (Сбер) — LLM для чат‑виджета на сайте
• Gemini Flash (Google) — вторая модель для задач скоринга
GigaChat нужен для обработки входящих сообщений на русском языке с привязкой к 152-ФЗ: если пользователь отправляет персональные данные (телефон, email), система должна обнаружить PII и обработать их отдельным контуром. GigaChat выбрали потому что данные не уходят за рубеж — серверы Сбера находятся в РФ.
Симптом: UNABLE_TO_VERIFY_LEAF_SIGNATURE
Стек подняли, завели в n8n узел HTTP Request, указали эндпоинт https://gigachat.devices.sberbank.ru/api/v1/chat/completions, передали авторизационный заголовок и тестовый JSON. Жмем кнопку запускаи нода сразу валится в красную ошибку:
Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
Суть проблемы упирается в устройство цепочки доверия. Сертификаты для доменов Сбера подписывает Головной удостоверяющий центр Минцифры России. При этом рантайм Node.js при сборке зашивает в себя эталонный список корневых сертификатов NSS от Mozilla Foundation. Поскольку российский удостоверяющий центр туда не включен, при валидации цепочки TLS‑хендшейка клиент Node.js просто берет и завершает соединение.
Вредный совет из интернета: почему нельзя отключать TLS
Первый порыв при виде красной ошибки сертификата, просто взять и выключить проверку сертификатов, и выставить NODE_TLS_REJECT_UNAUTHORIZED=0 в секции environment docker‑compose.
#docker-compose.yml — НЕ ДЕЛАЙТЕ ТАК
environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0
На раннем этапе тестирования, отложив правильную настройку сертификатов на потом, я сделал так же. Спустя пару месяцев выяснилось, что временная директива тихо прижилась на боевом сервере.
Опасность такого подхода заключается в том, что флаг действует глобально на уровне всего процесса Node.js. Контейнер n8n прекращает валидацию цепочек сертификатов не только для эндпоинтов GigaChat, но и для обращений к базам данных, внешним вебхукам и Telegram Bot API. При компрометации маршрутизации трафика злоумышленник сможет осуществить атаку Man‑in‑the‑Middle и перехватить рабочие Bearer‑токены.
Настройка сертификатов Минцифры в Docker
Чтобы вернуть серверу безопасность, нам нужно было научить рантайм Node.js распознавать подпись Минцифры на общих основаниях.
Сборка бандла на сервере занимает четыре строчки в терминале:
mkdir -p /opt/certs
curl -k -s https://gu-st.ru/content/Other/doc/russian\_trusted\_root\_ca.cer > /opt/certs/russian_trusted_root_ca.crt
echo "" >> /opt/certs/russian_trusted_root_ca.crt
curl -k -s https://gu-st.ru/content/Other/doc/russian\_trusted\_sub\_ca.cer >> /opt/certs/russian_trusted_sub_ca.crt
chmod 644 /opt/certs/russian_trusted_root_ca.crt
В docker‑compose.yml прокидываем файл через volume и объявляем переменную окружения:
services:
n8n:
image: n8nio/n8n:latest
volumes:
- /opt/certs/russian_trusted_root_ca.crt:/home/node/certs/russian_trusted_root_ca.crt:ro
environment:
- NODE_EXTRA_CA_CERTS=/home/node/certs/russian_trusted_root_ca.crt
После рестарта (docker compose up -d) не стоит проверять статус через консольный openssl s_client — утилита берет сертификаты из системного каталога ОС и переменную Node.js просто не увидит.
Проверяем прямо внутри контейнера:
docker exec -it n8n node -e "require('https').get('https://gigachat.devices.sberbank.ru', (res) => console.log('TLS code:', res.statusCode)).on('error', console.error)"
Пришел ответ 200 или 403? Отлично, значит TLS завелся, сертификаты подцепились нормально.
Особенность с переменными $env в n8n 1.x
С токенами в n8n 1.x есть отдельная засада. Если дернуть $env.GIGACHAT_TOKEN прямо в выражении ноды, n8n выдаст ошибку: ExpressionError: access to env vars denied. В первой ветке прямой доступ к переменным окружения из нод просто заблокировали по умолчанию.
Конечно, можно открыть доступ переменной N8N_BLOCK_ENV_ACCESS_IN_NODE=false, но лучше не костылить и нормально завести ключ через Header Auth в меню Credentials.
Бонус — Синдром Ивана

И напоследок — смешной баг, на котором мы знатно споткнулись («синдром Ивана»). Мы поставили GigaChat чистить текст от персональных данных‑ убрать телефоны и почту перед тем, как отправлять сообщения дальше...
В системном промпте стояла задача: если клиент оставил контакты, достать его имя в поле first_name.
Прикол вскрылся на безымянных лидах. Пишет человек: «Добрый вечер, сколько стоит создание агента для атосервиса?». Имени в сообщении нет. Но модель обязана отдать валидный JSON, строковое поле пустоту не терпит, а null она возвращать не умеет. В итоге GigaChat не нашел ничего лучше, как вписать самое частое русское имя из своего датасета — Иван.
Наш тестовый бот начал приветствовать абсолютно всех пользователей фразой «Здравствуйте, Иван!», включая женщин и юрлиц. Пришлось переписать промпт с жестким запретом на домысливание и добавить на выходе ноду Code с проверкой имени.
Итог
Если хотитие добавить в n8n российские сервисы — не отключайте проверку сертификатов костылями. Добавить сертификаты Минцифры занимает три минуты, зато криптографический контур остается целым.
Исходники docker‑compose и готовый воркфлоу для n8n выложены в открытом репозитории: n8n‑gigachat‑starter‑kit.