Skip to main content

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)
  • kubectl configured and connected to your cluster
  • helm v3 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.

vCPURAM
Minimal (1–5 databases)412 GB
Recommended (5–10 databases)816 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-platform
  • https://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
note

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: false and 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.zip package

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.