<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Вячеслав Старцев</title><subtitle>AI-агенты, автоматизация бизнес-процессов</subtitle><author><name>Вячеслав Старцев</name></author><id>https://teletype.in/atom/promptica</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/promptica?offset=0"></link><link rel="alternate" type="text/html" href="https://blog.promptica.ru/?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/promptica?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-19T03:03:45.491Z</updated><entry><id>promptica:rag-metrics</id><link rel="alternate" type="text/html" href="https://blog.promptica.ru/rag-metrics?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><title>Метрики качества RAG (шпаргалка)</title><published>2026-02-07T06:30:10.794Z</published><updated>2026-02-07T06:30:10.794Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/35/dc/35dcb88c-696b-4589-820e-f988a968ff91.png"></media:thumbnail><category term="rag" label="RAG"></category><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/1c/bd/1cbdb18a-cccf-4453-b911-00bd96460887.jpeg&quot;&gt;RAG (Retrieval-Augmented Generation) оценивают на двух уровнях: насколько хорошо нашли нужные документы и насколько хорошо сгенерировали ответ.</summary><content type="html">
  &lt;p id=&quot;kN1k&quot;&gt;RAG (Retrieval-Augmented Generation) оценивают на двух уровнях: насколько хорошо нашли нужные документы и насколько хорошо сгенерировали ответ.&lt;/p&gt;
  &lt;h2 id=&quot;1t9B&quot;&gt;Метрики поиска (Retrieval)&lt;/h2&gt;
  &lt;p id=&quot;E3FY&quot;&gt;&lt;strong&gt;Precision@K (точность)&lt;/strong&gt; - какая доля из K найденных документов реально полезна.&lt;/p&gt;
  &lt;p id=&quot;P792&quot;&gt;Пример: &lt;em&gt;система нашла 5 документов, из них 3 релевантны. Precision@5 = 3/5 = 0.6. То есть 40% мусора.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;7spV&quot;&gt;&lt;strong&gt;Recall@K (полнота)&lt;/strong&gt; - какую долю всех нужных документов мы нашли.&lt;/p&gt;
  &lt;p id=&quot;ezKU&quot;&gt;Пример: &lt;em&gt;в базе 10 релевантных документов, система нашла 3 из них. Recall = 3/10 = 0.3. Мы упустили 70% полезной информации.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;SIcW&quot;&gt;&lt;strong&gt;MRR (Mean Reciprocal Rank)&lt;/strong&gt; - насколько высоко в выдаче оказался первый правильный документ.&lt;/p&gt;
  &lt;p id=&quot;Aepx&quot;&gt;Пример: &lt;em&gt;первый релевантный документ на 3-й позиции - 1/3 = 0.33. Если бы на 1-й - 1/1 = 1.0. Чем выше, тем лучше.&lt;/em&gt;&lt;/p&gt;
  &lt;h2 id=&quot;VpUE&quot;&gt;Метрики генерации (Generation)&lt;/h2&gt;
  &lt;p id=&quot;Tp8l&quot;&gt;&lt;strong&gt;Faithfulness (верность контексту)&lt;/strong&gt; - не выдумывает ли модель то, чего нет в найденных документах.&lt;/p&gt;
  &lt;p id=&quot;jzFp&quot;&gt;Пример: &lt;em&gt;в документе написано &amp;quot;выручка выросла на 15%&amp;quot;, а модель отвечает &amp;quot;выручка выросла на 25%&amp;quot;. Faithfulness низкий, модель &amp;quot;галлюцинирует&amp;quot;.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;E09I&quot;&gt;&lt;strong&gt;Answer Relevancy (релевантность ответа)&lt;/strong&gt; - отвечает ли модель на заданный вопрос.&lt;/p&gt;
  &lt;p id=&quot;UgdQ&quot;&gt;Пример: &lt;em&gt;вопрос &amp;quot;Какая цена подписки?&amp;quot;, а модель рассказывает про историю компании. Ответ не релевантен.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;4Sfc&quot;&gt;&lt;strong&gt;Context Relevancy (релевантность контекста)&lt;/strong&gt; - насколько найденные куски текста вообще относятся к вопросу. Если в контекст попал мусор, модели сложнее дать хороший ответ.&lt;/p&gt;
  &lt;h2 id=&quot;AzPA&quot;&gt;Сквозные (end-to-end) метрики&lt;/h2&gt;
  &lt;p id=&quot;cTf9&quot;&gt;&lt;strong&gt;Answer Correctness&lt;/strong&gt; - просто правильный ли ответ, сравнивают с эталоном. Это итоговая оценка всей системы.&lt;/p&gt;
  &lt;p id=&quot;zFlW&quot;&gt;&lt;strong&gt;RAGAS&lt;/strong&gt; - популярный фреймворк, который объединяет Faithfulness, Answer Relevancy и Context Relevancy в единый скор.&lt;/p&gt;
  &lt;h2 id=&quot;vKvs&quot;&gt;Как это работает на практике&lt;/h2&gt;
  &lt;p id=&quot;Cmh9&quot;&gt;Представьте чат-бот по документации банка:&lt;/p&gt;
  &lt;ul id=&quot;0FqI&quot;&gt;
    &lt;li id=&quot;1wRi&quot;&gt;Бот не находит нужный регламент - Recall низкий.&lt;/li&gt;
    &lt;li id=&quot;LRW3&quot;&gt;Бот находит 10 документов, но 8 не по теме - Precision низкий.&lt;/li&gt;
    &lt;li id=&quot;BpYZ&quot;&gt;Бот нашел правильный документ, но выдумал цифры - Faithfulness низкий.&lt;/li&gt;
    &lt;li id=&quot;9LTy&quot;&gt;Бот отвечает правильно, но не на тот вопрос - Answer Relevancy низкий.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Cm4v&quot;&gt;&lt;strong&gt;Главное&lt;/strong&gt;: метрики помогают понять, где именно ломается система - на этапе поиска или на этапе генерации, и что нужно чинить.&lt;/p&gt;

