Langflow – Guia rápido

Saudações.

Esse tutorial ensina como implementar o Langflow em container Docker.

1 – O que é Langflow

Langflow é uma plataforma visual de low-code/no-code (tipo o N8N) para criar aplicações de inteligência artificial, agentes e fluxos de IA.

Ele é framework de código aberto, baseado em Python, personalizável e focado na criação de aplicações de IA.

O editor visual simplifica a criação de protótipos de fluxos de trabalho de aplicativos, permitindo que os desenvolvedores (você) transformem rapidamente suas ideias em soluções aplicáveis ​​ao mundo real.

Principais recursos:

  • Construção de workflows de tratamento de dados;
  • Nodes prontos para tratamento de dados;
  • Nodes prontos para configuração de agentes;
  • Acesso à contas de provedores de IA (OpenAI, Anthropic, …).

Pré-requisitos:

  • Internet no servidor Docker;
  • Banco de dados PostgreSQL, preferencialmente com PGVector incluso.

2 – Preparando ambiente

Você deve preparar previamente:

  • O servidor/VPS/VM com Docker;
  • A rede “network_public“;
  • O traefik como proxy-reverso com LetsEncrypt, ligado à rede “network_public“;

2.1 – Container do PostgreSQL

Vou usar o Postgres como base de armazenamento de dados do Langflow.

O PG é opcional, se a URL do banco de dados não for informada os dados serão armazenados em um arquivo SQLITE no volume do container Langflow.

Vou usar a imagem pgvector (Debian Trixie + Postgres 18 + PGVector).

O nome do container será “langflow-database” e as credenciais:

  • Usuário: langflow
  • Senha: tulipasql
  • Banco de dados: langflow
Bash
# Variaveis
    NAME="langflow-database";

# Argumentos do postgres (usado somente no primeiro boot)
    POSTGRES_USER="langflow";
    POSTGRES_PASSWORD="tulipasql";
    POSTGRES_DB="langflow";

# Imagem
    IMAGE="pgvector/pgvector:pg18-trixie";
    docker pull $IMAGE;

# Volume
    # obs: pg18 usa pasta principal interna: /var/lib/postgresql
    DATADIR=/storage/$NAME;
    mkdir -p          $DATADIR;
    chown -R 999:999  $DATADIR;

# Renovar/rodar:
    docker rm -f $NAME 2>/dev/null;
    docker run \
        -d \
        --restart            always \
        --name               $NAME \
        --hostname           $NAME.intranet.br \
        \
        --cpus                2.0 \
        --cpu-shares         1024 \
        --memory               2g \
        --memory-swap          2g \
        --memory-reservation   1g \
        --shm-size             1g \
        \
        --network            network_public \
        \
        --tmpfs              /run:rw,noexec,nosuid,size=64m \
        --tmpfs              /tmp:rw,exec,suid,size=64m \
        \
        -v $DATADIR:/var/lib/postgresql \
        \
        -e POSTGRES_USER=$POSTGRES_USER \
        -e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
        -e POSTGRES_DB=$POSTGRES_DB \
        -e PGDATA=/var/lib/postgresql/data/pgdata \
        \
        --health-cmd="pg_isready -U postgres" \
        --health-interval=5s \
        --health-timeout=5s \
        --health-retries=10 \
        \
        --entrypoint "docker-entrypoint.sh" \
        \
        $IMAGE \
            postgres \
              --max_connections=8192 \
              --wal_level=minimal \
              --max_wal_senders=0 \
              --port=5432;

2.2 – Usando Postgres pré-existente

Caso você ja tenha um banco de dados central e queira apenas criar o usuário e banco do LangFlow, siga os procedimentos no terminal PSQL:

PostgreSQL Shell (psql)
-- usuario do container local:
CREATE USER langflow
    WITH PASSWORD 'tulipasql'
        LOGIN;

-- criar db e usuario do chatwoot
CREATE DATABASE langflow
    WITH 
    OWNER = langflow
        ENCODING = 'UTF8'
        TABLESPACE = pg_default
        IS_TEMPLATE = False
        CONNECTION LIMIT = -1;

