MAATRIX / Блог / Как установить и настроить Langflow на VPS

Как установить и настроить Langflow на VPS

Как установить и настроить Langflow на VPS

MAATRIX

Langflow собирает агента или RAG-пайплайн мышью на холсте и сразу отдаёт результат как HTTP-эндпоинт — поэтому его и выносят на сервер, а не держат на ноутбуке. Но установка Langflow на VPS в 2026 году начинается не с docker run -p 7860:7860: за последние полтора года у проекта было две неаутентифицированные RCE с оценкой 9.8, обе попали в каталог активно эксплуатируемых уязвимостей CISA и обе находились сканерами за часы. Ниже — рабочая установка с закреплённой версией, Postgres, секретами и HTTPS, и честный разбор мест, где она ломается.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →

Что такое Langflow и какую версию ставить в 2026 году

Langflow — визуальный конструктор LLM-приложений на Python. Бэкенд на FastAPI, фронтенд — React-холст, всё в одном процессе, который по умолчанию слушает порт 7860. Вы соединяете узлы (модель, ретривер, парсер, инструмент, агент), сохраняете поток — и Langflow публикует его как API. Код открыт под MIT; проект родился в Logspace, был куплен DataStax и вместе с ним перешёл к IBM. В отличие от Flowise, ушедшего в августе 2026-го в архив, у Langflow есть кому выпускать патчи — и это в его случае критично.

ВерсияКогдаЧто принесла
1.86 марта 2026централизованная настройка провайдеров моделей, V2-API потоков
1.9весна 2026Langflow Assistant, Flow DevOps Toolkit, MCP для IDE и кодовых агентов
1.10лето 2026сборка потоков ассистентом, Memory bases, DB Providers, локализация
1.115 августа 2026Human-in-the-Loop, поддержка A2A, AG-UI-стриминг в Workflow API

Требования к Python у 1.11 — от 3.10 до 3.14. Ubuntu 24.04 приносит системный Python 3.12, и это ровно то, что нужно.

Два изменения в 1.11.x ломают привычки. Часть интеграций сторонних провайдеров уехала из ядра в пакет lfx-bundles: обычная установка uv pip install langflow тянет их автоматически, но если ставить облегчённый lfx отдельно, провайдеров придётся доустанавливать руками. И компоненты, которым нужен PyTorch (CUGA, Code Agents, локальная конвертация Docling), в стандартную поставку больше не входят — узел просто не появится в палитре.

Главное решение до всякой установки: версия не ниже 1.9.0. Это не вкусовщина, и почему — ниже.

Две RCE, из-за которых порт 7860 не выставляют наружу

У Langflow два критических провала, и оба устроены одинаково: HTTP-эндпоинт без аутентификации передавал пользовательский код прямо в exec().

CVEЭндпоинтУязвимые версииИсправлено в
CVE-2025-3248POST /api/v1/validate/codeвсё до 1.3.01.3.0
CVE-2026-33017POST /api/v1/build_public_tmp/{flow_id}/flow1.8.2 и всё раньше1.9.0

CVE-2025-3248 (CVSS 9.8) — эндпоинт проверки кода компонента вызывал exec() на присланной строке без авторизации и песочницы. Одного POST-запроса хватало для выполнения произвольного кода от имени процесса. CISA внесла её в KEV в мае 2025-го, Trend Micro описала кампанию, где через неё разворачивали ботнет Flodrix.

CVE-2026-33017 (тоже 9.8, раскрыта 17 марта 2026) — история повторилась в новом месте. Эндпоинт сборки публичных потоков по замыслу берёт данные из базы, но при переданном необязательном параметре data принимал определения узлов от клиента — вместе с питоновским кодом внутри. Дальше всё тот же exec(). Дедлайн CISA для госорганов США был 8 апреля 2026, а Orca фиксировала массовую установку майнеров на публично торчащих инстансах.

Нюанс, из-за которого многие остались дырявыми, считая себя пропатченными: версия 1.8.2, которую половина источников назвала исправленной, эксплуатируется по-прежнему. JFrog показала, что фикс закрыл частный случай, а не корень — вызов exec() в пути сборки потока всё ещё принимал управляемый атакующим ввод. Проверенная граница одна: 1.9.0. Временным вариантом были ночные сборки от 1.9.0.dev18.

Проверить, что реально запущено:

