{"slug": "deploying-langflow-an-open-source-visual-framework-for-building-ai-applications", "title": "Deploying Langflow: An Open-Source Visual Framework for Building AI Applications", "summary": "A developer published a step-by-step guide for self-hosting Langflow, an open-source low-code visual framework for building AI agents, workflows, and RAG applications, on a Linux server using Docker Compose. The deployment covers PostgreSQL persistence, Traefik reverse proxying with automatic HTTPS, editor authentication, and validation through a RAG chatbot that answers questions from an uploaded document. The guide notes that Langflow flows can run as API endpoints or Model Context Protocol servers without extra boilerplate code.", "body_md": "[Langflow](https://github.com/langflow-ai/langflow) is an open-source, low-code visual framework for building artificial intelligence (AI) agents, workflows, and retrieval-augmented generation (RAG) applications. Developers use its visual builder to assemble large language model (LLM) pipelines from prebuilt components and test them in an interactive Playground, and finished flows run as API endpoints or Model Context Protocol (MCP) servers without extra boilerplate code. This guide walks through self-hosting a production-ready Langflow instance on a Linux server with Docker Compose, covering PostgreSQL persistence, Traefik reverse proxying with automatic HTTPS certificates, authentication for the visual editor, and validation of the deployment through a RAG chatbot that answers questions from an uploaded document. By the end, you'll have a secured Langflow deployment running behind HTTPS with a working RAG chatbot proving that ingestion, retrieval, and generation all work end to end.\n\nBefore you begin, you need a Linux-based server with at least 2 CPU cores and 4 GB of RAM as a non-root user with sudo privileges, Docker and Docker Compose installed, a domain A record pointing to the server's public IP address (for example, `langflow.example.com`), and an API key from a supported LLM provider — this deployment uses OpenAI models for embeddings and chat responses.\n\nLangflow reads its runtime configuration from environment variables, so a dedicated project directory with a `.env` file keeps credentials out of the Compose manifest.\n\n**1. Create the project directory and switch into it:**\n\n``` bash\n$ mkdir ~/langflow && cd ~/langflow\n```\n\n**2. Generate a Langflow secret key and write it to the environment file:**\n\n``` python\n$ python3 -c \"from secrets import token_urlsafe; print(f'LANGFLOW_SECRET_KEY={token_urlsafe(32)}')\" >> .env\n```\n\nLangflow encrypts stored credentials with this Fernet key. Without an explicit key, Langflow generates a random one at startup and encrypted values become unreadable after a restart.\n\n**3. Verify that the file contains the key without displaying its value:**\n\n``` bash\n$ grep -c \"LANGFLOW_SECRET_KEY\" .env\n```\n\nOutput:\n\n```\n1\n```\n\n**4. Open the `.env` file with a text editor such as `nano`:**\n\n``` bash\n$ nano .env\n```\n\n**5. Add the following variables below the existing `LANGFLOW_SECRET_KEY` line, replacing every placeholder with your own values:**\n\n```\n# Domain and certificate settings\nLANGFLOW_HOSTNAME=langflow.example.com\nLETSENCRYPT_EMAIL=admin@example.com\n\n# PostgreSQL credentials\nPOSTGRES_USER=langflow\nPOSTGRES_PASSWORD=DATABASE_PASSWORD\nPOSTGRES_DB=langflow\n\n# Langflow storage paths\nLANGFLOW_CONFIG_DIR=/app/langflow\nLANGFLOW_KNOWLEDGE_BASES_DIR=/app/langflow/knowledge_bases\n\n# Authentication settings\nLANGFLOW_AUTO_LOGIN=False\nLANGFLOW_SUPERUSER=administrator\nLANGFLOW_SUPERUSER_PASSWORD=ADMIN_PASSWORD\nLANGFLOW_NEW_USER_IS_ACTIVE=False\nLANGFLOW_ENABLE_SUPERUSER_CLI=False\n\n# LLM provider credentials\nOPENAI_API_KEY=OPENAI_API_KEY\n```\n\n`LANGFLOW_HOSTNAME` and `LETSENCRYPT_EMAIL` supply the domain for the Traefik routing rule and the contact address for certificate expiry notices. The `POSTGRES_*` variables initialize the database container on first boot and are reused in the Langflow connection string — use only letters and numbers in the password, because symbols require %-encoding and `$` conflicts with Compose interpolation. `LANGFLOW_CONFIG_DIR` and `LANGFLOW_KNOWLEDGE_BASES_DIR` place application data and knowledge base vectors on the same volume-mapped path; without the second variable, Langflow writes knowledge bases outside that volume and a container replacement deletes your vector data. `LANGFLOW_AUTO_LOGIN=False` disables anonymous access, `LANGFLOW_SUPERUSER`/` LANGFLOW_SUPERUSER_PASSWORD` define the administrator account Langflow creates at startup, `LANGFLOW_NEW_USER_IS_ACTIVE=False` keeps new accounts inactive until approved, and `LANGFLOW_ENABLE_SUPERUSER_CLI=False` blocks superuser creation from the command line. `OPENAI_API_KEY` supplies the LLM provider credential, which Langflow stores as an encrypted global variable.\n\n**6. Restrict the environment file so only its owner can read or modify it:**\n\n``` bash\n$ chmod 600 .env\n```\n\nThe stack runs three services. Traefik terminates HTTPS, Langflow serves the application on internal port `7860`, and PostgreSQL stores flows, users, and settings. Langflow joins the `proxy` network with Traefik and the `internal` network with PostgreSQL, so the database stays unreachable from outside.\n\n**1. Create the `docker-compose.yml` file in the project directory:**\n\n``` bash\n$ nano docker-compose.yml\n```\n\n**2. Add the following service definitions to the file:**\n\n```\nservices:\n  traefik:\n    image: traefik:v3.7\n    restart: unless-stopped\n    command:\n      - --providers.docker=true\n      - --providers.docker.exposedbydefault=false\n      - --providers.docker.network=proxy\n      - --entryPoints.web.address=:80\n      - --entryPoints.websecure.address=:443\n      - --entryPoints.websecure.http.tls=true\n      - --entryPoints.web.http.redirections.entryPoint.to=websecure\n      - --entryPoints.web.http.redirections.entryPoint.scheme=https\n      - --certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}\n      - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json\n      - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock:ro\n      - ./letsencrypt:/letsencrypt\n    networks:\n      - proxy\n\n  langflow:\n    image: langflowai/langflow:1.11.3\n    restart: unless-stopped\n    depends_on:\n      postgres:\n        condition: service_healthy\n    environment:\n      - LANGFLOW_DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}\n      - LANGFLOW_CONFIG_DIR=${LANGFLOW_CONFIG_DIR}\n      - LANGFLOW_KNOWLEDGE_BASES_DIR=${LANGFLOW_KNOWLEDGE_BASES_DIR}\n      - LANGFLOW_AUTO_LOGIN=${LANGFLOW_AUTO_LOGIN}\n      - LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER}\n      - LANGFLOW_SUPERUSER_PASSWORD=${LANGFLOW_SUPERUSER_PASSWORD}\n      - LANGFLOW_SECRET_KEY=${LANGFLOW_SECRET_KEY}\n      - LANGFLOW_NEW_USER_IS_ACTIVE=${LANGFLOW_NEW_USER_IS_ACTIVE}\n      - LANGFLOW_ENABLE_SUPERUSER_CLI=${LANGFLOW_ENABLE_SUPERUSER_CLI}\n      - OPENAI_API_KEY=${OPENAI_API_KEY}\n    volumes:\n      - langflow-data:/app/langflow\n    networks:\n      - proxy\n      - internal\n    labels:\n      - traefik.enable=true\n      - traefik.http.routers.langflow.rule=Host(`${LANGFLOW_HOSTNAME}`)\n      - traefik.http.routers.langflow.entrypoints=websecure\n      - traefik.http.routers.langflow.tls.certresolver=le\n      - traefik.http.services.langflow.loadbalancer.server.port=7860\n\n  postgres:\n    image: postgres:16-trixie\n    restart: unless-stopped\n    environment:\n      - POSTGRES_USER=${POSTGRES_USER}\n      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\n      - POSTGRES_DB=${POSTGRES_DB}\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}\"]\n      interval: 5s\n      timeout: 5s\n      retries: 10\n    volumes:\n      - langflow-postgres:/var/lib/postgresql/data\n    networks:\n      - internal\nnetworks:\n  proxy:\n    name: proxy\n  internal:\n\nvolumes:\n  langflow-data:\n  langflow-postgres:\n```\n\nThe `traefik` service publishes ports `80` and `443`, discovers only explicitly labeled containers through the read-only Docker socket, and registers a certificate resolver named `le` that completes the ACME challenge on port `80` and redirects plain HTTP to HTTPS. The `langflow` service pins the `langflowai/langflow:1.11.3` image; the Traefik labels route your domain to port `7860` inside the container, and the `langflow-data` volume persists `LANGFLOW_CONFIG_DIR` across restarts. The `postgres` service pins `postgres:16-trixie`, joins only the `internal` network, and its `pg_isready` health check gates the Langflow start.\n\n**3. Start the stack in detached mode:**\n\n``` bash\n$ docker compose up -d\n```\n\n**4. Verify that all containers are running:**\n\n``` bash\n$ docker compose ps\n```\n\nThe output displays three running containers, with Traefik listening on ports 80 and 443 and PostgreSQL reporting a healthy status.\n\n**5. Check the Langflow logs to verify that the application started:**\n\n``` bash\n$ docker compose logs -f langflow\n```\n\nThe first start takes a few minutes because Langflow runs its database migrations against PostgreSQL. The log stream ends with a startup banner when the application is ready.\n\n```\nOpen Langflow → http://localhost:7860\n```\n\nPress Ctrl+C to stop following the logs. The `localhost` address applies inside the container only, and Traefik forwards your domain traffic to the same listener.\n\nThe stack now runs behind HTTPS, so the remaining configuration happens in the browser.\n\n`https://langflow.example.com`. Traefik requests a Let's Encrypt certificate after the stack starts — if the browser shows a certificate warning, wait a minute and reload. Because automatic login is off, Langflow redirects you to the `/login` page.`LANGFLOW_SUPERUSER` and `LANGFLOW_SUPERUSER_PASSWORD`. The Langflow `OPENAI_API_KEY` variable at startup. Enable the models you plan to use under A RAG chatbot answers questions from your own documents instead of relying only on the model's training data. Langflow ships a **Vector Store RAG** template that pairs a retrieval flow with a knowledge base, which chunks a document, embeds it, and stores the vectors locally. A grounded answer in the Playground proves that ingestion, retrieval, and generation all work on the deployed stack.\n\n`langflow_demo`, select an OpenAI embedding model, and keep `{question}` variable. `{context}`. For the full guide with additional tips, visit the original article on **[Vultr Docs](https://docs.vultr.com/how-to-deploy-langflow-open-source-visual-framework-for-building-ai-applications)**.", "url": "https://wpnews.pro/news/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications", "canonical_source": "https://dev.to/vultr/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications-19ol", "published_at": "2026-09-23 19:16:50+00:00", "updated_at": "2026-09-23 19:29:03.812300+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "large-language-models", "ai-infrastructure"], "entities": ["Langflow", "Docker Compose", "PostgreSQL", "Traefik", "OpenAI", "Model Context Protocol", "Linux"], "alternates": {"html": "https://wpnews.pro/news/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications", "markdown": "https://wpnews.pro/news/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications.md", "text": "https://wpnews.pro/news/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications.txt", "jsonld": "https://wpnews.pro/news/deploying-langflow-an-open-source-visual-framework-for-building-ai-applications.jsonld"}}