Skip to Content
DeerFlow

Deployment Guide

This guide covers all supported deployment methods for DeerFlow App: local development, Docker Compose, and production with Kubernetes-managed sandboxes.

Local development deployment

The local workflow is the fastest way to run DeerFlow. All services run as native processes on your machine.

make dev

Services started:

ServicePortDescription
Gateway API8001FastAPI backend + embedded agent runtime
Frontend3000Next.js UI
nginx2026Unified reverse proxy

Access the app at http://localhost:2026 .

Docker Compose deployment

Docker Compose runs all services in containers. Use this for a more production-like local setup or for team environments.

Prerequisites

  • Docker (or Docker Desktop / OrbStack on macOS)
  • A configured config.yaml at the repo root

Development compose

# Set the absolute path to your deer-flow repo root export DEER_FLOW_ROOT=/path/to/deer-flow docker compose -f docker/docker-compose-dev.yaml up --build

Services: nginx, frontend, gateway, and optionally provisioner (for K8s-managed sandboxes).

Access the app at http://localhost:2026 .

Environment variables

Create a .env file in the repo root for secrets and runtime configuration:

# .env OPENAI_API_KEY=sk-... DEER_FLOW_ROOT=/absolute/path/to/deer-flow BETTER_AUTH_SECRET=your-secret-here-min-32-chars

The docker-compose*.yaml files include an env_file: ../.env directive that loads this automatically.

Always set BETTER_AUTH_SECRET to a strong random string before deploying. Without it, the frontend build uses a default that is publicly known.

Data persistence

Thread data is stored in backend/.deer-flow/threads/. In Docker deployments, this directory is bind-mounted into the gateway container.

To avoid data loss when containers are recreated:

  1. Set DEER_FLOW_ROOT to the absolute repo root path (or a stable host path).
  2. Verify the threads/ and skills/ directories are mounted correctly.

For production, use a named volume or a Persistent Volume Claim (PVC) instead of a host bind-mount.

Production deployment considerations

Sandbox mode selection

SandboxUse case
LocalSandboxProviderSingle-user, trusted local workflows
AioSandboxProvider (Docker)Multi-user, moderate isolation requirement
E2BSandboxProvider (e2b cloud)Hosted/serverless, no Docker/K8s ops, instant Jupyter
AioSandboxProvider + K8s ProvisionerProduction, strong isolation, multi-user

For any deployment with more than one concurrent user, use a container-based sandbox to prevent users from interfering with each other’s execution environments.

Database backend

SQLite is convenient for local development and single-user deployments, but it is not a production backend for concurrent users.

In SQLite mode, DeerFlow stores LangGraph checkpoint data and application data in one deerflow.db file. WAL mode allows concurrent reads, but SQLite still permits only one writer at a time. When several users run agents at once, checkpoint writes and application writes can contend for the same file and raise sqlite3.OperationalError: database is locked.

For production or any multi-user deployment, use Postgres:

# .env DATABASE_URL=postgresql://user:password@postgres:5432/deerflow UV_EXTRAS=postgres
# config.yaml database: backend: postgres postgres_url: $DATABASE_URL run_events: backend: db

Keep SQLite deployments to local, single-node, or short-lived evaluation environments.

K8s Provisioner setup

The provisioner manages sandbox Pods in a Kubernetes cluster. It is included in docker/docker-compose-dev.yaml.

Configure the provisioner

Set required environment variables in your .env or compose override:

K8S_NAMESPACE=deer-flow SANDBOX_IMAGE=enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest DEER_FLOW_ROOT=/absolute/path/to/deer-flow

Configure the sandbox provider

# config.yaml sandbox: use: deerflow.community.aio_sandbox:AioSandboxProvider provisioner_url: http://provisioner:8002

Configure data persistence

For production, use PVCs instead of hostPath volumes:

# In .env or compose environment USERDATA_PVC_NAME=deer-flow-userdata-pvc SKILLS_PVC_NAME=deer-flow-skills-pvc

When USERDATA_PVC_NAME is set, the provisioner automatically uses subPath (threads/{thread_id}/user-data) so each thread gets its own directory in the PVC.

nginx configuration

nginx routes all traffic to the frontend or Gateway. /api/langgraph/* is rewritten to Gateway’s LangGraph-compatible /api/* routes, so no separate LangGraph upstream is required.

Authentication

DeerFlow App uses Better Auth  for session management. In production:

  1. Set BETTER_AUTH_SECRET to a strong random string (minimum 32 characters).
  2. Set BETTER_AUTH_URL to your public-facing URL (e.g., https://your-domain.com).
# Generate a secret openssl rand -base64 32

Resource recommendations

ServiceMinimumRecommended
Gateway + agent runtime2 vCPU, 4 GB RAM4 vCPU, 8 GB RAM
Frontend0.5 vCPU, 512 MB1 vCPU, 1 GB
Sandbox container (per session)1 vCPU, 1 GB2 vCPU, 2 GB

Deployment verification

After starting, verify the deployment:

# Check Gateway health curl http://localhost:8001/health # List configured models (through nginx) curl http://localhost:2026/api/models

A working deployment returns a 200 response from each endpoint. The /api/models call returns the list of models from your config.yaml.

Last updated on