curl -s http://127.0.0.1:7860/api/v1/version
curl -s http://127.0.0.1:7860/health

Первый вернёт JSON с полем version, второй — {"status":"ok"}. Молчит /health — процесс не поднялся, до интерфейса дело не дошло.

Отсюда три правила, зашитые дальше во все конфиги: тег latest в проде не используем — вы не знаете, что у вас крутится, когда выходит следующий бюллетень; порт 7860 наружу не публикуем никогда, ни «на пять минут посмотреть» (обе кампании находили жертв массовым сканированием); между интернетом и Langflow всегда стоит реверс-прокси с TLS, а фаервол пропускает только 22, 80 и 443.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Подготовка сервера и установка в Docker

Чистая Ubuntu 24.04. Первым делом фаервол — до того, как что-то поднимется:

ufw allow 22/tcp && ufw allow 80,443/tcp && ufw --force enable
curl -fsSL https://get.docker.com | sh
docker compose version

Дальше секреты. Langflow шифрует чувствительные данные библиотекой Fernet и подписывает JWT по HS256 — и то, и другое берёт из LANGFLOW_SECRET_KEY. Не зададите — ключ сгенерируется сам и ляжет файлом в конфигурационный каталог; потеряете каталог, потеряете доступ ко всем сохранённым переменным.

mkdir -p /opt/langflow && cd /opt/langflow
umask 077
{
  echo "LANGFLOW_SECRET_KEY=$(python3 -c 'from secrets import token_urlsafe; print(token_urlsafe(32))')"
  echo "LANGFLOW_SUPERUSER=admin"
  echo "LANGFLOW_SUPERUSER_PASSWORD=$(openssl rand -base64 24)"
  echo "POSTGRES_PASSWORD=$(openssl rand -hex 20)"
} > /opt/langflow/.env
cat /opt/langflow/.env

Пароль суперпользователя выпишите сразу: он нужен при первом входе, а в интерфейсе его потом не подсмотреть.

Теперь docker-compose.yml. Три важные вещи: закреплённый тег версии, публикация порта только на loopback и Postgres вместо SQLite.

services:
  langflow:
    image: langflowai/langflow:1.11.0
    container_name: langflow
    restart: unless-stopped
    depends_on:
      - postgres
    ports:
      - "127.0.0.1:7860:7860"
    env_file: .env
    environment:
      - LANGFLOW_HOST=0.0.0.0
      - LANGFLOW_PORT=7860
      - LANGFLOW_AUTO_LOGIN=false
      - LANGFLOW_CONFIG_DIR=/app/langflow
      - LANGFLOW_DATABASE_URL=postgresql://langflow:${POSTGRES_PASSWORD}@postgres:5432/langflow
      - LANGFLOW_NEW_USER_IS_ACTIVE=false
      - LANGFLOW_LOG_LEVEL=info
      - DO_NOT_TRACK=true
    volumes:
      - langflow-data:/app/langflow

  postgres:
    image: postgres:17-alpine
    container_name: langflow-db
    restart: unless-stopped
    environment:
      - POSTGRES_USER=langflow
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=langflow
    volumes:
      - langflow-db:/var/lib/postgresql/data

volumes:
  langflow-data:
  langflow-db:
docker compose up -d && docker compose logs -f langflow
curl -s http://127.0.0.1:7860/health

Что здесь неочевидно:

  • LANGFLOW_HOST=0.0.0.0 внутри контейнера — не дыра. Наружу процесс доступен только через 127.0.0.1:7860 на хосте, так описан проброс. А LANGFLOW_HOST=127.0.0.1 посадит приложение на loopback внутри контейнера, и Docker не пробросит его вообще — получите пустой ответ на любой запрос.
  • LANGFLOW_CONFIG_DIR=/app/langflow — каталог с логами, файловым хранилищем, данными мониторинга и файлом секретного ключа. Именно он должен быть на постоянном томе.
  • Именованный том, а не bind-mount. Официальный образ работает не от root, и каталог хоста с правами root:root даёт при старте PermissionError: [Errno 13] Permission denied. Именованный том Docker создаёт с правильным владельцем сам; если бинд-маунт нужен принципиально — chown -R 1000:1000 до первого запуска.
  • LANGFLOW_NEW_USER_IS_ACTIVE=false — новые регистрации требуют ручной активации. Без этого на публичном адресе аккаунт заводит любой желающий.
  • Postgres сразу. Перевести SQLite на Postgres потом можно только экспортом и импортом потоков вручную.

