Deployment Guide
Browser traffic is always nginx → backend-go (REST/SSE + auth). The Python worker only serves POST /internal/runtasks and is not meant to be exposed to browsers.
Local all-in-one development
Start
make dev| Service | Port | Role |
|---|---|---|
| backend-go | 18080 | Go control plane (public API) |
| worker | 8001 | Python RunTask (internal) |
| Frontend | 3000 | Next.js |
| nginx | 2026 | Single entrypoint |
Open http://localhost:2026 .
Docker development stack
Containers: frontend, worker, nginx, and optionally provisioner (from config.yaml sandbox mode). backend-go runs on the host (host.docker.internal:18080).
Prerequisites
- Docker
config.yamlat repo rootDEER_FLOW_WORKER_SECRETin.env(openssl rand -hex 32). Host backend-go needs the same DB/Redis setup as full local dev (backend-go/README.md).
Start
export DEER_FLOW_ROOT=/absolute/path/to/deer-flow # required for provisioner mode
make docker-start
# In another terminal: start backend-go from repo (e.g. `make run` under backend-go)Equivalent: docker compose -p deer-flow-dev -f docker/docker-compose-dev.yaml up --build from docker/ (keep -p and DEER_FLOW_ROOT as needed).
Open http://localhost:2026 . Stop with make docker-stop.
Docker production
Uses docker/docker-compose.yaml at repo root. Recommended:
./scripts/deploy.sh # build + start detached
# ./scripts/deploy.sh build
# ./scripts/deploy.sh start
# ./scripts/deploy.sh downOr make up / make down. deploy.sh persists BETTER_AUTH_SECRET, DEER_FLOW_WORKER_SECRET, and AUTH_JWT_SECRET under backend/.deer-flow/ when env vars are unset.
Environment variables
Root .env (loaded via env_file in compose). Typical keys:
OPENAI_API_KEY=sk-...
DEER_FLOW_ROOT=/absolute/path/to/deer-flow
BETTER_AUTH_SECRET=your-secret-min-32-chars
BETTER_AUTH_URL=https://your-domain.com
AUTH_JWT_SECRET=... # required if not using deploy.sh secret files
DEER_FLOW_WORKER_SECRET=...Always set a strong BETTER_AUTH_SECRET in production. Do not rely on frontend build defaults.
Data persistence
Runtime state lives under DEER_FLOW_HOME (default backend/.deer-flow). Use named volumes or PVCs in production.
Production topics
Sandbox selection
| Sandbox | Use case |
|---|---|
LocalSandboxProvider | Single user, trusted host |
AioSandboxProvider (Docker) | Multi-user, container isolation |
AioSandboxProvider + K8s provisioner | Strong isolation, multi-user |
Kubernetes provisioner
Environment
K8S_NAMESPACE=deer-flow
SANDBOX_IMAGE=deerflow-arduino-sandbox:latest
# or a registry all-in-one image
DEER_FLOW_ROOT=/absolute/path/to/deer-flowconfig.yaml
sandbox:
use: deerflow.community.aio_sandbox:AioSandboxProvider
provisioner_url: http://provisioner:8002PVCs (optional)
USERDATA_PVC_NAME=deer-flow-userdata-pvc
SKILLS_PVC_NAME=deer-flow-skills-pvcWith USERDATA_PVC_NAME, the provisioner uses subPath threads/{thread_id}/user-data per thread.
nginx
Routing is in docker/nginx/nginx.conf: only frontend and backend-go are browser-facing; the worker is not proxied for /api.
Authentication (Better Auth)
BETTER_AUTH_SECRET: strong random, ≥32 charsBETTER_AUTH_URL: public origin
openssl rand -base64 32Resource hints
| Component | Minimum | Recommended |
|---|---|---|
| backend-go | 1 vCPU, 512 MB | 2 vCPU, 1 GB |
| worker (agent) | 2 vCPU, 4 GB RAM | 4 vCPU, 8 GB RAM |
| Frontend | 0.5 vCPU, 512 MB | 1 vCPU, 1 GB |
| Sandbox (per session) | 1 vCPU, 1 GB | 2 vCPU, 2 GB |
Verification
curl -sf http://localhost:2026/health
curl -sf http://localhost:2026/api/modelsLocal-only: curl -sf http://localhost:8001/health (worker).