Skip to content

Helm Install

Errand can be deployed to any Kubernetes cluster using its official Helm chart. This is the recommended approach for production environments, teams, and anywhere you need high availability or autoscaling.

  • A running Kubernetes cluster (any provider — cloud or local)
  • Helm 3 installed on your machine
  • kubectl configured to access your cluster
  • An API key from at least one LLM provider (e.g. Anthropic, OpenAI)
  • A PostgreSQL database (the chart does not bundle one)

Before installing the chart, create the secrets that Errand needs. Run these commands, replacing the placeholder values with your own:

  1. Database credentials — connection string for PostgreSQL:

    Terminal window
    kubectl create secret generic errand-database \
    --from-literal=DATABASE_URL="postgresql://user:password@hostname:5432/errand"
  2. LLM provider credentials — your API key:

    Terminal window
    kubectl create secret generic errand-openai \
    --from-literal=OPENAI_API_KEY="your-api-key-here"
  3. Credential encryption key — used to encrypt stored integration credentials:

    Terminal window
    kubectl create secret generic errand-encryption \
    --from-literal=CREDENTIAL_ENCRYPTION_KEY="$(python3 -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())')"
  4. Hindsight bearer token (only if you enable Hindsight agent memory):

    Terminal window
    kubectl create secret generic errand-hindsight \
    --from-literal=HINDSIGHT_TOKEN="$(openssl rand -hex 32)"

Install the chart directly from the OCI registry:

Terminal window
helm install errand oci://ghcr.io/errand-ai/charts/errand \
--set database.existingSecret=errand-database \
--set llmProviders[0].name=openai \
--set llmProviders[0].existingSecret=errand-openai \
--set credentialEncryption.existingSecret=errand-encryption

The Helm chart is configured through a values.yaml file. Here are the key settings:

ValueDescriptionDefault
server.replicaCountNumber of API server replicas (the task manager runs in-process in the server)1
server.maxTurnsMaximum LLM reasoning turns per task200
server.maxConcurrentTasksOptional operator override for concurrent tasks per replica (leave unset to manage in the admin UI)unset

Multiple server replicas are safe — the in-process task manager uses Postgres advisory locks to elect a single leader per task, so only one replica runs each task runner.

ValueDescription
database.existingSecretKubernetes secret containing DATABASE_URL
llmProviders[].existingSecretKubernetes secret containing the LLM provider’s API key (one per provider entry)
credentialEncryption.existingSecretKubernetes secret containing CREDENTIAL_ENCRYPTION_KEY
hindsight.apiKey.secretKubernetes secret containing HINDSIGHT_TOKEN (only when Hindsight is enabled)
gdrive.existingSecretKubernetes secret containing GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
onedrive.existingSecretKubernetes secret containing MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, and MICROSOFT_TENANT_ID
ValueDescriptionDefault
ingress.hostDomain name for the Errand UI—
ingress.tls.enabledEnable HTTPS using cert-managerfalse
ValueDescriptionDefault
valkey.enabledDeploy a built-in Valkey cache (recommended for single-cluster deployments; disable and supply VALKEY_URL to use an external instance)true
onedrive.enabledEnable OneDrive integrationtrue
playwright.enabledDeploy the Playwright browser-automation sidecartrue
hindsight.urlURL of an external Hindsight service (empty = don’t connect to Hindsight)""
workspaceGateway.enabledEnable the shared cloud workspace gateway (rclone NFS at /shared)false

To use a custom values file:

Terminal window
helm install errand oci://ghcr.io/errand-ai/charts/errand \
-f values.yaml
  1. Check that the pods are running:

    Terminal window
    kubectl get pods -l app.kubernetes.io/name=errand
  2. If you configured an ingress, open https://your-domain in your browser. Otherwise, use port forwarding:

    Terminal window
    kubectl port-forward svc/errand-server 8000:8000
  3. Navigate to http://localhost:8000 and log in

The server’s in-process task manager uses Kubernetes Jobs to execute each task in an isolated pod. This means:

  • Each task runs in its own container with its own resources
  • A failed task does not affect other running tasks
  • The server’s ServiceAccount needs RBAC permissions to create and manage Jobs, ConfigMaps, and Pods

The Helm chart automatically creates the required ServiceAccount and RBAC roles. If you are using a custom ServiceAccount, make sure it has permissions for jobs, configmaps, and pods in the Errand namespace.

The chart does not include a built-in PostgreSQL instance. You need to provide your own database. Two common options:

  • Managed database — use a cloud-hosted PostgreSQL service (e.g. AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL) and pass the connection string via the database.existingSecret
  • CloudNativePG — deploy PostgreSQL on Kubernetes using the CloudNativePG operator, which handles backups, failover, and high availability
IssueSolution
Pods stuck in Pending stateCheck for resource constraints with kubectl describe pod <pod-name>. The cluster may not have enough CPU or memory available
Server pod crashes on startupCheck logs with kubectl logs <pod-name>. The most common cause is a missing or incorrect DATABASE_URL in the database secret
Tasks not startingCheck the server logs. The most common cause is a missing LLM provider API key secret or a wrong OPENAI_API_KEY
Cannot reach the UI through ingressConfirm that ingress.host is set correctly, DNS points to your cluster, and (if using TLS) cert-manager has issued a certificate
LLM errors during task executionVerify the LLM provider’s API key secret is correct and your account has available credits