</content></entry><entry><id>promptica:message-buffer</id><link rel="alternate" type="text/html" href="https://blog.promptica.ru/message-buffer?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><title>Буфер сообщений в n8n: снижаем нагрузку на AI и улучшаем качество ответов</title><published>2025-11-04T07:55:23.086Z</published><updated>2025-11-04T10:03:51.285Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/33/9b/339b281f-831b-4a19-b792-b68936eea783.png"></media:thumbnail><category term="n-8-n" label="n8n"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/69/0e/690e90ef-a1b5-4d00-a009-888ad0e035f5.png&quot;&gt;Представьте ситуацию: пользователь общается с вашим AI-ботом и в порыве эмоций отправляет 10 коротких сообщений подряд. Каждое сообщение моментально уходит на обработку в языковую модель, создавая лишнюю нагрузку и увеличивая расходы на API. При этом контекст разрывается на мелкие фрагменты и качество ответов страдает.</summary><content type="html">
  &lt;h2 id=&quot;65un&quot;&gt;Проблема, которую мы решаем&lt;/h2&gt;
  &lt;p id=&quot;6r3u&quot;&gt;Представьте ситуацию: пользователь общается с вашим AI-ботом и в порыве эмоций отправляет 10 коротких сообщений подряд. Каждое сообщение моментально уходит на обработку в языковую модель, создавая лишнюю нагрузку и увеличивая расходы на API. При этом контекст разрывается на мелкие фрагменты и качество ответов страдает.&lt;/p&gt;
  &lt;p id=&quot;3rTv&quot;&gt;Знакомо? Эта проблема типична для чат-ботов и виртуальных ассистентов. Решение простое и элегантное - &lt;strong&gt;буфер сообщений&lt;/strong&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;1WMC&quot;&gt;Что такое буфер сообщений?&lt;/h2&gt;
  &lt;p id=&quot;IS2G&quot;&gt;Буфер сообщений - это механизм накопления входящих сообщений от пользователя перед отправкой их на обработку AI. Вместо того чтобы обрабатывать каждое сообщение отдельно, мы собираем их в группу и отправляем единым пакетом.&lt;/p&gt;
  &lt;p id=&quot;oFAn&quot;&gt;&lt;strong&gt;Когда буфер отправляет накопленные сообщения:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;hp5L&quot;&gt;
    &lt;li id=&quot;2guB&quot;&gt;&lt;strong&gt;По таймеру&lt;/strong&gt;: Прошло 15 секунд с последнего сообщения - пользователь закончил мысль&lt;/li&gt;
    &lt;li id=&quot;BOCx&quot;&gt;&lt;strong&gt;По лимиту слов&lt;/strong&gt;: Накопилось 20+ слов - достаточно контекста для качественного ответа&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;FjD1&quot;&gt;Лимиты слов и таймер можно настраивать под себя.&lt;/p&gt;
  &lt;h2 id=&quot;D0BV&quot;&gt;Архитектура решения в n8n&lt;/h2&gt;
  &lt;p id=&quot;X9wI&quot;&gt;Мы используем &lt;a href=&quot;https://docs.n8n.io/code/cookbook/builtin/get-workflow-static-data/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Workflow&lt;/strong&gt; &lt;strong&gt;Static Data&lt;/strong&gt;&lt;/a&gt;- встроенное хранилище n8n, которое позволяет сохранять небольшие наборы данных между выполнениями workflow без внешних зависимостей вроде Redis, внешних баз данных, Airtable, Supabase, Google Sheets и т.п.&lt;/p&gt;
  &lt;p id=&quot;BTHF&quot;&gt;&lt;strong&gt;Структура данных для каждого пользователя:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;Tv2k&quot; data-lang=&quot;javascript&quot;&gt;{
  messages: [],           // Массив сообщений
  lastMessageTime: 0,     // Время последнего сообщения
  totalWords: 0           // Счетчик слов
}&lt;/pre&gt;
  &lt;p id=&quot;XGmn&quot;&gt;&lt;strong&gt;Для организации буфера сообщений надо добавить только 4 обязательных ноды:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;IFS4&quot;&gt;
    &lt;li id=&quot;CxaR&quot;&gt;&lt;strong&gt;Code Node&lt;/strong&gt; (Message Buffer) - накапливает сообщения в буфере&lt;/li&gt;
    &lt;li id=&quot;k85P&quot;&gt;&lt;strong&gt;IF Node&lt;/strong&gt; - проверяет готовность к отправке в AI&lt;/li&gt;
    &lt;li id=&quot;BLEB&quot;&gt;&lt;strong&gt;Schedule Trigger Node &lt;/strong&gt;(Flush Trigger) - триггер для проверки таймаута сброса буфера&lt;/li&gt;
    &lt;li id=&quot;4uMG&quot;&gt;&lt;strong&gt;Code Node&lt;/strong&gt; (Flush by timeout) - сбрасывает буферы всех пользователей, если достигнут таймаут ожидания&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;43AR&quot;&gt;Подробнее о работе буфера сообщений в n8n смотрите в видео:&lt;/p&gt;
  &lt;figure id=&quot;xtCx&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://vk.com/video_ext.php?oid=-231789689&amp;id=456239017&amp;autoplay=0&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;Буфер сообщений в n8n на базе Static Data&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Jc0B&quot;&gt;&lt;a href=&quot;https://vkvideo.ru/video-231789689_456239017&quot; target=&quot;_blank&quot;&gt;VK Видео&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;LsFZ&quot;&gt;&lt;a href=&quot;https://youtu.be/TeLwp_R9Mdo&quot; target=&quot;_blank&quot;&gt;YouTube&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;T2Sk&quot;&gt;&lt;a href=&quot;https://rutube.ru/video/d87621ea6f93b10ee3dc23e6edd4849a/&quot; target=&quot;_blank&quot;&gt;RuTube&lt;/a&gt;&lt;/p&gt;
  &lt;h2 id=&quot;W5j5&quot;&gt;Ключевые преимущества&lt;/h2&gt;
  &lt;h3 id=&quot;hQHP&quot;&gt;Многопользовательская изоляция&lt;/h3&gt;
  &lt;p id=&quot;cvXg&quot;&gt;Каждый &lt;code&gt;user_id&lt;/code&gt; имеет свой независимый буфер. Сообщения от разных пользователей никогда не смешиваются.&lt;/p&gt;
  &lt;h3 id=&quot;bR0q&quot;&gt;Умная обработка edge cases&lt;/h3&gt;
  &lt;p id=&quot;CexA&quot;&gt;Первое сообщение создает буфер автоматически. Превышение лимита слов вызывает немедленный сброс. Длинные паузы не ломают логику - буфер терпеливо ждет продолжения.&lt;/p&gt;
  &lt;h3 id=&quot;gPUX&quot;&gt;Экономия ресурсов&lt;/h3&gt;
  &lt;p id=&quot;abC5&quot;&gt;Вместо 10 API-запросов к языковой модели - один запрос с полным контекстом. Снижение затрат в 5-10 раз для активных пользователей.&lt;/p&gt;
  &lt;h3 id=&quot;Gu9F&quot;&gt;Лучшее качество ответов&lt;/h3&gt;
  &lt;p id=&quot;rWKM&quot;&gt;AI получает целостный контекст вместо разрозненных фрагментов. Это особенно важно для сложных запросов, которые пользователи формулируют несколькими сообщениями.&lt;/p&gt;
  &lt;h2 id=&quot;w7R7&quot;&gt;Практический пример&lt;/h2&gt;
  &lt;pre id=&quot;i6G9&quot;&gt;Пользователь отправляет:
0 сек  → &amp;quot;Привет&amp;quot;
3 сек  → &amp;quot;Мне нужна помощь&amp;quot;  
7 сек  → &amp;quot;с настройкой webhook&amp;quot;
15+ сек → [СБРОС]

AI получает: &amp;quot;Привет Мне нужна помощь с настройкой webhook&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;D6sI&quot;&gt;Альтернативный сценарий - длинное сообщение на 25 слов сбрасывается немедленно, не дожидаясь таймера.&lt;/p&gt;
  &lt;h2 id=&quot;BRc6&quot;&gt;Когда использовать?&lt;/h2&gt;
  &lt;p id=&quot;iBr3&quot;&gt;Буфер сообщений критически важен для:&lt;/p&gt;
  &lt;ul id=&quot;JPQt&quot;&gt;
    &lt;li id=&quot;AU1W&quot;&gt;&lt;strong&gt;Мессенджер-ботов&lt;/strong&gt; (Telegram, WhatsApp, Slack)&lt;/li&gt;
    &lt;li id=&quot;6Hdn&quot;&gt;&lt;strong&gt;Чат-поддержки&lt;/strong&gt; с высокой нагрузкой&lt;/li&gt;
    &lt;li id=&quot;4dsC&quot;&gt;&lt;strong&gt;AI-ассистентов&lt;/strong&gt; для бизнес-процессов&lt;/li&gt;
    &lt;li id=&quot;n9Jn&quot;&gt;&lt;strong&gt;Образовательных платформ&lt;/strong&gt; с интерактивными уроками&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;u3Gm&quot;&gt;Код решения&lt;/h2&gt;
  &lt;h3 id=&quot;MB1Z&quot;&gt;Нода Message Buffer&lt;/h3&gt;
  &lt;pre id=&quot;N94Q&quot; data-lang=&quot;javascript&quot;&gt;// ============================================================================
// БУФЕР СООБЩЕНИЙ
// Использует Static Data Workflow для хранения буферов сообщений
// ============================================================================

// ПОЛУЧЕНИЕ ВХОДНЫХ ДАННЫХ
const userId = $input.first().json.message.chat.id;
const userMessage = $input.first().json.message.text;

const WORD_LIMIT = 20;  // Лимит слов для принудительного сброса

// ============================================================================
// ИНИЦИАЛИЗАЦИЯ ХРАНИЛИЩА
// ============================================================================