Две грабли со строкой подключения. Схему postgres:// Langflow молча перепишет в postgresql:// при санитизации URL — заведутся оба варианта. А вот драйвер asyncpg не подходит: Langflow рассчитан на psycopg, у asyncpg строже обращение с таймзонами. Не «оптимизируйте» URL до postgresql+asyncpg://.

Установка через uv и systemd, когда Docker не нужен

Иногда контейнеров на машине быть не должно — сервер занят панелью со своим Docker-хозяйством. Тогда ставим в виртуальное окружение. Менеджер uv здесь не мода: дерево зависимостей у Langflow огромное, и обычный pip разрешает его недопустимо долго.

apt update && apt install -y python3.12 python3.12-venv build-essential curl
curl -LsSf https://astral.sh/uv/install.sh | sh
useradd -r -m -d /opt/langflow -s /usr/sbin/nologin langflow
sudo -u langflow bash -lc '
  cd /opt/langflow
  uv venv --python 3.12 .venv
  source .venv/bin/activate
  uv pip install "langflow==1.11.0"
'

Три ошибки, которые встречают здесь чаще всего.

No module named 'langflow.__main__' — в системе остался старый Langflow, и команда langflow указывает не туда. Запускайте через модуль (python -m langflow run) либо переустанавливайте: python -m pip install langflow --pre -U --force-reinstall. В venv проблема почти не возникает, ради чего venv и нужен.

Питон новее, чем есть колёса. На Python 3.13 и выше часть зависимостей до сих пор не имеет готовых wheel-пакетов, и установка разваливается на сборке из исходников: в трассировке будет не «Langflow не поддерживается», а error: Failed to build с ошибкой компилятора внутри. Лечение — 3.12, а не героическая доустановка компиляторов.

Нехватка памяти. На машине с 1 ГБ RAM разрешение зависимостей убивается по OOM: Killed в консоли и Out of memory: Killed process в dmesg. Своп на время установки закрывает вопрос: fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile.

Дальше юнит systemd — секреты в отдельном файле, не в самом юните:

[Unit]
Description=Langflow
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=langflow
Group=langflow
WorkingDirectory=/opt/langflow
EnvironmentFile=/etc/langflow/langflow.env
ExecStart=/opt/langflow/.venv/bin/langflow run --host 127.0.0.1 --port 7860
Restart=on-failure
RestartSec=10
TimeoutStartSec=300

[Install]
WantedBy=multi-user.target
install -d -m 750 -o root -g langflow /etc/langflow
chown root:langflow /etc/langflow/langflow.env && chmod 640 /etc/langflow/langflow.env
systemctl daemon-reload && systemctl enable --now langflow && journalctl -u langflow -f

TimeoutStartSec=300 — не перестраховка: первый старт импортирует все компоненты и на слабом vCPU занимает больше минуты, а systemd с дефолтным таймаутом успевает решить, что сервис завис, и убить его на середине инициализации базы. Права на env-файл — вторая по частоте причина «сервис не стартует»: файл 600 root:root при юните от пользователя langflow даёт в журнале Failed to load environment files: Permission denied. И проверьте, свободен ли порт: lsof -i :7860 покажет занявший его процесс, иначе получите [Errno 98] Address already in use.

Домен, HTTPS и Nginx: где ломается стриминг

Направьте A-запись langflow.example.com на IP сервера и выпустите сертификат: apt install -y nginx certbot python3-certbot-nginx, затем certbot --nginx -d langflow.example.com.

Дальше блок location — и здесь типовые инструкции подводят. Langflow отдаёт ответы модели потоком через Server-Sent Events, а события сборки потока на холсте — по WebSocket. На дефолтном прокси-конфиге вы получите холст, который «думает» и разом выплёвывает ответ через полминуты, либо обрыв посреди длинного запуска.

server {
    server_name langflow.example.com;
    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:7860;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
    }
}

