Helm Charts
Deploy Tuneloop on Kubernetes using Helm for production environments with high availability and scaling.
Prerequisites
- A Kubernetes cluster (1.26+)
- Helm 3.x
- A Postgres 17 instance (managed or self-hosted)
- Docker Hub credentials provided by the Tuneloop team (username + access token)
Installation
Create the image pull secret
Tuneloop images are hosted on a private Docker Hub registry. Create a Kubernetes secret with the credentials provided by the Tuneloop team:
kubectl create namespace tuneloop
kubectl create secret docker-registry tuneloop-registry-secret \
--namespace tuneloop \
--docker-server=docker.io \
--docker-username=<username> \
--docker-password=<access-token>
Install the chart
helm repo add tuneloop https://tuneloop.github.io/tuneloop-helm-charts
helm repo update
helm install tuneloop tuneloop/tuneloop \
--namespace tuneloop \
--set global.imagePullSecrets[0].name=tuneloop-registry-secret \
--set postgres.host=your-postgres-host \
--set postgres.password=your-password \
--set ingestToken=your-ingest-token
Architecture
The Helm chart deploys three workloads:
- web (Deployment) — API server and dashboard. Horizontally scalable. Expose via Ingress.
- worker (Deployment) — Background analysis pipeline. Scale by increasing replicas or worker concurrency.
- runner (Deployment) — Benchmark execution. Requires Docker socket access (DinD sidecar or privileged node pool). Optional — omit if you do not use benchmarks.
A migration Job runs on each upgrade before the workloads start, applying any pending schema changes.
Postgres is external — bring your own managed instance (RDS, Cloud SQL, etc.) or deploy one in-cluster.
Configuration
All configuration is via Helm values. See values.yaml for the full reference.
# values.yaml (excerpt)
global:
imagePullSecrets:
- name: tuneloop-registry-secret
web:
replicas: 2
env:
TUNELOOP_LLM_PROVIDER: anthropic
TUNELOOP_LLM_MODEL: claude-haiku-4-5
worker:
replicas: 2
concurrency: 4
runner:
enabled: false
github:
appClientId: ""
privateKeySecret: github-app-key
webhookSecret: ""
jira:
enabled: false
Ingress & DNS
The web service needs an externally reachable URL. This is the address your team will use for the dashboard and the same address every tuneloop-ingest CLI will upload transcripts to.
Add ingress values to your values.yaml:
web:
ingress:
enabled: true
className: nginx # or: alb (AWS), gce (GKE)
hosts:
- host: tuneloop.yourcompany.com
paths:
- path: /
pathType: Prefix
tls:
- hosts:
- tuneloop.yourcompany.com
secretName: tuneloop-tls # cert-manager, ACM, or your own cert
annotations: {} # add controller-specific annotations here
After deploying, retrieve the load balancer address:
# AWS (ALB / NLB — returns a hostname)
kubectl get ingress tuneloop-ingress -n tuneloop \
-o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
# GKE / nginx (returns an IP)
kubectl get ingress tuneloop-ingress -n tuneloop \
-o jsonpath='{.status.loadBalancer.ingress[0].ip}'
Create a DNS record pointing your chosen hostname to the load balancer:
- AWS: CNAME → the ALB/NLB hostname
- GKE / other: A record → the IP address
Once DNS propagates, the dashboard is live at https://tuneloop.yourcompany.com and the ingest endpoint is at https://tuneloop.yourcompany.com/api/ingest.
Database Setup
AWS RDS
aws rds create-db-instance \
--db-instance-identifier tuneloop-db \
--db-instance-class db.t3.medium \
--engine postgres \
--engine-version 17 \
--master-username tuneloop \
--master-user-password your-secure-password \
--allocated-storage 50 \
--storage-type gp3 \
--db-name tuneloop \
--no-publicly-accessible
Ensure the RDS security group allows inbound connections from your EKS cluster's security group on port 5432.
Google Cloud SQL
gcloud sql instances create tuneloop-db \
--database-version=POSTGRES_17 \
--tier=db-custom-2-7680 \
--region=us-central1 \
--root-password=your-secure-password \
--storage-size=50GB \
--storage-type=SSD
gcloud sql databases create tuneloop --instance=tuneloop-db
Scaling
# Scale web replicas
helm upgrade tuneloop tuneloop/tuneloop \
--namespace tuneloop \
--set web.replicas=4
# Scale worker replicas and concurrency
helm upgrade tuneloop tuneloop/tuneloop \
--namespace tuneloop \
--set worker.replicas=3 \
--set worker.concurrency=4
Updating
helm repo update
helm upgrade tuneloop tuneloop/tuneloop \
--namespace tuneloop \
-f my-values.yaml
Migrations run automatically as a pre-upgrade Job.
Teardown
Uninstall the release:
helm uninstall tuneloop --namespace tuneloop
To also remove the namespace and image pull secret:
kubectl delete namespace tuneloop
This does not delete your external Postgres database or its data.
Next Steps
Once deployed:
- Configure LLM enrichment and connectors
- Set up integrations to start capturing sessions
- Connect GitHub and Jira for outcome linking