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
kubectland Helm 3.8.0 or higher configured against it -
A default
StorageClassfor 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 specificStorageClass, or omit the line to use the cluster default<AUTH_KEYCLOAK_HOST>— your Keycloak realm's base URL, for examplehttps://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 atdial.<DOMAIN>and DIAL Chat atchat.<DOMAIN>, for exampleexample.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
HorizontalPodAutoscalerfor 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
- Custom Apps deployment — deploy your own applications alongside DIAL
- DIAL Core settings: Encryption — the AES settings Core uses for bucket prefixes
- Deployment profiles — which services and infrastructure each deployment profile needs
- AWS deployment — managed EKS with S3 and Bedrock
- Azure deployment — managed AKS with Blob Storage and Azure OpenAI
- GCP deployment — managed GKE with Cloud Storage and Vertex AI