Что чинит каждая строка:

  • proxy_buffering off — без неё Nginx копит SSE-поток в буфере, и токены доезжают до браузера одним куском в конце. Это ровно то, что описывают как «стриминг не работает».
  • proxy_http_version 1.1 плюс Upgrade и Connection — иначе WebSocket-апгрейд не проходит и события сборки до холста не долетают.
  • proxy_read_timeout 600s — дефолт Nginx 60 секунд. Агентный поток с несколькими вызовами инструментов живёт дольше и рвётся посередине с 504 Gateway Time-out, причём в логах Langflow запуск будет выглядеть успешным. Для сравнения: собственный таймаут выполнения инструмента MCP у Langflow по умолчанию 180 секунд.
  • client_max_body_size 100m — дефолт Nginx 1 МБ. Загрузка PDF в базу знаний упрётся в прокси и вернёт 413 Request Entity Too Large, а в логах приложения не будет ничего: запрос до него не дошёл.
  • X-Forwarded-Proto $scheme — без него приложение считает себя работающим по HTTP и генерирует ссылки на http://, что в браузере даёт mixed content.

Если возиться с сертификатами не хочется, в документации Langflow есть готовый вариант с Caddy: он получает и продлевает сертификат сам. Nginx выбирают, когда на сервере уже живут другие сайты.

Аутентификация, ключи потока и что обязательно бэкапить

Вход. LANGFLOW_AUTO_LOGIN — режим разработки: при true первый визит в браузере создаёт сессию суперпользователя без пароля. Официальные Docker-образы ставят LANGFLOW_AUTO_LOGIN=false, и при этом значении LANGFLOW_SUPERUSER_PASSWORD обязателен — без него старт не пройдёт. Легендарная пара langflow/langflow больше не работает: дефолтный пароль убрали, и попытка выставить его вручную роняет старт намеренно, по принципу fail closed.

API-ключи. Начиная с 1.5 почти все эндпоинты требуют ключ; он создаётся в интерфейсе и передаётся заголовком x-api-key. Вызов опубликованного потока:

curl -X POST "https://langflow.example.com/api/v1/run/$FLOW_ID?stream=false" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $LANGFLOW_API_KEY" \
  -d '{
        "input_value": "Какие у вас условия возврата?",
        "input_type": "chat",
        "output_type": "chat"
      }'

Поле tweaks в теле запроса переопределяет настройки конкретных узлов на лету — удобно, когда один поток обслуживает нескольких клиентов с разными промптами.

Ключи моделей кладут в Global Variables, где они шифруются тем самым LANGFLOW_SECRET_KEY. Отсюда правило бэкапа: копировать надо и базу, и секретный ключ. Сохранили дамп Postgres без .env — потоки развернутся, а переменные с ключами останутся нерасшифровываемым мусором.

cd /opt/langflow
docker compose exec -T postgres pg_dump -U langflow langflow | gzip > /root/langflow-$(date +%F).sql.gz
cp /opt/langflow/.env /root/langflow-env-$(date +%F)

Здесь же всплывает вещь, к Langflow отношения не имеющая, но ломающая ровно те же потоки: провайдеры смотрят на исходящий IP сервера. С российского адреса OpenAI отвечает 403 unsupported_country_region_territory, Google для Gemini — User location is not supported for the API use. Ключ рабочий, а узел в потоке красный. Перевыпуск ключа не помогает — помогает сервер в подходящей локации.

Рост нагрузки. Один процесс обслуживает запросы асинхронно, но тяжёлый узел (разбор большого PDF, локальные эмбеддинги) блокирует событийный цикл, и соседние запуски ждут. Тогда включают несколько воркеров через LANGFLOW_WORKERS. Честно: каждый воркер — ещё один полный набор загруженных компонентов в памяти. Команда проекта отчитывалась о сокращении расхода памяти примерно на 89% за счёт чистки зависимостей и copy-on-write при форке, но порядок величин такой, что второй воркер стоит вам гигабайта. Включайте, когда упёрлись, а не заранее.

Какой сервер под Langflow брать в MAATRIX

