Skip to main content

Deploy DIAL on a generic Kubernetes cluster

Deploy the full DIAL stack to any Kubernetes cluster that is not tied to a specific cloud provider — a self-managed cluster, an on-premises cluster, or a local distribution such as minikube or kind. This guide assumes you are familiar with Helm and kubectl. For provider-managed clusters, use the AWS, Azure, or GCP guides instead, which integrate managed storage and identity.

Prerequisites​

  • A Kubernetes cluster, version 1.23 or higher, with kubectl and Helm 3.8.0 or higher configured against it

  • A default StorageClass for persistent volumes (DIAL Core stores files on a persistent volume rather than cloud object storage)

  • An ingress controller, if you want to expose DIAL outside the cluster

  • An endpoint and key for at least one model provider reachable from the cluster

  • An OpenID Connect identity provider for DIAL Chat sign-in (this example uses Keycloak; substitute your own provider's endpoints if you use a different one)

  • The DIAL Helm repository added:

    helm repo add dial https://charts.dialx.ai
    helm repo update

Step 1: Create a values file​

Start from the upstream generic simple example, which deploys DIAL with a persistent-volume file store and a single model adapter. The required values are:

core:
# Files are stored on a persistent volume instead of cloud object storage
persistence:
enabled: true
size: 10Gi
# storageClass: <STORAGE_CLASS> # omit to use the cluster default
env:
aidial.identityProviders.keycloak.jwksUrl: "<AUTH_KEYCLOAK_HOST>/protocol/openid-connect/certs"
aidial.identityProviders.keycloak.rolePath: "roles"
aidial.identityProviders.keycloak.issuerPattern: "^<AUTH_KEYCLOAK_HOST>$"
ingress:
enabled: true
ingressClassName: nginx
hosts:
- dial.<DOMAIN>

openai:
env:
aidial.openai.endpoint: <MODEL_ENDPOINT>
aidial.openai.key: <MODEL_KEY>

chat:
env:
AUTH_CALLBACK_BASE_URL: "http://chat.<DOMAIN>"
AUTH_POST_LOGOUT_REDIRECT_URI: "http://chat.<DOMAIN>"
DIAL_CORE_URL: "http://dial-core.dial.svc.cluster.local"
CORS_ORIGIN: "http://chat.<DOMAIN>"
secrets:
AUTH_SESSION_SECRET: <AUTH_SESSION_SECRET>
AUTH_KEYCLOAK_CLIENT_ID: <AUTH_KEYCLOAK_CLIENT_ID>
AUTH_KEYCLOAK_HOST: <AUTH_KEYCLOAK_HOST>
AUTH_KEYCLOAK_SECRET: <AUTH_KEYCLOAK_SECRET>
ingress:
enabled: true
ingressClassName: nginx
hosts:
- chat.<DOMAIN>

This example assumes an NGINX-based ingress controller (ingressClassName: nginx); substitute your own class if you use a different controller. DIAL Core and DIAL Chat each get their own host, under core.ingress and chat.ingress. core.env registers Keycloak as the identity provider DIAL Core trusts for user tokens; chat.env/chat.secrets configure DIAL Chat's own sign-in flow against the same Keycloak client — set its redirect URI to match AUTH_CALLBACK_BASE_URL. If you use a real domain with HTTPS instead of plain HTTP, switch these URLs to https://. The upstream example also shows a cert-manager-issued TLS variant; see the generic example - simple if you want HTTPS out of the box.

Replace the placeholders:

  • <STORAGE_CLASS> — a specific StorageClass, or omit the line to use the cluster default
  • <AUTH_KEYCLOAK_HOST> — your Keycloak realm's base URL, for example https://keycloak.example.com/realms/dial
  • <MODEL_ENDPOINT> — the endpoint of your model provider
  • <MODEL_KEY> — the API key for the model provider
  • <DOMAIN> — the base domain for ingress; DIAL Core is exposed at dial.<DOMAIN> and DIAL Chat at chat.<DOMAIN>, for example example.com
  • <AUTH_KEYCLOAK_CLIENT_ID> — the Keycloak client ID
  • <AUTH_KEYCLOAK_SECRET> — the Keycloak client secret
  • <AUTH_SESSION_SECRET> — a random secret DIAL Chat uses to encrypt session cookies

Generate the DIAL API key, encryption key, and <AUTH_SESSION_SECRET> before installing and supply them as values or Kubernetes secrets.

Step 2: Install the chart​

helm install dial dial/dial \
-f values.yaml \
--version <CHART_VERSION> \
--namespace dial \
--create-namespace

Pin <CHART_VERSION> to a released chart version.

Step 3: Verify the deployment​

Check that the pods are running:

kubectl get pods -n dial

If you configured ingress as shown in Step 1, DIAL Chat is reachable at http://chat.<DOMAIN>/ and the Unified API at http://dial.<DOMAIN>/ (or https:// once you add TLS); open DIAL Chat in a browser and sign in through Keycloak.

If you did not configure ingress, port-forward DIAL Core to reach the Unified API instead:

kubectl port-forward svc/dial-core 8080:8080 -n dial
curl http://localhost:8080/openai/deployments \
-H "Api-Key: <YOUR_DIAL_API_KEY>"

Result​

DIAL Core, DIAL Chat, and Valkey run on your cluster, with files persisted to a Kubernetes persistent volume and models served from your configured provider.

Production architecture​

The generic example uses a persistent volume and a single model endpoint, which suits evaluation and on-premises installs. For production resilience, address the same concerns the managed-cloud guides cover:

  • Stateless scaling — DIAL services are stateless. Run at least two copies of each service across nodes and configure a HorizontalPodAutoscaler for DIAL Core based on CPU usage.
  • Storage durability — a single persistent volume is a single point of failure. Back the volume with replicated or networked storage, and schedule snapshots or backups of the file store.
  • Cache — Valkey is a cache and can be restarted safely, but a production deployment should run a highly available Redis-compatible cache rather than the in-cluster single instance.
  • Model resilience — define multiple model endpoints so DIAL fails over automatically when one is unavailable.
  • Secrets — store the API key, encryption key, and model credentials in your secret manager rather than in the values file.

Further reading​