deployment
workflowdev
Deployment
Two deployment paths: Docker Compose for local development, Helm chart for Kubernetes.
Docker Compose
The simplest way to run everything locally.
git clone https://github.com/excalibase/excalibase-workflow.git
cd excalibase-workflow
cp .env.example .env
docker compose up -d --build
Services
| Service | Image | Port |
|---|---|---|
| postgres | pgvector/pgvector:pg16 | 5434 |
| nats | nats:2-alpine | 4222 |
| dind | docker:24-dind | 2375 |
| backend | excalibase-workflow-backend | 8080 |
| worker | excalibase-workflow-worker | — |
| frontend | excalibase-workflow-frontend | 3000 |
Scale workers
docker compose up -d --scale worker=3
Reset everything
docker compose down -v
docker compose up -d --build
Kubernetes (Helm)
For production environments. The Helm chart deploys all services with proper health checks, RBAC, and auto-scaling.
Prerequisites
- Kubernetes cluster (minikube, EKS, GKE, AKS, etc.)
- Helm 3
- kubectl
Install
helm install excalibase ./helm/excalibase-workflow \
--namespace excalibase --create-namespace
Configure
Create a values-override.yaml:
backend:
replicas: 2
env:
OPENAI_API_KEY: "sk-..."
ANTHROPIC_API_KEY: "sk-ant-..."
worker:
replicas: 3
postgres:
password: "strong-password-here"
storage:
size: 10Gi
ingress:
enabled: true
host: workflow.example.com
helm install excalibase ./helm/excalibase-workflow \
--namespace excalibase --create-namespace \
-f values-override.yaml
What gets deployed
| Resource | Description |
|---|---|
| Deployment: backend | Go API server |
| Deployment: worker | Go task worker (scales independently) |
| Deployment: nats | NATS JetStream message queue |
| StatefulSet: postgres | PostgreSQL 16 with pgvector |
| Deployment: frontend | React UI (nginx) |
| ServiceAccount + Role + RoleBinding | RBAC for K8s Job execution |
| Ingress | Routes /api/* to backend, /* to frontend |
| Secret | Database password, API keys |
No Docker-in-Docker needed
In Kubernetes, script tasks run as native K8s Jobs — no DinD layer. The runner auto-detects the environment:
- Local (Docker Compose): Uses Docker-in-Docker to run script containers
- Kubernetes: Creates K8s Jobs directly via the API
This means 2 layers instead of 3:
Docker Compose: Host → DinD Container → Task Container (3 layers)
Kubernetes: K8s Node → Task Pod (2 layers, native)
The ServiceAccount is configured with least-privilege RBAC:
| Resource | Verbs | Purpose |
|---|---|---|
batch/jobs | create, get, list, watch, delete | Spawn task pods |
pods | get, list, watch | Monitor task status |
pods/log | get | Collect task output |
configmaps, secrets | create, get, delete | Task configuration |
Minikube quickstart
minikube start --cpus=4 --memory=4096 --driver=docker
minikube addons enable ingress
# Build images into minikube's Docker daemon
eval $(minikube docker-env)
docker build -t excalibase-workflow-backend:latest ./server/
docker build -t excalibase-workflow-worker:latest -f ./server/Dockerfile.worker ./server/
docker build -t excalibase-workflow-frontend:latest ./web/
# Deploy
helm install excalibase ./helm/excalibase-workflow \
--namespace excalibase --create-namespace
# Verify
kubectl get pods -n excalibase
# Access
kubectl port-forward -n excalibase svc/excalibase-excalibase-workflow-backend 8080:8080
kubectl port-forward -n excalibase svc/excalibase-excalibase-workflow-frontend 3000:80
Environment Variables
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | — | PostgreSQL connection string |
NATS_URL | — | NATS server URL |
PORT | 8080 | API server port |
DOCKER_HOST | unix:///var/run/docker.sock | Docker daemon (local dev only) |
RUNNER_MODE | (auto) | docker or kubernetes (auto-detects if empty) |
KUBE_NAMESPACE | default | Namespace for K8s task Jobs |
WORKER_CONCURRENCY | 10 | Concurrent task workers |
OPENAI_API_KEY | — | For AI tasks |
ANTHROPIC_API_KEY | — | For Anthropic provider |
GEMINI_API_KEY | — | For Gemini provider |
CREDENTIAL_ENCRYPTION_KEY | — | 32-char AES key for credential encryption |
CLI
A command-line tool for managing workflows from the terminal.
# Build
cd server && go build -o excalibase-cli ./cmd/cli
# Login
excalibase-cli login --server http://localhost:8080 --token <jwt>
# Manage workflows
excalibase-cli validate -f workflow.yaml
excalibase-cli apply -f workflow.yaml
excalibase-cli run <flow-id>
excalibase-cli status <execution-id>
excalibase-cli logs <execution-id>