Self-hosted DBtune on Kubernetes
Overview
DBtune can be deployed on any Kubernetes cluster using the official Helm chart. This is the recommended deployment method for customers running Kubernetes infrastructure such as AWS EKS, Google GKE, Azure AKS, Red Hat OpenShift, Rancher, or k3s.
If you are running a single VM without Kubernetes, see the Docker Compose self-hosted guide instead.
Prerequisites
- A running Kubernetes cluster (EKS, GKE, AKS, OpenShift, Rancher, k3s, or similar)
kubectlconfigured and connected to your clusterhelmv3 or later installed- A GitHub account — DBtune will provide access to pull the necessary images
System Requirements
Requirements scale with the number of connected databases and concurrent tuning sessions.
| vCPU | RAM | |
|---|---|---|
| Minimal (1–5 databases) | 4 | 12 GB |
| Recommended (5–10 databases) | 8 | 16 GB |
Installation
Step 1 — Unpack the release
The Helm chart is included in the self-hosted.zip archive provided to you by DBtune.
Unpack it and locate the chart directory:
unzip self-hosted.zip
cd self-hosted/helm
Step 2 — Create the namespace
kubectl create namespace dbtune
Step 3 — Create the image pull secret
DBtune images are hosted on GitHub Container Registry. Create a pull secret using your GitHub account (DBtune will have granted your account access):
kubectl create secret docker-registry ghcr-pull-secret \
--docker-server=ghcr.io \
--docker-username=<your-github-username> \
--docker-password=<your-github-token> \
-n dbtune
Step 4 — Create your values file
cp dbtune/values.yaml my-values.yaml
Edit my-values.yaml and fill in the required fields:
# URL the platform will be accessed from — must match how users reach the platform
# e.g. https://dbtune.yourdomain.com for public access, or http://internal-host for private/air-gapped
frontendUrl: "https://dbtune.yourdomain.com"
django:
secretKey: "<random-50-char-string>" # openssl rand -base64 40
superuserEmail: "admin@yourdomain.com"
superuserPassword: "<strong-password>"
superuserApiKey: "<uuid4>" # python3 -c "import uuid; print(uuid.uuid4())"
email:
host: "smtp.yourdomain.com"
port: 587
useTls: "true"
from: "noreply@yourdomain.com"
password: "<smtp-password>"
postgres:
password: "<strong-password>"
prefectPassword: "<strong-password>"
influxdb:
token: "<random-string>"
initPassword: "<strong-password>"
Step 5 — Configure access
How users reach the platform depends on your network setup. Choose the option that fits your environment:
Option A — Ingress (public or internal domain)
The chart can create a Kubernetes Ingress resource to route traffic to the platform. Your cluster must have an ingress controller already installed (e.g. nginx, Traefik, ALB).
ingress:
enabled: true
className: "nginx" # or "traefik", "alb", etc.
annotations: {} # add ingress controller specific annotations here
To enable TLS, create a secret from your certificate files first:
kubectl create secret tls dbtune-tls \
--cert=tls.crt \
--key=tls.key \
-n dbtune
Then reference it in your values:
ingress:
tls:
enabled: true
secretName: dbtune-tls
Option B — Port-forward (air-gapped, internal, or testing)
For air-gapped or private deployments where no ingress controller is available, disable ingress and access the platform via port-forward:
ingress:
enabled: false
kubectl port-forward -n dbtune svc/web <local-port>:8000
The right side (8000) is the port the web service listens on inside the cluster and must stay as-is.
The left side is the local port you want to access it on — you can use any available port on your machine.
Then set frontendUrl to match, e.g. http://internal-hostname:<local-port>.
Step 6 — Deploy
helm install dbtune dbtune \
-f my-values.yaml \
-n dbtune
Step 7 — Wait for all pods to be ready
kubectl get pods -n dbtune -w
All 9 pods should reach 1/1 Running:
db 1/1 Running
dbtuner 1/1 Running
influxdb 1/1 Running
ingest 1/1 Running
prefect-server 1/1 Running
redis 1/1 Running
web 1/1 Running
worker 1/1 Running
ws 1/1 Running
Step 8 — Access the platform
Open the URL you set as frontendUrl and log in with the superuser credentials from your values file.
OpenShift
When deploying on Red Hat OpenShift, set openshift.enabled: true. This enables OpenShift-specific behaviour:
- Runs containers as root (required — OpenShift's default restricted SCC does not allow the UIDs used by the platform and postgres images)
- Adds an init container to fix PostgreSQL data directory permissions before startup
- Creates OpenShift Routes instead of standard Ingress resources
Additional OpenShift setup
OpenShift's restricted SCC blocks containers from running as specific UIDs by default.
Grant the anyuid SCC to the namespace to allow this before deploying:
oc adm policy add-scc-to-group anyuid system:serviceaccounts:dbtune
Deploy on OpenShift
helm install dbtune dbtune \
-f my-values.yaml \
-n dbtune \
--set openshift.enabled=true
OpenShift Routes are created automatically — no ingress controller needed.
Upgrading
When a new version is released, update the image tags in your values file and run:
helm upgrade dbtune dbtune \
-f my-values.yaml \
-n dbtune
Check available versions at:
https://github.com/dbtuneai/dbtune-platform/pkgs/container/dbtune-platformhttps://github.com/dbtuneai/dbtune-platform/pkgs/container/dbtuner
Scaling
The platform includes a dedicated ingest service that handles all agent API traffic (/api/v1/agent/*) separately from the user-facing web service. This means agent load does not affect dashboard performance and each can scale independently.
For deployments with a large number of agents (20+), enable autoscaling on the ingest service:
ingest:
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 60
Autoscaling requires the Kubernetes metrics-server to be installed in your cluster. Most managed Kubernetes services (EKS, GKE, AKS) include it by default. For k3s, install it with kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml.
DBtune agent
The DBtune agent connects to the platform via the frontendUrl you configured.
Set the agent's server_url to that same value.
The agent is open-source and written in Go: github.com/dbtuneai/dbtune-agent. More information can be found in the agent documentation.
Email / SMTP
Real SMTP is required for password resets and notifications. Example for Gmail:
email:
host: "smtp.gmail.com"
port: 587
useTls: "true"
from: "your@email.com"
password: "<app-password>"
Air-gapped deployments
The platform requires no internet access at runtime. All inter-service communication happens inside the cluster over the internal Kubernetes network.
For fully air-gapped environments:
- Use
ingress.enabled: falseand access via port-forward or an internal load balancer — no public endpoint required - Pre-pull all images and push to your internal registry, then update the image repositories in
values.yaml - All DBtune images are provided to you via the
self-hosted.zippackage
Security
All internal services (postgres, redis, influxdb, prefect, worker, ws) communicate privately inside the cluster and are not reachable from outside.
The web service is only exposed externally if you enable ingress (ingress.enabled: true)
or explicitly expose it via port-forward. With ingress.enabled: false nothing is exposed
to the network automatically.