Skip to content

TutorialsAI & LLM

How to install Langflow with Docker Compose and PostgreSQL

Self-host Langflow with Docker Compose and PostgreSQL on Ubuntu or Debian: superuser login, a fixed secret key, HTTPS through Caddy, backups and safe updates.

  • Intermediate
  • 35 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Create the project folder and secrets
  3. Step 2 — Write the Compose file
  4. Step 3 — Start Langflow and check it
  5. Step 4 — Publish Langflow over HTTPS with Caddy
  6. Step 5 — Sign in and manage users
  7. Step 6 — Connect Ollama on the same server
  8. Step 7 — Keep code execution under control
  9. Back up and restore
  10. Update Langflow
  11. Troubleshooting
  12. Langflow exits at startup with a superuser password error
  13. New users cannot sign in
  14. password authentication failed for user langflow
  15. The Ollama component cannot connect
  16. Caddy answers 403 Forbidden
  17. Next steps

Langflow is a visual builder for AI agents and LLM workflows. You drag components for models, prompts, vector stores, tools and agents onto a canvas, test the flow in a playground, and serve it as an API endpoint or an MCP server. Under the hood every component is Python code you can open and change, which makes Langflow flexible and also means it must be run carefully.

This guide deploys the official langflowai/langflow image with a PostgreSQL database, following the project's Docker Compose example. You pin the image version, turn off auto-login with a superuser and your own secret key, keep every port on localhost, publish Langflow over HTTPS with Caddy, connect a local Ollama server and learn how to back up and update the stack.

Prerequisites

Langflow's installation page lists these requirements for the Python package; the Docker page publishes none of its own, so the same figures are a sensible floor:

ResourceMinimum (official)Suggested starting point
CPUDual-coreMulti-core (4 vCPU)
RAM2 GBAt least 4 GB (official recommendation)
DiskNot published20 GB for images, database and files

Step 1 — Create the project folder and secrets

Bash
sudo apt update
sudo apt install python3 openssl
sudo mkdir -p /opt/langflow
sudo chown $USER:$USER /opt/langflow
cd /opt/langflow

Write the settings Compose needs into .env. The secret key encrypts stored credentials such as API keys; Langflow can generate one on its own, but the documentation recommends setting your own in production and shows the Python command used here.

Bash
cat > .env <<EOF
LANGFLOW_VERSION=1.12.5
POSTGRES_PASSWORD=$(openssl rand -hex 24)
LANGFLOW_SUPERUSER=admin
LANGFLOW_SUPERUSER_PASSWORD=$(openssl rand -base64 24)
LANGFLOW_SECRET_KEY=$(python3 -c "from secrets import token_urlsafe; print(token_urlsafe(32))")
EOF
chmod 600 .env
grep SUPERUSER .env

Note the superuser name and password from the last command. LANGFLOW_VERSION pins the image; check the Langflow tags on Docker Hub for the newest stable number and avoid tags containing dev.

Step 2 — Write the Compose file

Create /opt/langflow/compose.yaml. It is based on the official docker_example/docker-compose.yml, with three changes: the database port is not published at all, Langflow is published on localhost only, and the authentication settings from Langflow's recommended secure configuration are added.

YAML
services:
  langflow:
    image: langflowai/langflow:${LANGFLOW_VERSION}
    restart: unless-stopped
    depends_on:
      - postgres
    ports:
      - "127.0.0.1:7860:7860"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    environment:
      - LANGFLOW_DATABASE_URL=postgresql://langflow:${POSTGRES_PASSWORD}@postgres:5432/langflow
      - LANGFLOW_CONFIG_DIR=/app/langflow
      - LANGFLOW_AUTO_LOGIN=False
      - LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER}
      - LANGFLOW_SUPERUSER_PASSWORD=${LANGFLOW_SUPERUSER_PASSWORD}
      - LANGFLOW_SECRET_KEY=${LANGFLOW_SECRET_KEY}
      - LANGFLOW_NEW_USER_IS_ACTIVE=False
      - LANGFLOW_ENABLE_SIGNUP=False
      - LANGFLOW_ENABLE_SUPERUSER_CLI=False
      - DO_NOT_TRACK=true
    volumes:
      - langflow-data:/app/langflow
  postgres:
    image: postgres:16-trixie
    restart: unless-stopped
    environment:
      POSTGRES_USER: langflow
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: langflow
    volumes:
      - langflow-postgres:/var/lib/postgresql/data
