Skip to content

Kubernetes

AI Butler ships with a Helm chart for Kubernetes deployments. It’s a single-pod deployment with a persistent volume for state — no clustering complexity.

  • Kubernetes 1.26+
  • Helm 3.10+
  • A StorageClass that supports ReadWriteOnce (almost all providers do)
Terminal window
git clone https://github.com/LumabyteCo/aibutler.git
cd aibutler
helm install aibutler deploy/helm/aibutler/ \
--namespace aibutler \
--create-namespace \
--set secrets.anthropicApiKey=sk-ant-... \
--set ingress.host=aibutler.example.com

Key values.yaml settings:

image:
repository: ghcr.io/lumabyteco/aibutler
tag: latest
pullPolicy: IfNotPresent
persistence:
enabled: true
size: 10Gi
storageClass: "" # "" = default StorageClass
resources:
limits:
cpu: 2000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
ingress:
enabled: true
className: nginx
host: aibutler.example.com
tls: true
certIssuer: letsencrypt-prod # if using cert-manager
secrets:
anthropicApiKey: ""
openaiApiKey: ""
telegramBotToken: ""
config:
settings:
persona_name: "Butler"
configurations:
web:
port: 3377
auth:
enabled: true

The chart creates a Kubernetes Secret from any secrets.* values. At runtime, the init container writes them to the encrypted vault. For production, use your secrets manager (Sealed Secrets, External Secrets Operator, Vault, etc.) instead of plain Helm values.

AI Butler is stateful — it needs persistent storage for SQLite. The chart provisions a PersistentVolumeClaim and mounts it at /data. This is not a stateless 12-factor app — do not run multiple replicas without understanding that each replica needs its own PV and shares no state with others.

Single-replica is the intended deployment. Horizontal scale-out uses the A2A protocol instead (see A2A).

The included ingress works out of the box with nginx-ingress and cert-manager:

ingress:
enabled: true
className: nginx
host: aibutler.example.com
tls: true
certIssuer: letsencrypt-prod
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "25m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"

WebSocket upgrades are required for streaming replies — nginx-ingress handles this automatically, but if you use a different ingress controller, make sure it supports HTTP upgrade and has a generous read timeout.

Terminal window
helm upgrade aibutler deploy/helm/aibutler/ \
--namespace aibutler \
--reuse-values

Database schema migrations run automatically on pod startup. If a migration fails, the pod fails its readiness probe — check the logs with kubectl logs -n aibutler deploy/aibutler.

Terminal window
# Trigger a hot backup
kubectl exec -n aibutler deploy/aibutler -- aibutler backup create /data/backups/manual.db
# Copy it out of the cluster
kubectl cp aibutler/aibutler-pod-name:/data/backups/manual.db ./manual.db

For scheduled backups, use a CronJob that execs into the pod nightly. Or enable the built-in remote backup target (S3-compatible):

config:
configurations:
backup:
remote:
provider: s3
endpoint: s3.amazonaws.com
bucket: my-aibutler-backups
# access/secret keys via secrets.*

Enable the metrics endpoint:

metrics:
enabled: true
serviceMonitor:
enabled: true # auto-scrapes with prometheus-operator

Exposes standard Go runtime metrics plus AI Butler specifics: requests per channel, tool-call counts, memory system health, model latency histograms.