Kubernetes deployment
Deploy self-hosted Tambo to a Kubernetes cluster with example manifests.
The Docker images can be deployed to Kubernetes. Below is a minimal example covering all three services. For production, add resource limits, health checks, and ingress configuration appropriate for your cluster.
Unlike Docker Compose, Kubernetes does not guarantee startup order. The API and web pods may restart a few times before PostgreSQL is ready — this is normal, and Kubernetes keeps retrying until connections succeed.
Want Helm charts or a more detailed Kubernetes setup? File an issue or reach out on Discord and we'll prioritize it.
Secrets
Create a Kubernetes secret with your environment variables:
apiVersion: v1
kind: Secret
metadata:
name: tambo-secrets
type: Opaque
stringData:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: your-secure-password
POSTGRES_DB: tambo
DATABASE_URL: postgresql://postgres:your-secure-password@tambo-postgres:5432/tambo
API_KEY_SECRET: your-32-character-api-key-secret
PROVIDER_KEY_SECRET: your-32-character-provider-secret
NEXTAUTH_SECRET: your-nextauth-secret
NEXTAUTH_URL: https://your-domain.com
FALLBACK_OPENAI_API_KEY: your-openai-api-keyPostgreSQL
For production, consider a managed database (e.g., AWS RDS, GCP Cloud SQL). If running PostgreSQL in-cluster:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: tambo-postgres
spec:
serviceName: tambo-postgres
replicas: 1
selector:
matchLabels:
app: tambo-postgres
template:
metadata:
labels:
app: tambo-postgres
spec:
containers:
- name: postgres
image: postgres:17
ports:
- containerPort: 5432
envFrom:
- secretRef:
name: tambo-secrets
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: tambo-postgres
spec:
selector:
app: tambo-postgres
ports:
- port: 5432
targetPort: 5432API service (NestJS)
apiVersion: apps/v1
kind: Deployment
metadata:
name: tambo-api
spec:
replicas: 2
selector:
matchLabels:
app: tambo-api
template:
metadata:
labels:
app: tambo-api
spec:
containers:
- name: api
image: your-registry/tambo-api:latest
ports:
- containerPort: 3000
env:
- name: PORT
value: "3000"
envFrom:
- secretRef:
name: tambo-secrets
---
apiVersion: v1
kind: Service
metadata:
name: tambo-api
spec:
selector:
app: tambo-api
ports:
- port: 8261
targetPort: 3000Web service (Next.js)
apiVersion: apps/v1
kind: Deployment
metadata:
name: tambo-web
spec:
replicas: 2
selector:
matchLabels:
app: tambo-web
template:
metadata:
labels:
app: tambo-web
spec:
containers:
- name: web
image: your-registry/tambo-web:latest
ports:
- containerPort: 3000
env:
- name: PORT
value: "3000"
# NEXT_PUBLIC_TAMBO_API_URL must be reachable from the browser,
# not an internal cluster address. Set this to your external API URL.
- name: NEXT_PUBLIC_TAMBO_API_URL
value: https://api.your-domain.com
envFrom:
- secretRef:
name: tambo-secrets
---
apiVersion: v1
kind: Service
metadata:
name: tambo-web
spec:
selector:
app: tambo-web
ports:
- port: 8260
targetPort: 3000Database migrations
After deploying, run database migrations by executing into a running API pod:
kubectl exec -it deployment/tambo-api -- npm -w @tambo-ai-cloud/db run db:migrateBuild and push images
./scripts/cloud/tambo-build.shTag and push to your container registry:
docker tag tambo-web:latest your-registry/tambo-web:latest
docker tag tambo-api:latest your-registry/tambo-api:latest
docker push your-registry/tambo-web:latest
docker push your-registry/tambo-api:latest