volumes:
  langflow-postgres:
  langflow-data:

The settings in brief:

  • LANGFLOW_CONFIG_DIR=/app/langflow is where Langflow keeps logs, file storage and monitoring data; the langflow-data volume keeps it across updates.
  • LANGFLOW_AUTO_LOGIN=False with a superuser password forces everyone to sign in. New accounts start inactive until a superuser activates them, self sign-up is off, and LANGFLOW_ENABLE_SUPERUSER_CLI=False stops the CLI from creating additional superusers.
  • postgres:16-trixie is the tag the official example pins, so the PostgreSQL base system does not change underneath an existing volume and cause collation warnings.
  • DO_NOT_TRACK=true opts out of Langflow's telemetry.

Step 3 — Start Langflow and check it

Bash
docker compose up -d
docker compose ps
docker compose logs --tail 50 langflow
curl -I http://127.0.0.1:7860

The first start creates the database schema and takes a minute or two. Both services should show as running, the langflow line should list 127.0.0.1:7860->7860/tcp, and curl should return HTTP/1.1 200 OK. If Langflow exits immediately, the logs usually name a missing or rejected superuser password.

Step 4 — Publish Langflow over HTTPS with Caddy

Add a site block to /etc/caddy/Caddyfile. Langflow can run arbitrary code, so the example restricts access to your own IP address; replace 198.51.100.24 with it, or delete the two matcher lines if you need public flow endpoints:

Caddyfile
langflow.example.com {
    @outside not remote_ip 198.51.100.24
    respond @outside 403
    reverse_proxy 127.0.0.1:7860
}
Bash
sudo systemctl reload caddy
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
curl -I https://langflow.example.com

Langflow's Nginx example enables WebSocket upgrades, long read timeouts and unbuffered responses for streaming. Caddy needs none of that configured: it proxies WebSockets automatically, applies no read timeout by default and flushes streamed responses immediately. If you prefer Nginx, copy those settings from the official example or the Nginx with Certbot guide; Traefik is another option.

Step 5 — Sign in and manage users

Open https://langflow.example.com and sign in with the superuser from Step 1, and keep its generated password in a password manager. Then create accounts for colleagues in the Admin Page. Because LANGFLOW_NEW_USER_IS_ACTIVE=False, every new account stays inactive until you activate it there.

To call a flow from another application, create a Langflow API key in your account settings and send it with each request. Keys belong to a user, so delete them when that user leaves.

Step 6 — Connect Ollama on the same server

The container reaches the host through host.docker.internal, but Ollama listens on 127.0.0.1 after a standard installation. Make it listen on all addresses with a systemd drop-in, as the Ollama FAQ describes, and allow only the Langflow network through ufw:

Bash
sudo mkdir -p /etc/systemd/system/ollama.service.d
sudo tee /etc/systemd/system/ollama.service.d/override.conf <<'EOF'
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
EOF
sudo systemctl daemon-reload
sudo systemctl restart ollama
docker network inspect langflow_default | grep Subnet
sudo ufw allow from 172.18.0.0/16 to any port 11434 proto tcp

Replace 172.18.0.0/16 with the subnet the inspect command prints. This rule only protects Ollama while ufw is active with its default deny policy, so confirm that sudo ufw status verbose shows Status: active and deny (incoming), and that nc -vz your-server-ip 11434 from another machine fails. Ollama has no authentication, so never open port 11434 to everyone. In a flow, add the Ollama model component, set its base URL to http://host.docker.internal:11434 and choose a model you pulled with ollama pull. Larger models are far more responsive on a GPU server.

Step 7 — Keep code execution under control

Langflow's security documentation is explicit about the risks: the component code editor lets users author and run arbitrary Python with full access to the backend process, Langflow does not isolate users within one process, and authentication and authorization should be enforced outside the container.

Practical measures for a single server:

  • Keep the Caddy IP allowlist from Step 4, or reach Langflow only through a VPN such as WireGuard.
  • If your users only need the built-in components, add LANGFLOW_ALLOW_CUSTOM_COMPONENTS=False to the environment list. The documentation says this disables custom components and in-editor editing of component code.
  • Use separate model API keys with spending limits for Langflow, and rotate them when people leave.
  • Run one Langflow instance per team that needs isolation, instead of sharing a single instance between groups that must not see each other's data.