// Получение глобального static data для хранения буферов всех пользователей
const staticData = $getWorkflowStaticData(&amp;#x27;global&amp;#x27;);

// Инициализация структуры данных, если она еще не существует
if (!staticData.userBuffers) {
  staticData.userBuffers = {};
}

// Текущее время в секундах (Unix timestamp)
const currentTime = Math.floor(Date.now() / 1000);

// ============================================================================
// ПОЛУЧЕНИЕ ИЛИ СОЗДАНИЕ БУФЕРА ПОЛЬЗОВАТЕЛЯ
// ============================================================================

// Если буфер пользователя не существует, создаем новый
if (!staticData.userBuffers[userId]) {
  staticData.userBuffers[userId] = {
    messages: [],           // Массив накопленных сообщений
    lastMessageTime: 0,     // Timestamp последнего сообщения
    totalWords: 0           // Общее количество слов в буфере
  };
}

// Получение буфера текущего пользователя
const userBuffer = staticData.userBuffers[userId];

// ============================================================================
// ПОДСЧЕТ СЛОВ В НОВОМ СООБЩЕНИИ
// ============================================================================

/**
 * Функция для подсчета слов в тексте
 * Учитывает пробелы, переносы строк и множественные пробелы
 */
function countWords(text) {
  // Убираем лишние пробелы и разбиваем на слова
  const words = text.trim().split(/\s+/).filter(word =&amp;gt; word.length &amp;gt; 0);
  return words.length;
}

const newMessageWords = countWords(userMessage);

// ============================================================================
// ДОБАВЛЕНИЕ НОВОГО СООБЩЕНИЯ В БУФЕР
// ============================================================================

// Добавляем новое сообщение в массив
userBuffer.messages.push({
  text: userMessage,
  timestamp: currentTime,
  wordCount: newMessageWords
});

// Обновляем общий счетчик слов
userBuffer.totalWords += newMessageWords;

// Обновляем время последнего сообщения
userBuffer.lastMessageTime = currentTime;

// Сохраняем обновленный буфер обратно в static data
staticData.userBuffers[userId] = userBuffer;

// Формируем выходные данные
let output = {shouldProcess: false};

// ============================================================================
// ПРОВЕРКА УСЛОВИЙ СБРОСА БУФЕРА
// ============================================================================

if (userBuffer.totalWords &amp;gt;= WORD_LIMIT) {
  // БУФЕР ГОТОВ К СБРОСУ - возвращаем данные для обработки
  
  // Переопределяем выходные данные
  output = {
    userId: userId,
    message: userBuffer.messages.map(msg =&amp;gt; msg.text).join(&amp;#x27; &amp;#x27;), // склеим все сообщения в одну строку, разделив пробелом 
    shouldProcess: true
  };
  
  // ОЧИЩАЕМ БУФЕР ПОЛЬЗОВАТЕЛЯ
  staticData.userBuffers[userId] = {
    messages: [],
    lastMessageTime: 0,
    totalWords: 0
  };  
}
  
// Возвращаем данные
return [{ json: output }];
&lt;/pre&gt;
  &lt;h3 id=&quot;ZzYp&quot;&gt;Нода Flush by timeout&lt;/h3&gt;
  &lt;pre id=&quot;AI1A&quot; data-lang=&quot;javascript&quot;&gt;// ПРОВЕРКА ТАЙМАУТОВ ДЛЯ ВСЕХ БУФЕРОВ
// Вызывается по расписанию (каждые 5 секунд)

const staticData = $getWorkflowStaticData(&amp;#x27;global&amp;#x27;);
// Текущее время в секундах (Unix timestamp)
const currentTime = Math.floor(Date.now() / 1000);
const TIMEOUT_SECONDS = 15;
const results = [];

if (staticData.userBuffers) {
  for (const userId in staticData.userBuffers) {
    const buffer = staticData.userBuffers[userId];

    // Пропускаем пустые буферы
    if (buffer.messages.length === 0) continue;
    
    // Проверяем таймаут
    const timeSinceLastMessage = currentTime - buffer.lastMessageTime;
    
    if (timeSinceLastMessage &amp;gt;= TIMEOUT_SECONDS) {
      // Буфер готов к сбросу
      results.push({
        userId: userId,
        message: buffer.messages.map(msg =&amp;gt; msg.text).join(&amp;#x27; &amp;#x27;)
      });
      
      // Очищаем буфер
      staticData.userBuffers[userId] = {
        messages: [],
        lastMessageTime: 0,
        totalWords: 0
      };
    }
  }
}

// Возвращаем все буферы, готовые к обработке
return results.map(r =&amp;gt; ({ json: r }));&lt;/pre&gt;
  &lt;h3 id=&quot;LUzH&quot;&gt;Нода Delete buffers&lt;/h3&gt;
  &lt;pre id=&quot;uQ3Y&quot; data-lang=&quot;javascript&quot;&gt;// УДАЛЕНИЕ НЕ ИСПОЛЬЗУЕМЫХ БУФЕРОВ
// Вызывается по расписанию (каждый час)

const staticData = $getWorkflowStaticData(&amp;#x27;global&amp;#x27;);
// Текущее время в секундах (Unix timestamp)
const currentTime = Math.floor(Date.now() / 1000);
const MAX_AGE_SECONDS = 3600; // 1 час
const buffers = staticData.userBuffers || {};

for (const userId in buffers) {
  const buffer = buffers[userId];
  const age = currentTime - buffer.lastMessageTime;
  
  // Если буфер не обновлялся больше MAX_AGE_SECONDS, удаляем его
  if (age &amp;gt; MAX_AGE_SECONDS &amp;amp;&amp;amp; buffer.messages.length === 0) {
    delete staticData.userBuffers[userId];
  }
}

return [];&lt;/pre&gt;
  &lt;p id=&quot;HjQm&quot;&gt;Также вы можете &lt;a href=&quot;https://github.com/promptica/n8n-workflows/blob/main/message-buffer/message-buffer.json&quot; target=&quot;_blank&quot;&gt;скачать workflow n8n с буфером сообщений&lt;/a&gt;&lt;/p&gt;
  &lt;h2 id=&quot;aFdn&quot;&gt;Заключение&lt;/h2&gt;
  &lt;p id=&quot;PCaf&quot;&gt;Реализация буфера сообщений в n8n без внешних зависимостей - это баланс между простотой и эффективностью. Static Data Workflow предоставляет надежное хранилище, а гибкие условия сброса адаптируются под разные сценарии использования.&lt;/p&gt;
  &lt;p id=&quot;KMho&quot;&gt;Копируйте код, адаптируйте под свои задачи и экономьте ресурсы уже сегодня!&lt;/p&gt;

</content></entry><entry><id>promptica:llm-proxy</id><link rel="alternate" type="text/html" href="https://blog.promptica.ru/llm-proxy?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><title>Доступ к зарубежным LLM с российских IP-адресов</title><published>2025-10-11T08:43:30.844Z</published><updated>2025-10-13T07:08:11.651Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/36/e1/36e13aca-a4e9-42d8-9750-7790e99b7194.png"></media:thumbnail><category term="proxy" label="proxy"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/49/e7/49e77132-4558-4a89-807d-ef0cc3168452.png&quot;&gt;При размещении систем автоматизации, таких как n8n или аналогичные платформы, на российских серверах для соблюдения требований 152-ФЗ о защите персональных данных, возникает техническая сложность с доступом к зарубежным языковым моделям (OpenAI, Anthropic, Google и другим). Эти сервисы в рамках соблюдения санкционного режима ограничивают подключения с российских IP-адресов.</summary><content type="html">
  &lt;p id=&quot;A6oq&quot;&gt;При размещении систем автоматизации, таких как n8n или аналогичные платформы, на российских серверах для соблюдения требований 152-ФЗ о защите персональных данных, возникает техническая сложность с доступом к зарубежным языковым моделям (OpenAI, Anthropic, Google и другим). Эти сервисы в рамках соблюдения санкционного режима ограничивают подключения с российских IP-адресов.&lt;/p&gt;
  &lt;h2 id=&quot;hdOv&quot;&gt;Техническое решение через прокси-сервер&lt;/h2&gt;
  &lt;p id=&quot;ptr3&quot;&gt;Эффективным способом обхода данного ограничения является настройка прокси-сервера в нейтральной юрисдикции. Для этого потребуется арендовать дополнительный VPS с локацией в стране, не участвующей в санкционных ограничениях - например, в Казахстане. Стоимость такого решения относительно невысока: VPS у провайдера &lt;a href=&quot;https://beget.com/p23143033&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt; с казахстанской локацией обойдётся в 22 рубля в сутки (около 660 рублей в месяц).&lt;/p&gt;
  &lt;p id=&quot;UCeC&quot;&gt;В данном руководстве подробно рассматривается процесс развёртывания прокси-сервера и конфигурации клиентской части. Вы научитесь настраивать автоматическое перенаправление всех запросов к зарубежным LLM через промежуточный сервер, что обеспечит стабильный доступ к AI-сервисам при сохранении данных на территории РФ в соответствии с законодательными требованиями.&lt;/p&gt;
  &lt;h2 id=&quot;tolO&quot;&gt;Настройка прокси-сервера&lt;/h2&gt;
  &lt;p id=&quot;K2AA&quot;&gt;Прокси-сервер будем реализовывать на базе &lt;strong&gt;Nginx Stream Module&lt;/strong&gt; с SSL passthrough функциональностью. Это позволяет проксировать SSL/TLS трафик без его терминации, сохраняя end-to-end шифрование между клиентом и целевыми API. Nginx будем устанавливать в докере.&lt;/p&gt;
  &lt;h3 id=&quot;dsuK&quot;&gt;1. Подключаемся к серверу по SSH&lt;/h3&gt;
  &lt;pre id=&quot;wS47&quot;&gt;ssh root@ip_адрес_сервера&lt;/pre&gt;
  &lt;h3 id=&quot;1DQv&quot;&gt;2. Проверяем доступ к LLM&lt;/h3&gt;
  &lt;p id=&quot;RCbn&quot;&gt;Перед дальнейшими действиями нам надо убедиться, что с этого сервера есть доступ к зарубежным LLM. Проверим на примере с OpenAI:&lt;/p&gt;
  &lt;pre id=&quot;dU7F&quot;&gt;curl -i https://api.openai.com/v1/models -H &amp;quot;Authorization: Bearer YOUR_OPENAI_KEY&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;ZsGj&quot;&gt;где YOUR_OPENAI_KEY - это ваш ключ OpenAI, полученный на &lt;a href=&quot;https://platform.openai.com/&quot; target=&quot;_blank&quot;&gt;https://platform.openai.com/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;bzFT&quot;&gt;В результате вы должны получить список моделей OpenAI. Если этого не произошло и вы получили 403 ошибку типа: &lt;code&gt;{&amp;quot;error&amp;quot;:{&amp;quot;code&amp;quot;:&amp;quot;unsupported_country_region_territory&amp;quot;,&amp;quot;message&amp;quot;:&amp;quot;Country, region, or territory not supported&amp;quot;,&amp;quot;param&amp;quot;:null,&amp;quot;type&amp;quot;:&amp;quot;request_forbidden&amp;quot;}}&lt;/code&gt;, то с этого сервера нельзя подключиться к зарубежным LLM и следуют выбрать другой сервер в другой локации.&lt;/p&gt;
  &lt;h3 id=&quot;7Pjs&quot;&gt;3. Устанавливаем docker&lt;/h3&gt;
  &lt;p id=&quot;RdTb&quot;&gt;Установку можно произвести по &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository&quot; target=&quot;_blank&quot;&gt;инструкции на сайте докера&lt;/a&gt; или выполнив действия ниже:&lt;/p&gt;
  &lt;pre id=&quot;CWeU&quot;&gt;# Обновляем систему
apt update &amp;amp;&amp;amp; apt install -y curl ca-certificates

# Добавляем GPG ключ Docker
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

# Добавляем репозиторий Docker
echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release &amp;amp;&amp;amp; echo &amp;quot;${UBUNTU_CODENAME:-$VERSION_CODENAME}&amp;quot;) stable&amp;quot; | tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null

# Устанавливаем Docker
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin&lt;/pre&gt;
  &lt;h3 id=&quot;JFqF&quot;&gt;4. Создаем конфигурацию nginx&lt;/h3&gt;
  &lt;pre id=&quot;LCqo&quot;&gt;# Создаем директорию для конфигурации
mkdir -p /root/llm-proxy &amp;amp;&amp;amp; cd /root/llm-proxy

# Создаем конфигурационный файл
cat &amp;gt; nginx.conf &amp;lt;&amp;lt; &amp;#x27;EOF&amp;#x27;
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
  worker_connections 1024;
}

stream {
  # Определяем upstream серверы
  upstream openai_api {
    server api.openai.com:443;
  }

  upstream anthropic_api {
    server api.anthropic.com:443;
  }

  upstream cohere_api {
    server api.cohere.com:443;
  }

  # Карта для выбора upstream по SNI hostname
  map $ssl_preread_server_name $upstream {
    api.openai.com openai_api;
    api.anthropic.com anthropic_api;
    api.cohere.com cohere_api;
    default openai_api;
  }

  # Прокси сервер
  server {
    listen 443;
    ssl_preread on;
    proxy_pass $upstream;
    proxy_connect_timeout 60s;
    proxy_timeout 600s;
  }
}
EOF&lt;/pre&gt;
  &lt;h3 id=&quot;kUtf&quot;&gt;5. Запускаем docker контейнер с proxy&lt;/h3&gt;
  &lt;pre id=&quot;v9up&quot;&gt;docker run -d \
	--name llm-proxy \
	-p 443:443 \
	-v /root/llm-proxy/nginx.conf:/etc/nginx/nginx.conf:ro \
	--restart always \
	nginx:latest&lt;/pre&gt;
  &lt;h3 id=&quot;D6Iv&quot;&gt;6. Проверяем работу контейнера&lt;/h3&gt;
  &lt;pre id=&quot;khcf&quot;&gt;# Проверяем логи
docker logs llm-proxy

# Проверяем, что контейнер запущен
docker ps | grep llm-proxy&lt;/pre&gt;
  &lt;h2 id=&quot;ZYAL&quot;&gt;Настройка клиента для работы через прокси-сервер&lt;/h2&gt;
  &lt;p id=&quot;4IPu&quot;&gt;Для корректной работы необходимо настроить перенаправление всех запросов к зарубежным LLM через ваш прокси-сервер. Ключевая идея решения - переопределить DNS-резолвинг для доменов AI-сервисов, чтобы они указывали на IP-адрес вашего прокси вместо реальных адресов.&lt;/p&gt;
  &lt;h3 id=&quot;9Ya9&quot;&gt;Принцип работы&lt;/h3&gt;
  &lt;p id=&quot;xlAl&quot;&gt;Вместо стандартного DNS-разрешения мы жёстко привязываем определённые доменные имена (api.openai.com, api.anthropic.com и другие) к IP-адресу прокси-сервера. Все запросы к этим доменам автоматически направляются через промежуточный сервер, который уже имеет доступ к зарубежным LLM.&lt;/p&gt;
  &lt;h3 id=&quot;rG8h&quot;&gt;Варианты реализации&lt;/h3&gt;
  &lt;p id=&quot;m5le&quot;&gt;&lt;strong&gt;Вариант 1: Приложение запущено непосредственно на хосте&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Tlax&quot;&gt;Если ваше клиентское приложение работает напрямую в операционной системе сервера, достаточно добавить соответствующие записи в системный файл &lt;code&gt;/etc/hosts&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;RgJf&quot;&gt;YOUR_PROXY_IP api.openai.com
YOUR_PROXY_IP api.anthropic.com
YOUR_PROXY_IP api.cohere.com&lt;/pre&gt;
  &lt;p id=&quot;t9ho&quot;&gt;&lt;strong&gt;Вариант 2: Приложение в Docker-контейнере&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;3sDa&quot;&gt;При использовании Docker необходимо задействовать параметр &lt;code&gt;extra_hosts&lt;/code&gt; в файле &lt;code&gt;docker-compose.yml&lt;/code&gt;. Этот параметр добавляет пользовательские записи в &lt;code&gt;/etc/hosts&lt;/code&gt; внутри изолированной среды контейнера, что позволяет перенаправлять запросы независимо от настроек хост-системы.&lt;/p&gt;
  &lt;h3 id=&quot;GDVc&quot;&gt;Практический пример для n8n на хостинге Beget&lt;/h3&gt;
  &lt;p id=&quot;lwAm&quot;&gt;Ниже представлена пошаговая инструкция настройки для популярной платформы автоматизации n8n, развёрнутой на серверах &lt;a href=&quot;https://beget.com/p23143033&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt;:&lt;/p&gt;
  &lt;h3 id=&quot;CV13&quot;&gt;1. Подключаемся к серверу n8n по SSH&lt;/h3&gt;
  &lt;pre id=&quot;id1K&quot;&gt;ssh root@ip_адрес_сервера_n8n&lt;/pre&gt;
  &lt;h3 id=&quot;t9Qf&quot;&gt;2. Переходим в папку с n8n&lt;/h3&gt;
  &lt;pre id=&quot;nIwm&quot;&gt;cd /opt/beget/n8n/&lt;/pre&gt;
  &lt;h3 id=&quot;970i&quot;&gt;3. Останавливаем контейнер с n8n&lt;/h3&gt;
  &lt;pre id=&quot;UsBk&quot;&gt;docker compose down n8n&lt;/pre&gt;
  &lt;h3 id=&quot;5bSd&quot;&gt;4. Добавляем параметр extra_hosts в docker-compose.yml&lt;/h3&gt;
  &lt;p id=&quot;JFo6&quot;&gt;Находим секцию &lt;code&gt;x-shared: &amp;amp;shared&lt;/code&gt; и внутри нее после &lt;code&gt;volumes&lt;/code&gt; добавляем новый параметр &lt;code&gt;extra_hosts&lt;/code&gt;, вот так:&lt;/p&gt;
  &lt;pre id=&quot;mDpL&quot;&gt;# Запускаем редактор nano
nano docker-compose.yml

# Добавляем extra_hosts
x-shared: &amp;amp;shared
  restart: always
  image: docker.n8n.io/n8nio/n8n:latest
  env_file: .env
  links:
    - postgres
    - redis
  volumes:
    - n8n_storage:/home/node/.n8n
    - ./healthcheck.js:/healthcheck.js
    - ./my_user_folder/pro_files:/home/node/my_user_folder/pro_files
  extra_hosts:
    - &amp;quot;api.openai.com:YOUR_PROXY_IP&amp;quot;
    - &amp;quot;api.anthropic.com:YOUR_PROXY_IP&amp;quot;
    - &amp;quot;api.cohere.com:YOUR_PROXY_IP&amp;quot;
  depends_on:
    redis:
      condition: service_healthy
    postgres:
      condition: service_healthy
&lt;/pre&gt;
  &lt;p id=&quot;8vhR&quot;&gt;где YOUR_PROXY_IP - это IP-адрес вашего прокси сервера&lt;/p&gt;
  &lt;h3 id=&quot;sfVq&quot;&gt;5. Запускаем контейнер с n8n&lt;/h3&gt;
  &lt;pre id=&quot;f5LH&quot;&gt;docker compose up -d n8n&lt;/pre&gt;
  &lt;h3 id=&quot;L7Pd&quot;&gt;6. Проверяем логи&lt;/h3&gt;
  &lt;pre id=&quot;tn2R&quot;&gt;docker compose logs n8n&lt;/pre&gt;
  &lt;p id=&quot;GFcn&quot;&gt;&lt;strong&gt;Готово! Вы успешно настроили доступ к зарубежным AI-сервисам, сохранив при этом соответствие российскому законодательству. Успешной автоматизации!&lt;/strong&gt;&lt;/p&gt;

</content></entry><entry><id>promptica:install-adminer-n8n</id><link rel="alternate" type="text/html" href="https://blog.promptica.ru/install-adminer-n8n?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><title>Установка и настройка Adminer для работы с Postgres в n8n</title><published>2025-08-09T18:23:27.008Z</published><updated>2025-10-11T05:53:35.019Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/a4/61/a461a3d6-6796-4bc5-9dc8-75619e8459e6.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img2.teletype.in/files/1d/14/1d14f4da-11d3-4ac7-996a-d6c4e30cc67d.png&quot;&gt;Гайд по установке Adminer в Docker для управления встроенным Postgres в n8n: настройка домена, Traefik и работа с базами данных.</summary><content type="html">
  &lt;p id=&quot;IFeo&quot;&gt;Часто в workflows &lt;strong&gt;n8n&lt;/strong&gt; требуется сохранить небольшой объем данных в постоянное хранилище, например, идентификатор (&lt;code&gt;id&lt;/code&gt;) сущности или пару строк в кастомную таблицу.&lt;/p&gt;
  &lt;p id=&quot;NdDU&quot;&gt;Поднимать для этого отдельный инстанс &lt;strong&gt;Postgres&lt;/strong&gt; в Docker или заказывать облачный Postgres нецелесообразно, ведь у нас уже есть рабочий инстанс Postgres, установленный вместе с &lt;strong&gt;n8n&lt;/strong&gt;. Можно использовать его, создав отдельную базу данных для экспериментов.&lt;/p&gt;
  &lt;p id=&quot;1kHs&quot;&gt;Для удобного администрирования подойдет &lt;strong&gt;Adminer&lt;/strong&gt; - легковесный менеджер БД с минималистичным интерфейсом и базовым функционалом, которого вполне достаточно для наших задач.&lt;/p&gt;
  &lt;p id=&quot;E22C&quot;&gt;В этой инструкции разберем установку и настройку Adminer в Docker на том же VPS, где работает n8n. В примере используется облачная платформа &lt;a href=&quot;https://beget.com/p2314303&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt;, где можно заказать установку n8n вместе с VPS.&lt;/p&gt;
  &lt;h3 id=&quot;3mO6&quot;&gt;1. Подготовка поддомена&lt;/h3&gt;
  &lt;p id=&quot;8fj0&quot;&gt;Создайте поддомен (например, &lt;code&gt;adminer.&amp;lt;yourdomain.com&amp;gt;&lt;/code&gt;) и направьте его на IP-адрес вашего VPS.&lt;br /&gt;Именно на этом домене будет доступен веб-интерфейс Adminer по HTTPS.&lt;/p&gt;
  &lt;h3 id=&quot;ctNP&quot;&gt;2. Подключение к серверу по SSH&lt;/h3&gt;
  &lt;pre id=&quot;WD7q&quot;&gt;ssh root@ip_адрес_сервера&lt;/pre&gt;
  &lt;h3 id=&quot;hESg&quot;&gt;3. Переход в папку с n8n&lt;/h3&gt;
  &lt;pre id=&quot;cCtT&quot;&gt;cd /opt/beget/n8n&lt;/pre&gt;
  &lt;h3 id=&quot;KcMI&quot;&gt;4. Редактирование docker-compose.yml&lt;/h3&gt;
  &lt;p id=&quot;CPSg&quot;&gt;Откройте файл в редакторе &lt;strong&gt;nano&lt;/strong&gt;:&lt;/p&gt;
  &lt;pre id=&quot;X5Bi&quot;&gt;nano docker-compose.yml&lt;/pre&gt;
  &lt;p id=&quot;CCw9&quot;&gt;В секцию &lt;code&gt;services&lt;/code&gt; добавьте сервис &lt;code&gt;adminer&lt;/code&gt;. Замените &lt;code&gt;&amp;lt;yourdomain.com&amp;gt;&lt;/code&gt; на свой домен.&lt;br /&gt;Для выхода с сохранением в &lt;strong&gt;nano&lt;/strong&gt; нажмите &lt;code&gt;Ctrl + X&lt;/code&gt;, затем подтвердите сохранение клавишей &lt;code&gt;Y&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;RQhS&quot;&gt;  adminer:
    image: adminer:latest
    restart: unless-stopped
    labels:
      - traefik.enable=true
      - traefik.http.routers.adminer.rule=Host(&amp;#x60;adminer.&amp;lt;yourdomain.com&amp;gt;&amp;#x60;)
      - traefik.http.routers.adminer.tls=true
      - traefik.http.routers.adminer.entrypoints=web,websecure
      - traefik.http.routers.adminer.tls.certresolver=mytlschallenge
      - traefik.http.middlewares.adminer.headers.SSLRedirect=true
      - traefik.http.middlewares.adminer.headers.STSSeconds=315360000
      - traefik.http.middlewares.adminer.headers.browserXSSFilter=true
      - traefik.http.middlewares.adminer.headers.contentTypeNosniff=true
      - traefik.http.middlewares.adminer.headers.forceSTSHeader=true
      - traefik.http.middlewares.adminer.headers.SSLHost=adminer.&amp;lt;yourdomain.com&amp;gt;
      - traefik.http.middlewares.adminer.headers.STSIncludeSubdomains=true
      - traefik.http.middlewares.adminer.headers.STSPreload=true
      - traefik.port=8080
    ports:
      - 127.0.0.1:8080:8080
    depends_on:
      - postgres
&lt;/pre&gt;
  &lt;h3 id=&quot;1YpH&quot;&gt;5. Загрузка образа Adminer&lt;/h3&gt;
  &lt;pre id=&quot;SFo7&quot;&gt;docker compose pull adminer&lt;/pre&gt;
  &lt;h3 id=&quot;Og3y&quot;&gt;6. Запуск Adminer&lt;/h3&gt;
  &lt;pre id=&quot;KcM7&quot;&gt;docker compose up -d adminer&lt;/pre&gt;
  &lt;h3 id=&quot;x2FE&quot;&gt;7. Проверка логов&lt;/h3&gt;
  &lt;pre id=&quot;QNC3&quot;&gt;docker compose logs adminer&lt;/pre&gt;
  &lt;h3 id=&quot;3t8X&quot;&gt;8. Подключение к Adminer&lt;/h3&gt;
  &lt;p id=&quot;z4OY&quot;&gt;Если все сделано правильно, Adminer будет доступен по адресу:&lt;/p&gt;
  &lt;pre id=&quot;pGOu&quot;&gt;https://adminer.&amp;lt;yourdomain.com&amp;gt;&lt;/pre&gt;
  &lt;p id=&quot;D4sC&quot;&gt;Чтобы создавать базы данных и таблицы, подключитесь к Postgres с правами администратора.&lt;br /&gt;На VPS &lt;a href=&quot;https://chatgpt.com/c/beget.com/p2314303&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt; с предустановленным n8n админ - это пользователь &lt;code&gt;root&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;iQI9&quot;&gt;Узнать пароль можно командой:&lt;/p&gt;
  &lt;pre id=&quot;lBz9&quot;&gt;cat .env | grep POSTGRES_&lt;/pre&gt;
  &lt;p id=&quot;gPdg&quot;&gt;Первое подключение можно выполнить к базе n8n, после чего создать свою, например &lt;code&gt;my_db&lt;/code&gt;, для экспериментов.&lt;br /&gt;В качестве сервера указывайте имя Docker-сервиса, то есть &lt;code&gt;postgres&lt;/code&gt;.&lt;/p&gt;
  &lt;figure id=&quot;Wvvk&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/1d/14/1d14f4da-11d3-4ac7-996a-d6c4e30cc67d.png&quot; width=&quot;1405&quot; /&gt;
  &lt;/figure&gt;

</content></entry><entry><id>promptica:n8n-postgresql-update</id><link rel="alternate" type="text/html" href="https://blog.promptica.ru/n8n-postgresql-update?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=promptica"></link><title>Как обновить PostgreSQL до версии 17 в n8n на VPS от Бегет</title><published>2025-08-06T17:30:36.758Z</published><updated>2025-08-06T18:09:12.126Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/c9/c0/c9c0f157-316c-44b6-b9c0-c3906e60433c.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/ca/56/ca56bd96-50c6-4b79-98e8-4c78f264d7cd.png&quot;&gt;При автоматической установке n8n на VPS от Beget используется устаревшая версия PostgreSQL - 11 (выпущена в 2018 году). Актуальная версия на 2025 год - PostgreSQL 17, содержащая множество улучшений в области безопасности и производительности.</summary><content type="html">
  &lt;p id=&quot;0mZk&quot;&gt;Многие выбирают облачную платформу &lt;a href=&quot;https://beget.com/p2314303&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt; для размещения self-hosted версии n8n на VPS по следующим причинам:&lt;/p&gt;
  &lt;ul id=&quot;dZUP&quot;&gt;
    &lt;li id=&quot;UoG8&quot;&gt;&lt;strong&gt;Низкие тарифы&lt;/strong&gt; - от 9 ₽ в день. Можно пополнить баланс на 30 ₽ и протестировать работу n8n в течение трёх дней на выбранном тарифе.&lt;/li&gt;
    &lt;li id=&quot;ZfP5&quot;&gt;&lt;strong&gt;Прозрачное проксирование запросов к OpenAI API&lt;/strong&gt; - вы можете без проблем обращаться к &lt;code&gt;api.openai.com&lt;/code&gt; даже с российских IP, минуя блокировку:&lt;code&gt;{&amp;quot;error&amp;quot;:{&amp;quot;code&amp;quot;:&amp;quot;unsupported_country_region_territory&amp;quot;, &amp;quot;message&amp;quot;:&amp;quot;Country, region, or territory not supported&amp;quot;, &amp;quot;param&amp;quot;:null, &amp;quot;type&amp;quot;:&amp;quot;request_forbidden&amp;quot;}} &lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;JBZb&quot;&gt;&lt;strong&gt;Бесплатная установка n8n&lt;/strong&gt; - при заказе нового VPS вы можете сразу получить настроенную версию n8n с защищённым HTTPS-доступом.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;GPDf&quot;&gt;Однако стоит учитывать один нюанс: при автоматической установке используется устаревшая версия PostgreSQL - 11 (выпущена в 2018 году). Актуальная версия на 2025 год - &lt;strong&gt;PostgreSQL 17&lt;/strong&gt;, содержащая множество улучшений в области безопасности и производительности. N8n корректно работает с 17 версией.&lt;/p&gt;
  &lt;p id=&quot;PXIR&quot;&gt;Ниже - пошаговая инструкция по обновлению PostgreSQL до версии 17 для n8n на VPS от &lt;a href=&quot;https://beget.com/p2314303&quot; target=&quot;_blank&quot;&gt;Бегет&lt;/a&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Qvi1&quot;&gt;Пошаговая инструкция&lt;/h2&gt;
  &lt;h3 id=&quot;8xAp&quot;&gt;1. Подключение к серверу по SSH&lt;/h3&gt;
  &lt;pre id=&quot;FZ2P&quot; data-lang=&quot;bash&quot;&gt;ssh root@&amp;lt;ip_адрес_сервера&amp;gt;&lt;/pre&gt;
  &lt;h3 id=&quot;pZLH&quot;&gt;2. Переход в директорию n8n&lt;/h3&gt;
  &lt;pre id=&quot;OGll&quot; data-lang=&quot;bash&quot;&gt;cd /opt/beget/n8n&lt;/pre&gt;
  &lt;h3 id=&quot;z7To&quot;&gt;3. Остановка сервиса n8n&lt;/h3&gt;
  &lt;pre id=&quot;AxZl&quot; data-lang=&quot;bash&quot;&gt;docker compose stop n8n&lt;/pre&gt;
  &lt;h3 id=&quot;EW9x&quot;&gt;4. Создание дампа базы данных&lt;/h3&gt;
  &lt;p id=&quot;MKHa&quot;&gt;Уточните имя контейнера с PostgreSQL:&lt;/p&gt;
  &lt;pre id=&quot;EPIQ&quot; data-lang=&quot;bash&quot;&gt;docker compose ps | grep postgres&lt;/pre&gt;
  &lt;p id=&quot;liwh&quot;&gt;Скорее всего, он называется &lt;code&gt;n8n-postgres-1&lt;/code&gt;. Выполните дамп БД:&lt;/p&gt;
  &lt;pre id=&quot;fVYd&quot; data-lang=&quot;bash&quot;&gt;docker exec -it n8n-postgres-1 pg_dump -U root n8n &amp;gt; n8n_backup.sql&lt;/pre&gt;
  &lt;h3 id=&quot;ImmT&quot;&gt;5. Остановка сервиса PostgreSQL&lt;/h3&gt;
  &lt;pre id=&quot;TqmA&quot; data-lang=&quot;bash&quot;&gt;docker compose stop postgres&lt;/pre&gt;
  &lt;h3 id=&quot;V1VB&quot;&gt;6. Создание резервных копий&lt;/h3&gt;
  &lt;pre id=&quot;sADD&quot; data-lang=&quot;bash&quot;&gt;mv db_storage db_storage_backup
mkdir db_storage
cp init-data.sh init-data_backup.sh
cp docker-compose.yml docker-compose_backup.yml&lt;/pre&gt;
  &lt;h3 id=&quot;14xc&quot;&gt;7. Обновление версии PostgreSQL в &lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/h3&gt;
  &lt;pre id=&quot;CKg1&quot; data-lang=&quot;bash&quot;&gt;sed -i &amp;#x27;s#postgres:11#postgres:17#g&amp;#x27; docker-compose.yml&lt;/pre&gt;
  &lt;h3 id=&quot;AOqb&quot;&gt;8. Обновление скрипта инициализации &lt;code&gt;init-data.sh&lt;/code&gt;&lt;/h3&gt;
  &lt;p id=&quot;xJMi&quot;&gt;Содержимое должно быть следующим:&lt;/p&gt;
  &lt;pre id=&quot;qrcm&quot; data-lang=&quot;bash&quot;&gt;cat &amp;gt; init-data.sh &amp;lt;&amp;lt; &amp;#x27;EOF&amp;#x27;
#!/bin/bash
set -e;

if [ -n &amp;quot;${POSTGRES_NON_ROOT_USER:-}&amp;quot; ] &amp;amp;&amp;amp; [ -n &amp;quot;${POSTGRES_NON_ROOT_PASSWORD:-}&amp;quot; ]; then
    psql -v ON_ERROR_STOP=1 --username &amp;quot;$POSTGRES_USER&amp;quot; --dbname &amp;quot;$POSTGRES_DB&amp;quot; &amp;lt;&amp;lt;-EOSQL
        CREATE USER &amp;quot;${POSTGRES_NON_ROOT_USER}&amp;quot; WITH PASSWORD &amp;#x27;${POSTGRES_NON_ROOT_PASSWORD}&amp;#x27;;
        GRANT ALL PRIVILEGES ON DATABASE &amp;quot;${POSTGRES_DB}&amp;quot; TO &amp;quot;${POSTGRES_NON_ROOT_USER}&amp;quot;;
        GRANT CREATE ON SCHEMA public TO &amp;quot;${POSTGRES_NON_ROOT_USER}&amp;quot;;
EOSQL
else
    echo &amp;quot;SETUP INFO: No Environment variables given!&amp;quot;
fi
EOF&lt;/pre&gt;
  &lt;h3 id=&quot;qA5t&quot;&gt;9. Загрузка нового образа PostgreSQL&lt;/h3&gt;
  &lt;pre id=&quot;hVzP&quot; data-lang=&quot;bash&quot;&gt;docker compose pull postgres&lt;/pre&gt;
  &lt;h3 id=&quot;fV5B&quot;&gt;10. Запуск новой версии PostgreSQL&lt;/h3&gt;
  &lt;pre id=&quot;gCH5&quot; data-lang=&quot;bash&quot;&gt;docker compose up -d postgres&lt;/pre&gt;
  &lt;h3 id=&quot;o67P&quot;&gt;11. Проверка логов PostgreSQL&lt;/h3&gt;
  &lt;p id=&quot;twcE&quot;&gt;Убедитесь, что нет ошибок:&lt;/p&gt;
  &lt;pre id=&quot;G6W0&quot; data-lang=&quot;bash&quot;&gt;docker compose logs postgres&lt;/pre&gt;
  &lt;h3 id=&quot;RyH5&quot;&gt;12. Восстановление дампа в новую базу данных&lt;/h3&gt;
  &lt;pre id=&quot;j7z4&quot; data-lang=&quot;bash&quot;&gt;cat n8n_backup.sql | docker exec -i n8n-postgres-1 psql -U root -d n8n&lt;/pre&gt;
  &lt;h3 id=&quot;lPDI&quot;&gt;13. Запуск сервиса n8n&lt;/h3&gt;
  &lt;pre id=&quot;cJWD&quot; data-lang=&quot;bash&quot;&gt;docker compose start n8n&lt;/pre&gt;
  &lt;h3 id=&quot;i6P2&quot;&gt;14. Проверка логов n8n&lt;/h3&gt;
  &lt;pre id=&quot;DNGA&quot; data-lang=&quot;bash&quot;&gt;docker compose logs n8n --tail 100&lt;/pre&gt;
  &lt;h3 id=&quot;EMua&quot;&gt;15. Проверка интерфейса n8n&lt;/h3&gt;
  &lt;p id=&quot;06my&quot;&gt;Убедитесь, что все workflows работают корректно. Если всё в порядке - удалите временные файлы:&lt;/p&gt;
  &lt;pre id=&quot;aSQs&quot; data-lang=&quot;bash&quot;&gt;rm init-data_backup.sh docker-compose_backup.yml n8n_backup.sql
rm -rf db_storage_backup&lt;/pre&gt;
  &lt;h3 id=&quot;6Exq&quot;&gt;16. Очистка неиспользуемых Docker-образов&lt;/h3&gt;
  &lt;pre id=&quot;coKQ&quot; data-lang=&quot;bash&quot;&gt;docker image prune -a&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;p id=&quot;31pt&quot;&gt;Если вы всё сделали по инструкции - поздравляю! Теперь ваша система работает с актуальной и безопасной версией PostgreSQL 17.&lt;/p&gt;

</content></entry></feed>