Нагрузка у Langflow оркестраторская: он почти всё время ждёт ответа модели, векторной базы или внешнего API. Процессор нужен на разбор документов и на старт с импортом компонентов, память — на питоновский процесс с загруженной палитрой узлов. Официальные требования проекта — минимум двухъядерный процессор и 2 ГБ RAM, рекомендуется многоядерный и не меньше 4 ГБ; в гайде по production-развёртыванию в Kubernetes бэкенду отводят 2Gi памяти и 1000m CPU на реплику. Отсюда три честные конфигурации:

  • Минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Langflow в Docker, Postgres рядом, Nginx с сертификатом, один-два пользователя, потоки на облачных моделях. Почему не 2 ГБ, раз документация их допускает: 2 ГБ — это один процесс без базы и без запаса, установка через uv там уже требует свопа. Ограничения называю прямо — параллельная загрузка нескольких больших PDF в базу знаний на 4 ГБ закончится процессом, убитым по OOM, а второй воркер не поднять.
  • Комфорт: 4 vCPU, 8 ГБ RAM, 80 ГБ NVMe. Помещаются Langflow с двумя воркерами, Postgres, Redis, векторная база вроде Qdrant и место под загруженные документы. Разумная точка старта для команды, у которой потоки работают в проде, а не на демо.
  • Нагрузка и несколько воркспейсов: 8 vCPU, 16 ГБ RAM. Спокойные обновления, бэкапы без пауз, запас на индексацию корпуса документов.

Если LLM должна крутиться на своём железе, планируйте под неё отдельную машину. На нашем стенде — AMD EPYC 9554, 16 vCPU, Ollama 0.33.1 — qwen2.5:7b в кванте Q4_K_M занимает 5,1 ГБ памяти и даёт около 7,6 токена в секунду на CPU, llama3.1:8b — 5,6 ГБ и 12,8 ток/с, qwen2.5:3b — 2,2 ГБ и 34,1 ток/с. Деталь того же замера: генерация выходит на полку уже на четырёх потоках (num_thread 4), дальше упор идёт в память, а не в ядра, а 32 потока на 16 vCPU обрушивают скорость в двадцать раз, до 0,35 ток/с. Langflow и локальная модель на одном сервере дерутся за одну шину памяти — страдают оба. Расчёт по моделям — в статье сколько RAM нужно для Ollama.

Локация — Великобритания, Лондон. Причина прикладная: Langflow почти всегда ходит в чужие API, и лондонский адрес у OpenAI, Anthropic и Google принимается штатно, без тех самых 403 по региону. До европейских дата-центров пинг минимальный, а из Москвы RTT до Лондона заметно меньше, чем до Нью-Йорка — при работе на холсте, где каждое действие идёт через сервер, это чувствуется руками. Если аудитория ваших ботов в Америке, берите Нью-Йорк, разница только в маршруте. Российская локация под Langflow с облачными моделями не годится: интерфейс будет летать, а узлы моделей упираться в блокировку по региону.

Про установку честно: Langflow в каталоге apps.maatrix.io нет. Сервер приезжает чистым — Ubuntu 24.04 или Debian, root-доступ, — и Langflow вы ставите по инструкции выше, минут за пятнадцать вместе с сертификатом. Зато в каталоге есть готовые сборки родственных сервисов: они разворачиваются автоматически при заказе, доступы появляются в личном кабинете — n8n, Dify, AnythingLLM, Open WebUI, Ollama, LiteLLM, Qdrant, Langfuse, Portainer. Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT: зарубежная карта не нужна, хотя сервер стоит в Лондоне.

Порядок действий на новом сервере всегда один: сначала ufw и реверс-прокси, потом первый запуск Langflow, и только потом первое открытие интерфейса в браузере. Кто увидит экран создания администратора раньше вас — тот и станет владельцем инстанса.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →

Частые вопросы

Можно ли выставить 7860 наружу, если инстанс закрыт паролем?

Нет. Обе критические уязвимости Langflow — CVE-2025-3248 и CVE-2026-33017 — эксплуатировались без аутентификации: пароль от интерфейса на них не влиял вообще. Публикуйте порт только на 127.0.0.1, наружу пускайте через Nginx или Caddy с TLS и держите версию не ниже 1.9.0.

Обновился, и контейнер перестал стартовать. Что случилось?

Скорее всего, вы приехали на версию, где убрали дефолтный пароль. При LANGFLOW_AUTO_LOGIN=false переменная LANGFLOW_SUPERUSER_PASSWORD обязательна, а значение langflow запрещено — старт падает намеренно, вместо тихого создания уязвимого аккаунта. Задайте нормальный пароль в .env и перезапустите.

Перенёс базу на новый сервер, а потоки падают на ключах моделей. Почему?

Переменные из Global Variables зашифрованы значением LANGFLOW_SECRET_KEY. Без него строки в базе есть, но расшифровать их нечем. Переносите .env вместе с дампом; если ключ утерян — переменные придётся завести заново вручную.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.