-- Conectar no banco:
\c langflow;

-- Sair
\q

3 – Rodando o Langflow

Agora vamos ao Langflow em si.

3.1 – Variáveis de ambiente

Observe as variáveis e configure adequadamente de acordo com seu ambiente.

VariávelPadrãoFunção
LANGFLOW_HOST0.0.0.0IP para abrir porta TCP/HTTP de escuta.
LANGFLOW_PORT7860Porta padrão do servidor monolítico Langflow.
LANGFLOW_AUTO_LOGINfalseExige login em vez de compartilhar uma sessão iniciada automáticamente.
LANGFLOW_SUPERUSER(preencha)Super usuário
LANGFLOW_SUPERUSER_PASSWORD(preencha)Senha do super usuário.
LANGFLOW_SECRET_KEY(preencha)Usada para criptografar credenciais, não altere após iniciar o uso.
LANGFLOW_DATABASE_URL(vazio)Caminho completo do Postgres. Se deixar em branco usa SQLITE internamente.
LANGFLOW_CONFIG_DIR/app/langflowDiretório de armazenamento de configurações.
LANGFLOW_ENABLE_SIGNUPfalseControla cadastro público direto.
LANGFLOW_LOG_ENVcontainer ou container_jsonFacilita coleta por Docker, Loki ou outro agregador.
LANGFLOW_ALLOW_CUSTOM_COMPONENTSdepende do modelo de ameaçaCódigo customizado pode executar código no servidor.
LANGFLOW_SSRF_PROTECTION_ENABLEDtrue em instalação pública, após allowlistReduz acesso indevido a redes privadas a partir de componentes.

3.2 – Criar container Langflow

Você precisará de um nome de DNS para acessá-lo via HTTPs (pelo Traefik), no exemplo vou usar langflow.seudominio.com.br

Script para criar container via “docker run“:

Bash
# Variaveis
    NAME=langflow;
    FQDN="langflow.seudominio.com.br";
    LOCAL=$NAME.intranet.br;

# Variaveis do acesso postgres
    PG_HOST="pgvector-main"; # < Nome do container ou ip/fqdn do Postgres
    PG_PORT="5432";
    PG_USER="langflow";
    PG_PASS="tulipasql";
    PG_DB='langflow';
    # URL PG final:
    DB_URL="postgresql://${PG_USER}:${PG_PASS}@${PG_HOST}:${PG_PORT}/${PG_DB}";

# Variaveis langflow
    # - Acesso administrativo
    LANGFLOW_SUPERUSER="admin";
    LANGFLOW_SUPERUSER_PASSWORD="tulipa";
    # - Controle de usuarios
    LANGFLOW_AUTO_LOGIN="false";
    LANGFLOW_ENABLE_SIGNUP="false";
    LANGFLOW_NEW_USER_IS_ACTIVE="false";
    # - Segredo, gerar com comando:
    #   python3 -c "import secrets; print(secrets.token_urlsafe(32))"
    LANGFLOW_SECRET_KEY="lCHWWiQr__7IyKCBsMaZpiekDOQgXULjvDIyf7H6tk0";
    LANGFLOW_HOSTNAME="$FQDN";
    LANGFLOW_HOST="0.0.0.0";
    LANGFLOW_PORT="7860";
    LANGFLOW_CONFIG_DIR="/app/langflow";

# Imagem:
    IMAGE="langflowai/langflow:latest";
    docker pull $IMAGE;

# Pasta de persistencia das configuracoes
    DATADIR=/storage/langflow;
    mkdir  -p $DATADIR;

