Installing Helix on GKE with Helm
The following demonstrates how to deploy Helix on GKE using Terraform and Helm.
Prerequisites
- Install
terraform
brew install terraform
- Install
google-cloud-sdk
to get thegcloud
CLI
brew install --cask google-cloud-sdk
- Ensure you have sufficient quota for an
L4
GPU. See the GCP docs for more details.
Setup
- Clone this repository and cd into the directory:
git clone https://github.com/helixml/terraform-gke-helix.git
cd terraform-gke-helix
- Log into GCP:
gcloud init
gcloud auth application-default login
- Edit the configuration in the
terraform.tfvars
file to match your account. - Initialize the Terraform workspace:
terraform init
Provision
Now deploy the infra.
terraform apply
Configure Kubectl
gcloud container clusters get-credentials $(terraform output -raw kubernetes_cluster_name) --region $(terraform output -raw region) --project $(terraform output -raw project_id)
You may need to install gke-gcloud-auth-plugin to gain access to the cluster.
Install Helix
Now you’re ready to install Helix.
1. Install Keycloak
Helix uses Keycloak for authentication. If you have one already, you can skip this step. Otherwise, to install one through Helm (chart info, repo). This step installs our Keycloak image with the Helix theme installed.
For example:
HELIX_VERSION=$(curl -s https://get.helixml.tech/latest.txt)
helm upgrade --install keycloak oci://registry-1.docker.io/bitnamicharts/keycloak \
--version "24.3.1" \
--set global.security.allowInsecureImages=true \
--set image.registry=registry.helixml.tech \
--set image.repository=helix/keycloak-bitnami \
--set image.tag="${HELIX_VERSION}" \
--set auth.adminUser=admin \
--set auth.adminPassword=oh-hallo-insecure-password \
--set httpRelativePath="/auth/"
Note: Helix includes a custom Keycloak image with the Helix theme pre-installed. Helix will also work with a standard Keycloak install.
Note the pinned version of the chart and the image tag. These are versions that we have tested and are known to work. Newer versions may work, but we have not tested them. Raise an issue if you have any issues.
You do not need to expose a service to access Keycloak from outside the cluster - it is used as an internal implementation detail of Helix (and Helix manages the helix
Keycloak realm via admin access).
Wait until the Keycloak is running:
kubectl get pods
NAME READY STATUS RESTARTS AGE
keycloak-0 0/1 Running 0 61s
keycloak-postgresql-0 1/1 Running 0 61s
Both pods should turn 1/1 running.
Using an External PostgreSQL Database
Keycloak uses PostgreSQL to persist state. If you want to reuse a pre-existing PostgreSQL cluster, please add the following settings:
--set postgresql.enabled=false \
--set externalDatabase.existingSecret=helix-external-postgres-app \
--set externalDatabase.existingSecretHostKey=host \
--set externalDatabase.existingSecretPortKey=port \
--set externalDatabase.existingSecretUserKey=user \
--set externalDatabase.existingSecretDatabaseKey=dbname \
--set externalDatabase.existingSecretPasswordKey=password \
This assumes that the helix-external-postgres-app
exists with the expected secrets.
2. Install the Helm Repository
helm repo add helix https://charts.helixml.tech
helm repo update
3. Apply the Chart
Use the license key from the license manager and create a secret with the contents:
kubectl create \
secret generic helix-license \
--from-literal=license="<base64 encoded secret contents here>"
Copy the values-example.yaml from the repository to configure the Helix control plane. You can look at the configuration documentation to learn more about what they do.
curl -o values-example.yaml https://raw.githubusercontent.com/helixml/helix/main/charts/helix-controlplane/values-example.yaml
You must edit the provider configuration in this file so that Helix can run. Specifying a remote provider (e.g. openai
or togetherai
) is the easiest, but you must provide API keys to do that. A helix
provider ensures local operation but then you must also add a runner.
Now you’re ready to install the control plane helm chart with the latest images.
export LATEST_RELEASE=$(curl -s https://get.helixml.tech/latest.txt)
helm upgrade --install my-helix-controlplane helix/helix-controlplane \
-f values-example.yaml \
--set image.tag="${LATEST_RELEASE}"
Ensure all the pods start. If they do not inspect the logs.
Once they are all running, access the control plane via port-forwarding (default) or according to your configuration, for example:
kubectl port-forward svc/helix-helix-controlplane 8080:80
You can configure the Kubernetes deployment by overriding the settings in the values.yaml.
Database Configuration
Helix requires PostgreSQL for application data and optionally PostgreSQL with the PGVector extension for RAG (Retrieval-Augmented Generation) functionality. You can use vanilla PostgreSQL for the main database and PostgreSQL with the PGVector extension for vectors. Both configurations support bundled deployment or external connection with comprehensive secret support.
PostgreSQL Configuration
Bundled PostgreSQL (default):
postgresql:
enabled: true
auth:
username: helix
password: "secure-password"
database: helix
# Optional: Use existing secret
# existingSecret: "postgresql-auth-secret"
# usernameKey: "username" # defaults to "username"
# passwordKey: "password" # defaults to "password"
# databaseKey: "database" # defaults to "database"
External PostgreSQL:
postgresql:
enabled: false
external:
host: "my-postgres.example.com"
port: 5432
user: "helix"
password: "secure-password"
database: "helix"
# Optional: Use existing secret
# existingSecret: "postgresql-external-secret"
# existingSecretHostKey: "host"
# existingSecretUserKey: "user"
# existingSecretPasswordKey: "password"
# existingSecretDatabaseKey: "database"
PostgreSQL with PGVector Extension Configuration (for RAG)
Bundled PostgreSQL with PGVector:
pgvector:
enabled: true
auth:
username: postgres
password: "secure-password"
database: postgres
# Optional: Use existing secret
# existingSecret: "pgvector-auth-secret"
# usernameKey: "username" # defaults to "username"
# passwordKey: "password" # defaults to "password"
# databaseKey: "database" # defaults to "database"
External PostgreSQL with PGVector:
pgvector:
enabled: false
external:
host: "my-pgvector.example.com"
port: 5432
user: "postgres"
password: "secure-password"
database: "postgres"
# Optional: Use existing secret
# existingSecret: "pgvector-external-secret"
# existingSecretHostKey: "host"
# existingSecretUserKey: "user"
# existingSecretPasswordKey: "password"
# existingSecretDatabaseKey: "database"
Important: External PostgreSQL with PGVector must have the vector
, vectorchord
, and vectorchord-bm25
extensions installed. The bundled PostgreSQL with PGVector uses an image which includes all required extensions.
Database Secrets Management
For production deployments, use Kubernetes secrets instead of plain text passwords:
# Create PostgreSQL secret
kubectl create secret generic postgresql-auth-secret \
--from-literal=username=helix \
--from-literal=password=secure-password \
--from-literal=database=helix
# Create PostgreSQL with PGVector secret
kubectl create secret generic pgvector-auth-secret \
--from-literal=username=postgres \
--from-literal=password=secure-password \
--from-literal=database=postgres
# Create controlplane secrets
kubectl create secret generic runner-token-secret \
--from-literal=token=your-secure-runner-token-here
kubectl create secret generic keycloak-auth-secret \
--from-literal=user=admin \
--from-literal=password=your-secure-keycloak-admin-password
# Create provider API key secrets
kubectl create secret generic openai-credentials \
--from-literal=api-key=sk-your-openai-api-key
kubectl create secret generic anthropic-credentials \
--from-literal=api-key=sk-ant-your-anthropic-api-key
kubectl create secret generic together-credentials \
--from-literal=api-key=your-together-api-key
kubectl create secret generic vllm-credentials \
--from-literal=api-key=your-vllm-api-key
4. Deploying a Runner
Here is some useful information when you configure the runner:
- the default GPU type in the
terraform.tfvars
is an L4 with 24GB GPU ram. So--set runner.memory=24GB
. - by default there’s a single node with a GPU. So install everything on the same node (no selector) and
--set replicaCount=1
For example:
export LATEST_RELEASE=$(curl -s https://get.helixml.tech/latest.txt)
helm upgrade --install my-helix-runner helix/helix-runner \
--set runner.host="http://my-helix-controlplane" \
--set runner.token="oh-hallo-insecure-token" \
--set runner.memory=24GB \
--set replicaCount=1 \
--set runner.axolotl="false" \
--set image.tag="${LATEST_RELEASE}-small"
If you want to schedule the runner to run on certain nodes, then please set the nodeSelector
. Change the label to match the value shown in the output of kubectl describe node
.
--set nodeSelector."nvidia\.com/gpu\.product"="NVIDIA-A100-SXM4-40GB"
Access Helix
The default kubernetes installation is locked down. You can access Helix via port-forwarding from your machine.
kubectl port-forward svc/my-helix-controlplane 8080:80
And visit: http://localhost:8080/
Take a look at the user documentation to learn how to use Helix.
Delete the Cluster
terraform destroy