# Openclaw Helm Chart Personal AI assistant with multi-channel support (WhatsApp, Telegram, Discord, and more) running on Kubernetes. ## TL;DR ```bash helm install my-openclaw ./openclaw \ --set secrets.data.anthropicApiKey=sk-ant-xxx \ --set secrets.data.gatewayToken=$(openssl rand -hex 32) ``` ## Introduction This chart deploys Openclaw Gateway on a Kubernetes cluster using the Helm package manager. **Important:** Openclaw is designed as a single-user personal assistant. The chart enforces `replicas: 1` and does not support horizontal scaling. ## Prerequisites - Kubernetes 1.19+ - Helm 3.x - PV provisioner support in the underlying infrastructure (for persistent storage) - **Optional:** Ingress controller (NGINX, Traefik, etc.) for external access - **Optional:** cert-manager for automatic TLS certificates ## Installing the Chart ### Basic Installation ```bash helm install my-openclaw ./openclaw ``` ### With Custom Values ```bash helm install my-openclaw ./openclaw \ --values examples/values-production.yaml \ --set secrets.data.anthropicApiKey=sk-ant-xxx \ --set ingress.hosts[0].host=assistant.example.com ``` ### From Examples ```bash # Basic (local testing) helm install my-openclaw ./openclaw -f examples/values-basic.yaml # Production helm install my-openclaw ./openclaw -f examples/values-production.yaml # Fly.io-like setup helm install my-openclaw ./openclaw -f examples/values-fly-like.yaml ``` ## Uninstalling the Chart ```bash helm uninstall my-openclaw # Also delete PVCs (data will be lost) kubectl delete pvc -l app.kubernetes.io/instance=my-openclaw ``` ## Configuration ### Key Parameters | Parameter | Description | Default | |-----------|-------------|---------| | `replicaCount` | Number of replicas (must be 1) | `1` | | `image.repository` | Openclaw image repository | `openclaw/openclaw` | | `image.tag` | Image tag | Chart appVersion | | `gateway.bind` | Gateway binding mode (`loopback`, `lan`, `auto`) | `lan` | | `gateway.port` | Gateway port | `18789` | | `secrets.data.anthropicApiKey` | Anthropic API key | `""` | | `secrets.data.openaiApiKey` | OpenAI API key | `""` | | `secrets.data.gatewayToken` | Gateway authentication token (auto-generated if empty) | `""` | | `persistence.enabled` | Enable persistent storage | `true` | | `persistence.size` | PVC size | `10Gi` | | `ingress.enabled` | Enable Ingress | `false` | | `ingress.className` | Ingress class | `nginx` | | `resources.limits.memory` | Memory limit | `2Gi` | | `resources.requests.memory` | Memory request | `512Mi` | ### Full Values Reference See [values.yaml](values.yaml) for all available parameters. ## Storage The chart creates a StatefulSet with a persistent volume claim template that mounts storage at two locations: - `/home/node/.openclaw` (subPath: `openclaw-state`) - Configuration, sessions, device identity, SQLite databases - `/home/node/clawd` (subPath: `openclaw-workspace`) - Agent workspace files **Storage Class:** By default, uses the cluster's default storage class. Override with `persistence.storageClass`. **Size Recommendations:** - Development/Testing: 5-10Gi - Production (single user): 20Gi+ - Depends on session history and workspace usage ## Secrets Management ### Option 1: Inline Secrets (Development Only) ```bash helm install my-openclaw ./openclaw \ --set secrets.data.anthropicApiKey=sk-ant-xxx \ --set secrets.data.gatewayToken=$(openssl rand -hex 32) ``` ### Option 2: External Secret (Production) Create a Kubernetes Secret: ```bash kubectl create secret generic openclaw-secrets \ --from-literal=gatewayToken=$(openssl rand -hex 32) \ --from-literal=anthropicApiKey=sk-ant-xxx \ --from-literal=discordBotToken=MTQ... ``` Install with existing secret: ```bash helm install my-openclaw ./openclaw \ --set secrets.create=false \ --set secrets.existingSecret=openclaw-secrets ``` ### Option 3: External Secrets Operator Use External Secrets Operator to sync from Vault, AWS Secrets Manager, etc. ## Ingress ### NGINX Ingress Controller ```yaml ingress: enabled: true className: nginx annotations: cert-manager.io/cluster-issuer: letsencrypt-prod nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" nginx.ingress.kubernetes.io/websocket-services: "{{ include \"openclaw.fullname\" . }}" hosts: - host: assistant.example.com paths: - path: / pathType: Prefix tls: - secretName: openclaw-tls hosts: - assistant.example.com ``` **Important:** WebSocket support requires extended timeouts (3600s recommended). ### Traefik ```yaml ingress: className: traefik annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" ``` ## Health Checks The chart uses exec-based probes that run the CLI health command: ```yaml livenessProbe: exec: command: - sh - -c - node dist/index.js health --token "${CLAWDBOT_GATEWAY_TOKEN}" || exit 1 ``` ## Upgrading ```bash # Pull latest chart changes git pull # Upgrade with current values helm upgrade my-openclaw ./openclaw --reuse-values # Upgrade with new values helm upgrade my-openclaw ./openclaw -f values-production.yaml ``` ## Troubleshooting ### Pod Not Starting ```bash # Check pod events kubectl describe pod my-openclaw-0 # Check logs kubectl logs my-openclaw-0 ``` ### OOM (Out of Memory) Increase memory limits: ```yaml resources: limits: memory: 4Gi requests: memory: 1Gi ``` **Note:** 512MB is too small for production. 2GB recommended minimum. ### PVC Not Binding ```bash # Check PVC status kubectl get pvc # Check storage class kubectl get storageclass # Describe for events kubectl describe pvc data-my-openclaw-0 ``` ### WebSocket Connections Timing Out Ensure Ingress has WebSocket annotations: ```yaml annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" ``` ### Gateway Lock File Issues If the gateway won't start due to stale lock files: ```bash kubectl exec my-openclaw-0 -- rm -f /home/node/.openclaw/gateway.*.lock kubectl delete pod my-openclaw-0 # Restart pod ``` ## Examples ### Local Testing (Minikube/Kind/Docker Desktop) ```bash # Build local image docker build -t openclaw:local . # Load into cluster (example for Minikube) minikube image load openclaw:local # Install chart helm install test ./openclaw \ -f examples/values-basic.yaml \ --set image.repository=openclaw \ --set image.tag=local \ --set image.pullPolicy=Never ``` ### Production Deployment ```bash # Create external secret first kubectl create secret generic openclaw-secrets \ --from-literal=gatewayToken=$(openssl rand -hex 32) \ --from-literal=anthropicApiKey=$ANTHROPIC_API_KEY # Install with production values helm install my-openclaw ./openclaw -f examples/values-production.yaml ``` ## Documentation - [Openclaw Documentation](https://docs.clawd.bot) - [Kubernetes Installation Guide](https://docs.clawd.bot/install/kubernetes) - [GitHub Repository](https://github.com/openclaw/openclaw) ## Support - [GitHub Issues](https://github.com/openclaw/openclaw/issues) - [Documentation](https://docs.clawd.bot) ## License See [LICENSE](https://github.com/openclaw/openclaw/blob/main/LICENSE)