This guide covers installation on both local Kind clusters and OpenShift environments.
- Prerequisites
- Kind Installation (Local Development)
- OpenShift Installation
- Accessing the UI
- Verifying the Installation
| Tool | Version | Purpose |
|---|---|---|
| kubectl | ≥1.32.1 | Kubernetes CLI |
| Helm | ≥3.18.0, <4 | Package manager for Kubernetes |
| git | ≥2.48.0 | Cloning repositories |
If you're setting up a brand-new Mac, install all prerequisites at once with Homebrew:
# Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install required tools
brew install git kind kubectl helm@3
# Verify Helm version meets the ≥3.18.0 requirement above
helm version
# Container runtime — pick one:
brew install podman # recommended for macOS
# or: brew install --cask docker # Docker Desktop
# If using Podman, create and start a machine with sufficient resources:
podman machine init --memory 18432 --cpus 4
podman machine start| Tool | Purpose |
|---|---|
| Docker Desktop / Rancher Desktop / Podman | Container runtime (16GB RAM, 4 cores recommended) |
| Kind | Local Kubernetes cluster |
| Ollama | Local LLM inference |
| GitHub Token | (Optional) Only needed to deploy agents/tools from private GitHub repos or pull from private registries. Recommended scopes: repo for private repositories and read:packages for private registries (e.g., GHCR). |
| Tool | Purpose |
|---|---|
| oc | ≥4.16.0 (OpenShift CLI) |
| OpenShift cluster | Admin access required (tested with OpenShift 4.19) |
# Clone the repository
git clone https://github.com/kagenti/kagenti.git
cd kagentiThe bash installer (scripts/kind/setup-kagenti.sh) is a composable, single-file
script that creates a Kind cluster and deploys Kagenti. Core components are always
installed; optional layers are enabled with --with-* flags.
Core (always installed): cert-manager, Gateway API CRDs, Istio Gateway controller (istio-base + istiod), Keycloak, kagenti-operator, kagenti-webhook
Install everything:
scripts/kind/setup-kagenti.sh --with-allInstall only what you need:
# Core + Istio ambient + UI
scripts/kind/setup-kagenti.sh --with-istio --with-ui
# Core + full service mesh + builds
scripts/kind/setup-kagenti.sh --with-istio --with-spire --with-buildsAvailable --with-* flags:
| Flag | Components |
|---|---|
--with-istio |
Full Istio ambient mesh (mTLS, waypoints); Gateway API controller always installed as core |
--with-spire |
SPIRE + SPIFFE IdP setup |
--with-backend |
Kagenti backend API |
--with-ui |
Kagenti UI (auto-enables backend) |
--with-mcp-gateway |
MCP Gateway |
--with-kuadrant |
Kuadrant operator (auto-enables MCP Gateway) |
--with-otel |
OpenTelemetry collector |
--with-mlflow |
MLflow trace backend (auto-enables OTel + Istio ambient) |
--with-builds |
Tekton + Shipwright (build agents from source) |
--with-kiali |
Kiali + Prometheus (auto-enables Istio ambient) |
--with-all |
All of the above |
Other options:
| Flag | Description |
|---|---|
--skip-cluster |
Reuse an existing Kind cluster |
--secrets-file FILE |
YAML file with secrets (see below) |
--cluster-name NAME |
Kind cluster name (default: kagenti) |
--domain DOMAIN |
Domain for services (default: localtest.me) |
--dry-run |
Show commands without executing |
Create a secrets file from the template:
cp charts/kagenti/.secrets_template.yaml charts/kagenti/.secrets.yaml
# Edit .secrets.yaml with your valuesPass it to the installer:
scripts/kind/setup-kagenti.sh --with-all --secrets-file charts/kagenti/.secrets.yamlIf --secrets-file is not specified, the installer automatically uses
charts/kagenti/.secrets.yaml when it exists.
To uninstall Kagenti from a Kind cluster:
# Uninstall platform, keep cluster
scripts/kind/cleanup-kagenti.sh
# Uninstall platform and destroy cluster
scripts/kind/cleanup-kagenti.sh --destroy-clusterIf you have an existing Kind cluster:
scripts/kind/setup-kagenti.sh --skip-cluster --with-allFor non-Kind clusters, use the Ansible-based installer or the OpenShift installation instructions.
Deprecated: The Ansible-based installer for Kind is deprecated and will be removed in a future release. Use the Bash Installer above instead. The Ansible installer remains supported for OpenShift installations. See migration epic #1266 for details.
Ansible-based installer instructions (click to expand)
# Install additional prerequisites
brew install ansible uv python@3.11 # macOS
# Copy and configure secrets
cp deployments/envs/secret_values.yaml.example deployments/envs/.secret_values.yaml
# Edit .secret_values.yaml with your values
# Run installer
deployments/ansible/run-install.sh --env devSee Ansible README for details and override files.
Note: OpenShift support is work in progress. Current limitations:
- Only quay.io registry tested for build-from-source
Both Ollama (local models) and OpenAI are supported as LLM backends. See the Local Models Guide for setup details.
Kagenti installs its own Cert Manager. Remove any existing installation:
# Check if cert-manager exists
kubectl get all -n cert-manager-operator
kubectl get all -n cert-managerIf present, uninstall via OpenShift Console:
- Go to Operators > Installed Operators
- Find cert-manager Operator for Red Hat OpenShift
- Click ⋮ → Uninstall Operator
Then clean up:
kubectl delete deploy cert-manager cert-manager-cainjector cert-manager-webhook -n cert-manager
kubectl delete service cert-manager cert-manager-cainjector cert-manager-webhook -n cert-manager
kubectl delete ns cert-manager-operator cert-managerCheck your network type:
kubectl describe network.config/clusterIf using OVNKubernetes, enable local gateway mode:
kubectl patch network.operator.openshift.io cluster --type=merge \
-p '{"spec":{"defaultNetwork":{"ovnKubernetesConfig":{"gatewayConfig":{"routingViaHost":true}}}}}'export DOMAIN=apps.$(kubectl get dns cluster -o jsonpath='{ .spec.baseDomain }')# Get latest version
LATEST_TAG=$(git ls-remote --tags --sort="v:refname" https://github.com/kagenti/kagenti.git | tail -n1 | sed 's|.*refs/tags/v||; s/\^{}//')
# Prepare secrets
# Download .secrets_template.yaml from https://github.com/kagenti/kagenti/blob/main/charts/kagenti/.secrets_template.yaml
# Save as .secrets.yaml and fill in required values
# Install dependencies
helm install --create-namespace -n kagenti-system kagenti-deps \
oci://ghcr.io/kagenti/kagenti/kagenti-deps \
--version $LATEST_TAG \
--set spire.trustDomain=${DOMAIN}
# Install MCP Gateway
LATEST_GATEWAY_TAG=$(skopeo list-tags docker://ghcr.io/kagenti/charts/mcp-gateway | jq -r '.Tags[-1]')
helm install mcp-gateway oci://ghcr.io/kagenti/charts/mcp-gateway \
--create-namespace --namespace mcp-system \
--version $LATEST_GATEWAY_TAG
# Install Kagenti (with OpenShift CA workaround)
helm upgrade --install --create-namespace -n kagenti-system \
-f .secrets.yaml kagenti oci://ghcr.io/kagenti/kagenti/kagenti \
--version $LATEST_TAG \
--set agentOAuthSecret.spiffePrefix=spiffe://${DOMAIN}/sa \
--set uiOAuthSecret.useServiceAccountCA=false \
--set agentOAuthSecret.useServiceAccountCA=false# Clone repository
git clone https://github.com/kagenti/kagenti.git
cd kagenti
# Prepare secrets
cp charts/kagenti/.secrets_template.yaml charts/kagenti/.secrets.yaml
# Edit .secrets.yaml with your values
# Update chart dependencies
helm dependency update ./charts/kagenti-deps/
helm dependency update ./charts/kagenti/
# Install dependencies
helm install kagenti-deps ./charts/kagenti-deps/ \
-n kagenti-system --create-namespace \
--set spire.trustDomain=${DOMAIN} --wait
# Install MCP Gateway
helm install mcp-gateway oci://ghcr.io/kagenti/charts/mcp-gateway \
--create-namespace --namespace mcp-system --version 0.4.0
# Get latest UI tag
LATEST_TAG=$(git ls-remote --tags --sort="v:refname" https://github.com/kagenti/kagenti.git | tail -n1 | sed 's|.*refs/tags/||; s/\^{}//')
# Install Kagenti (with OpenShift CA workaround)
helm upgrade --install kagenti ./charts/kagenti/ \
-n kagenti-system --create-namespace \
-f ./charts/kagenti/.secrets.yaml \
--set ui.tag=${LATEST_TAG} \
--set agentOAuthSecret.spiffePrefix=spiffe://${DOMAIN}/sa \
--set uiOAuthSecret.useServiceAccountCA=false \
--set agentOAuthSecret.useServiceAccountCA=false# Configure secrets
cp deployments/envs/secret_values.yaml.example deployments/envs/.secret_values.yaml
# Edit .secret_values.yaml
# Run installer for OpenShift
deployments/ansible/run-install.sh --env ocpkubectl get daemonsets -n zero-trust-workload-identity-managerIf Current or Ready is 0, see Troubleshooting.
open http://kagenti-ui.localtest.me:8080echo "https://$(kubectl get route kagenti-ui -n kagenti-system -o jsonpath='{.status.ingress[0].host}')"If using self-signed certificates, accept the certificate in your browser.
For MCP Inspector, also accept the proxy certificate:
echo "https://$(kubectl get route mcp-proxy -n kagenti-system -o jsonpath='{.status.ingress[0].host}')"Run the following script to display all service URLs and credentials:
./.github/scripts/local-setup/show-services.shFor OpenShift, Keycloak admin credentials can also be retrieved directly:
kubectl get secret keycloak-initial-admin -n keycloak \
-o go-template='Username: {{.data.username | base64decode}} Password: {{.data.password | base64decode}}{{"\n"}}'The AuthBridge stack (separate sidecars or a single combined authbridge container) needs Keycloak admin credentials for automatic OAuth2 client registration. These credentials are stored in a Kubernetes Secret called keycloak-admin-secret in each agent namespace.
The installer automatically creates keycloak-admin-secret in every agent namespace (e.g., team1, team2). By default it uses admin/admin, matching the default Keycloak admin account.
If your Keycloak admin credentials differ from the defaults, override them using a values file (preferred over --set to avoid exposing passwords in shell history and process listings):
Ansible installer (via .secret_values.yaml):
Add to your deployments/envs/.secret_values.yaml:
charts:
kagenti:
values:
keycloak:
adminUsername: myadmin
adminPassword: mypasswordHelm install (via values file):
helm upgrade --install kagenti ./charts/kagenti/ \
-n kagenti-system --create-namespace \
-f my-secret-values.yamlIf you already manage Keycloak admin credentials in a Secret (e.g., via an external secrets operator), you can skip the automatic secret creation entirely by setting keycloak.adminExistingSecret to the name of that secret. The referenced secret must contain KEYCLOAK_ADMIN_USERNAME and KEYCLOAK_ADMIN_PASSWORD keys:
helm upgrade --install kagenti ./charts/kagenti/ \
-n kagenti-system --create-namespace \
--set keycloak.adminExistingSecret=my-keycloak-admin-secretIf you need to create or update the secret manually in an agent namespace:
kubectl create secret generic keycloak-admin-secret -n <agent-namespace> \
--from-literal=KEYCLOAK_ADMIN_USERNAME=admin \
--from-literal=KEYCLOAK_ADMIN_PASSWORD=admin \
--dry-run=client -o yaml | kubectl apply -f -kubectl get secret keycloak-admin-secret -n team1Security note: For production deployments, use a dedicated Keycloak service account with limited permissions instead of the admin account. See the Identity Guide for details.
# SPIRE OIDC (Kind)
curl http://spire-oidc.localtest.me:8080/keys
curl http://spire.localtest.me:8080/.well-known/openid-configuration
# Tornjak API
curl http://spire-tornjak-api.localtest.me:8080/
# Expected: "Welcome to the Tornjak Backend!"
# Tornjak UI
open http://spire-tornjak-ui.localtest.me:8080/open http://keycloak.localtest.me:8080/
# Login: see .github/scripts/local-setup/show-services.sh output for credentialsFrom the UI you can:
- Import and deploy A2A agents from any framework
- Deploy MCP tools directly from source
- Test agents interactively
- Monitor traces and network traffic
If daemonsets show Current=0 or Ready=0:
kubectl describe daemonsets -n zero-trust-workload-identity-manager spire-agent
kubectl describe daemonsets -n zero-trust-workload-identity-manager spire-spiffe-csi-driverIf you see SCC (Security Context Constraint) errors:
oc adm policy add-scc-to-user privileged -z spire-agent -n zero-trust-workload-identity-manager
kubectl rollout restart daemonsets -n zero-trust-workload-identity-manager spire-agent
oc adm policy add-scc-to-user privileged -z spire-spiffe-csi-driver -n zero-trust-workload-identity-manager
kubectl rollout restart daemonsets -n zero-trust-workload-identity-manager spire-spiffe-csi-driverRed Hat OpenShift Container Platform (AWS)
# Update channel
oc patch clusterversion version --type merge -p '{"spec":{"channel":"fast-4.19"}}'
# Acknowledge changes
oc -n openshift-config patch cm admin-acks --patch '{"data":{"ack-4.18-kube-1.32-api-removals-in-4.19":"true"}}' --type=merge
oc -n openshift-config patch cm admin-acks --patch '{"data":{"ack-4.18-boot-image-opt-out-in-4.19":"true"}}' --type=merge
# Upgrade
oc adm upgrade --to-latest=true --allow-not-recommended=true
# Monitor
oc get clusterversionFor more troubleshooting tips, see Troubleshooting Guide.