Back up and restore

State lives in two named volumes: langflow_langflow-postgres holds the database with flows, users and encrypted credentials, and langflow_langflow-data holds logs and uploaded files. Without .env you cannot decrypt the stored credentials, so back it up too.

Bash
sudo mkdir -p /opt/backups
sudo chown $USER:$USER /opt/backups
cd /opt/langflow
docker compose exec -T postgres pg_dump -U langflow langflow | gzip > /opt/backups/langflow-db-$(date +%F).sql.gz
docker compose stop langflow
docker run --rm -v langflow_langflow-data:/data -v /opt/backups:/backup ubuntu tar czf /backup/langflow-data-$(date +%F).tar.gz -C /data .
docker compose start langflow
sudo tar czf /opt/backups/langflow-config-$(date +%F).tar.gz -C /opt langflow

To restore on a new server, unpack the config archive to /opt, create the containers and volumes without starting Langflow, load the database and the files, then start everything:

Bash
sudo tar xzf /opt/backups/langflow-config-2026-10-09.tar.gz -C /opt
cd /opt/langflow
docker compose create
docker compose start postgres
gunzip -c /opt/backups/langflow-db-2026-10-09.sql.gz | docker compose exec -T postgres psql -U langflow langflow
docker run --rm -v langflow_langflow-data:/data -v /opt/backups:/backup ubuntu tar xzf /backup/langflow-data-2026-10-09.tar.gz -C /data
docker compose up -d

Give PostgreSQL a few seconds after start before you load the dump. Copy all three archives off the server.

Update Langflow

The documented upgrade path is to change the image tag, pull the new image and restart with the same volumes. Read the release notes and take a backup first, because database migrations run on startup and cannot be undone by switching the tag back.

Bash
cd /opt/langflow
nano .env
docker compose pull
docker compose up -d
docker compose logs --tail 50 langflow

In nano, set LANGFLOW_VERSION to the new stable tag. Keep the postgres:16-trixie image unless the release notes tell you otherwise; a new PostgreSQL major version needs a dump and restore, not just a new tag.

Troubleshooting

Langflow exits at startup with a superuser password error

LANGFLOW_SUPERUSER_PASSWORD is empty, was not passed to the container, or is the legacy default langflow. Check .env, run docker compose config | grep SUPERUSER to see what Compose passes, and start again.

New users cannot sign in

They are inactive, because LANGFLOW_NEW_USER_IS_ACTIVE=False. Activate them in the Admin Page as a superuser.

password authentication failed for user langflow

POSTGRES_PASSWORD changed after the database volume was created. PostgreSQL keeps the original password. Put the old value back in .env, or change it inside PostgreSQL with ALTER USER before updating .env.

The Ollama component cannot connect

Ollama still listens on 127.0.0.1, or ufw blocks the Docker subnet. Check ss -tln | grep 11434 and sudo ufw status, and make sure the base URL uses host.docker.internal, not localhost.

Caddy answers 403 Forbidden

Your current public IP address differs from the one in the remote_ip line. Update it and run sudo systemctl reload caddy.

Next steps

Frequently asked questions

Why does Langflow refuse to start without a superuser password?

When LANGFLOW_AUTO_LOGIN is False, Langflow requires LANGFLOW_SUPERUSER_PASSWORD and fails closed if it is missing or set to the old default langflow. The official Docker images already turn auto-login off, so you must provide a password.

Is it safe to put Langflow on the public internet?

Treat it as a private tool. Flows and custom components run Python code with full access to the Langflow backend, and the documentation says Langflow does not isolate users within one process. Give accounts only to trusted people and consider an IP allowlist or VPN.

Which Langflow version does this guide install?

The image tag is pinned in .env. When this guide was checked, 1.12.5 was the latest stable tag on Docker Hub; tags containing dev are development builds and not meant for production.

How do I connect Langflow to Ollama on the same server?

Make Ollama listen on 0.0.0.0 with OLLAMA_HOST, allow only the Compose subnet to port 11434 in ufw, and set the base URL of the Ollama component to http://host.docker.internal:11434.

Sources

Parooli genereerimine

Please confirm