10 KiB
| title | description |
|---|---|
| Kubernetes (Helm) | Deploy Clawdbot on Kubernetes using Helm charts |
Kubernetes Deployment
Goal: Clawdbot Gateway running on Kubernetes with Helm, persistent storage, automatic HTTPS, and channel access.
What you need
- Kubernetes cluster (1.19+)
- kubectl CLI configured
- Helm 3.x
- Model auth: Anthropic API key (or other provider keys)
- Channel credentials: Discord bot token, Telegram token, etc.
- Optional: Ingress controller (NGINX, Traefik) for external access
- Optional: cert-manager for automatic TLS certificates
Beginner quick path
- Install Helm chart from source
- Configure secrets (API keys)
- Access Control UI via Ingress or port-forward
- Configure channels
Prerequisites
1) Kubernetes Cluster
You need a running Kubernetes cluster. Options:
Local development:
- Docker Desktop (macOS/Windows) - Enable Kubernetes in settings
- Minikube -
brew install minikube && minikube start - Kind -
brew install kind && kind create cluster
Cloud providers:
- GKE (Google Kubernetes Engine)
- EKS (Amazon Elastic Kubernetes Service)
- AKS (Azure Kubernetes Service)
- DigitalOcean Kubernetes
- Linode Kubernetes Engine
2) kubectl
Install kubectl:
# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Verify
kubectl version --client
kubectl cluster-info
3) Helm
Install Helm 3.x:
# macOS
brew install helm
# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Verify
helm version
Installation
1) Clone the repository
git clone https://github.com/clawdbot/clawdbot.git
cd clawdbot
2) Install Helm chart
Basic installation (development):
helm install my-clawdbot charts/clawdbot \
--set secrets.data.anthropicApiKey=sk-ant-xxx \
--set secrets.data.gatewayToken=$(openssl rand -hex 32)
With custom values file:
helm install my-clawdbot charts/clawdbot \
--values charts/clawdbot/examples/values-production.yaml \
--set secrets.data.anthropicApiKey=sk-ant-xxx \
--set ingress.hosts[0].host=assistant.example.com
Create external secret (recommended for production):
# Create secret
kubectl create secret generic clawdbot-secrets \
--from-literal=gatewayToken=$(openssl rand -hex 32) \
--from-literal=anthropicApiKey=sk-ant-xxx \
--from-literal=discordBotToken=YOUR_DISCORD_TOKEN
# Install with external secret
helm install my-clawdbot charts/clawdbot \
--values charts/clawdbot/examples/values-production.yaml \
--set secrets.create=false \
--set secrets.existingSecret=clawdbot-secrets
3) Verify installation
# Check deployment status
helm status my-clawdbot
kubectl get all -l app.kubernetes.io/instance=my-clawdbot
# Wait for pod to be ready
kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=my-clawdbot --timeout=120s
# Check logs
kubectl logs -f my-clawdbot-0
Access the Gateway
Option 1: Port-forward (local access)
kubectl port-forward my-clawdbot-0 18789:18789
Then visit: http://localhost:18789
Option 2: Ingress (external access)
Install NGINX Ingress Controller (if not already installed):
# For cloud providers
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.0/deploy/static/provider/cloud/deploy.yaml
# For bare metal/local
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.0/deploy/static/provider/baremetal/deploy.yaml
# For Minikube
minikube addons enable ingress
# For Kind
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
Enable Ingress in values:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod # If using cert-manager
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/websocket-services: "my-clawdbot"
hosts:
- host: assistant.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: clawdbot-tls
hosts:
- assistant.example.com
Upgrade with Ingress:
helm upgrade my-clawdbot charts/clawdbot \
--reuse-values \
--set ingress.enabled=true \
--set ingress.hosts[0].host=assistant.example.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix
3) Get gateway token
kubectl get secret my-clawdbot -o jsonpath='{.data.gatewayToken}' | base64 -d && echo
Use this token to authenticate in the Control UI.
Configuration
Configure channels
Discord
# Exec into pod
kubectl exec -it my-clawdbot-0 -- sh
# Inside pod
node dist/index.js channels add --channel discord --token YOUR_DISCORD_BOT_TOKEN
Or set via secret:
kubectl create secret generic clawdbot-secrets \
--from-literal=discordBotToken=YOUR_DISCORD_BOT_TOKEN \
--dry-run=client -o yaml | kubectl apply -f -
# Restart pod to apply
kubectl delete pod my-clawdbot-0
Telegram
kubectl exec -it my-clawdbot-0 -- node dist/index.js channels add \
--channel telegram \
--token YOUR_TELEGRAM_BOT_TOKEN
WhatsApp (QR code)
# Exec into pod
kubectl exec -it my-clawdbot-0 -- node dist/index.js channels login
Scan the QR code with WhatsApp on your phone.
Update configuration
Edit the config:
# Get current config
kubectl get configmap my-clawdbot-config -o yaml > clawdbot-config.yaml
# Edit clawdbot-config.yaml
# Apply changes
kubectl apply -f clawdbot-config.yaml
# Restart gateway to reload config
kubectl delete pod my-clawdbot-0
Storage
The chart creates a persistent volume claim that stores:
/home/node/.clawdbot- Config, sessions, device identity, SQLite databases/home/node/clawd- Agent workspace files
Check storage:
kubectl get pvc
kubectl describe pvc data-my-clawdbot-0
Increase storage size:
persistence:
size: 20Gi
Upgrading
# Pull latest changes
cd clawdbot
git pull
# Upgrade with current values
helm upgrade my-clawdbot charts/clawdbot --reuse-values
# Upgrade with new values
helm upgrade my-clawdbot charts/clawdbot -f values-production.yaml
Troubleshooting
Pod not starting
# Check events
kubectl describe pod my-clawdbot-0
# Check logs
kubectl logs my-clawdbot-0
# If pod crashed
kubectl logs my-clawdbot-0 --previous
OOM (Out of Memory)
Container keeps restarting. Signs: SIGABRT, v8::internal::Runtime_AllocateInYoungGeneration, or silent restarts.
Fix: Increase memory in values.yaml:
resources:
limits:
memory: 4Gi
requests:
memory: 1Gi
Note: 512MB is too small. 2GB recommended minimum.
PVC not binding
# Check PVC status
kubectl get pvc
# Check events
kubectl describe pvc data-my-clawdbot-0
# Check if storage provisioner is available
kubectl get storageclass
Fix for Minikube:
minikube addons enable storage-provisioner
minikube addons enable default-storageclass
Gateway lock issues
Gateway refuses to start with "already running" errors.
# Delete lock file
kubectl exec my-clawdbot-0 -- rm -f /home/node/.clawdbot/gateway.*.lock
# Restart pod
kubectl delete pod my-clawdbot-0
WebSocket connections timing out
Ensure Ingress has proper annotations:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/websocket-services: "my-clawdbot"
Config not being read
If using --allow-unconfigured, the gateway creates a minimal config. Your custom config should be read on restart.
# Verify config exists
kubectl exec my-clawdbot-0 -- cat /home/node/.clawdbot/clawdbot.json
# Verify ConfigMap
kubectl get configmap my-clawdbot-config -o yaml
Image pull errors (local testing)
When testing with local images:
# Ensure pullPolicy is Never
--set image.pullPolicy=Never
# Load image into cluster
# Docker Desktop: Image already available
# Minikube: minikube image load clawdbot:local
# Kind: kind load docker-image clawdbot:local
Local Testing
Test the Helm chart locally before deploying to production:
Using Docker Desktop Kubernetes
# Enable Kubernetes in Docker Desktop settings
# Run automated test script
./scripts/test-helm-local.sh
Using Minikube
# Start Minikube
minikube start --memory=4096 --cpus=2
# Build and load image
docker build -t clawdbot:local .
minikube image load clawdbot:local
# Install chart
helm install test charts/clawdbot \
-f charts/clawdbot/examples/values-basic.yaml \
--set image.repository=clawdbot \
--set image.tag=local \
--set image.pullPolicy=Never
# Access via port-forward
kubectl port-forward test-clawdbot-0 18789:18789
Using Kind
# Create cluster
kind create cluster
# Build and load image
docker build -t clawdbot:local .
kind load docker-image clawdbot:local
# Install chart
helm install test charts/clawdbot \
-f charts/clawdbot/examples/values-basic.yaml \
--set image.repository=clawdbot \
--set image.tag=local \
--set image.pullPolicy=Never
Uninstall
# Uninstall Helm release
helm uninstall my-clawdbot
# Delete PVCs (data will be lost)
kubectl delete pvc -l app.kubernetes.io/instance=my-clawdbot
Notes
- Clawdbot is a single-user application. The chart enforces
replicas: 1. - WebSocket gateway requires long-lived connections (use proper Ingress timeouts).
- Persistent storage is required to preserve state across restarts.
- Docker-in-Docker sandboxing is disabled by default in Kubernetes deployments.
- For production, use external secret management (Kubernetes Secrets, External Secrets Operator, or Vault).
Documentation
Cost
Kubernetes cluster costs vary by provider:
- Local (free): Docker Desktop, Minikube, Kind
- Cloud providers: $50-200/month depending on node size and region
- Recommended resources: 2 CPU, 4GB RAM minimum
See your cloud provider's pricing for details.