# Renovar/rodar
    docker rm -f $NAME 2>/dev/null
    docker pull $IMAGE;
    docker run \
        -d --restart=always \
        --name $NAME \
        -h $LOCAL \
        \
        --network network_public \
        \
        -p 7860:7860 \
        \
        -v $DATADIR:/app/langflow \
        \
        -e "LANGFLOW_DATABASE_URL=$LANGFLOW_DATABASE_URL" \
        -e "LANGFLOW_AUTO_LOGIN=$LANGFLOW_AUTO_LOGIN" \
        -e "LANGFLOW_SUPERUSER=$LANGFLOW_SUPERUSER" \
        -e "LANGFLOW_SUPERUSER_PASSWORD=$LANGFLOW_SUPERUSER_PASSWORD" \
        -e "LANGFLOW_SECRET_KEY=$LANGFLOW_SECRET_KEY" \
        -e "LANGFLOW_HOSTNAME=$FQDN" \
        -e "LANGFLOW_HOST=$LANGFLOW_HOST" \
        -e "LANGFLOW_PORT=$LANGFLOW_PORT" \
        -e "LANGFLOW_CONFIG_DIR=$LANGFLOW_CONFIG_DIR" \
        -e "LANGFLOW_ENABLE_SIGNUP=$LANGFLOW_ENABLE_SIGNUP" \
        -e "LANGFLOW_NEW_USER_IS_ACTIVE=$LANGFLOW_NEW_USER_IS_ACTIVE" \
        \
        --label "traefik.enable=true" \
        --label "traefik.http.routers.$NAME.rule=Host(\`$FQDN\`)" \
        --label "traefik.http.routers.$NAME.entrypoints=websecure" \
        --label "traefik.http.routers.$NAME.tls=true" \
        --label "traefik.http.routers.$NAME.tls.certresolver=letsencrypt" \
        --label "traefik.http.services.$NAME.loadbalancer.server.port=7860" \
        \
        $IMAGE;

    # URLs de acesso:
    echo;
    echo "Url de acesso:";
    echo "    https://$FQDN";
    echo "    https://$FQDN/login";
    echo;

4 – Stack

Para quem prefere a stack para usar no “docker compose” ou via Portainer, eis o YAML:

docker-compose.yml
services:
  langflow-db:
    image: pgvector/pgvector:pg18-trixie
    container_name: langflow-db
    hostname: langflow-db
    restart: always
    environment:
      POSTGRES_USER: langflow
      POSTGRES_PASSWORD: tulipasql
      POSTGRES_DB: langflow
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - langflow_db_data:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U langflow"]
      interval: 5s
      timeout: 5s
      retries: 10
    command:
      - postgres
      - --max_connections=8192
      - --wal_level=minimal
      - --max_wal_senders=0
      - --port=5432
    networks:
      - network_public

  langflow-app:
    image: langflowai/langflow:latest
    container_name: langflow
    hostname: langflow
    restart: always
    depends_on:
      langflow-db:
        condition: service_healthy
    environment:
      LANGFLOW_DATABASE_URL: postgresql://langflow:tulipasql@langflow-db:5432/langflow
      LANGFLOW_HOST: 0.0.0.0
      LANGFLOW_PORT: 7860
      LANGFLOW_AUTO_LOGIN: "false"
      LANGFLOW_ENABLE_SIGNUP: "false"
      LANGFLOW_NEW_USER_IS_ACTIVE: "false"
      LANGFLOW_SUPERUSER: admin
      LANGFLOW_SUPERUSER_PASSWORD: tulipa
      # Gere com: python3 -c "import secrets; print(secrets.token_urlsafe(32))"
      LANGFLOW_SECRET_KEY: "COLOQUE_UMA_CHAVE_SECRETA_AQUI"
      LANGFLOW_CONFIG_DIR: /app/langflow
    volumes:
      - langflow_data:/app/langflow
    ports:
      - "7860:7860"
    networks:
      - network_public
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.langflow.rule=Host(`langflow.seudominio.com.br`)"
      - "traefik.http.routers.langflow.entrypoints=websecure"
      - "traefik.http.routers.langflow.tls=true"
      - "traefik.http.routers.langflow.tls.certresolver=letsencrypt"
      - "traefik.http.services.langflow.loadbalancer.server.port=7860"

networks:
  network_public:
    external: true

volumes:
  langflow_db_data:
  langflow_data:

Agora basta acessa a interface pelo navegador e começar a explorar a solução!

Terminamos por hoje!

Patrick Brandão, patrickbrandao@gmail.com

Vamos agradecer aos idiotas.
Não fosse por eles não faríamos tanto sucesso.
Mark Twain