{
  "schema_version": 2,
  "id": "operate/iris/self-managed",
  "title": "Install the Redis Iris suite",
  "url": "https://redis.io/docs/latest/operate/iris/self-managed/",
  "summary": "Install the Identity Service, the Redis Iris services, and the Iris console on Kubernetes as one Helm release.",
  "tags": [
    "docs",
    "operate",
    "iris"
  ],
  "last_updated": "2026-11-03T16:45:14-08:00",
  "children": [],
  "page_type": "content",
  "content_hash": "640ff6b6eef861c74468aff0941a1d211c1354436825319dca7fd7200ff97dea",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "The `redis-iris` Helm chart installs the Identity Service, the Redis Iris services you choose, and the Iris console as one release. It's the supported way to run Redis Iris on your own Kubernetes cluster. The product charts that each service guide describes, such as `redis-agent-memory` and `iris-identity-service`, are published as dependencies of this chart. Installing one on its own isn't a supported install path.\n\n> [!NOTE]\n> You need a Redis Iris suite license. Contact your Redis representative or\n> [contact sales](https://redis.io/contact/)."
    },
    {
      "id": "what-you-deploy",
      "title": "What you deploy",
      "role": "content",
      "text": "The chart installs every component under a fixed name in the release namespace, whatever you call the release, so the components reach each other by Service name.\n\n| Component | Values key | Services | Installed when |\n| --- | --- | --- | --- |\n| Identity Service | `identityService` | `iris-identity-service` (`9200`) | Always |\n| [Agent Memory](https://redis.io/docs/latest/operate/iris/agent-memory/self-managed) | `memory` | `redis-agent-memory` (`9000`), `redis-agent-memory-controlplane` (`9100`) | `global.iris.products.memory.enabled` |\n| [Agent Playbooks](https://redis.io/docs/latest/operate/iris/agent-playbook/self-managed) | `playbook` | `redis-agent-playbook-controlplane` (`9200`), `redis-agent-playbook-dataplane` (`9201`) | `global.iris.products.playbook.enabled` |\n| [Lens](https://redis.io/docs/latest/operate/iris/lens/self-managed) | `lens` | `redis-lens-dataplane` (`9000`), `redis-lens-controlplane` (`9300`) | `global.iris.products.lens.enabled` |\n| [Context Gateway](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed) | `contextGateway` | `redis-context-gateway-controlplane` (`9100`), `redis-context-gateway-dataplane` (`8083`) | `global.iris.products.contextGateway.enabled` |\n| [Intent Router](https://redis.io/docs/latest/operate/iris/intent-router/self-managed) | `intent` | `redis-intent-router-controlplane` (`9400`), `redis-intent-router-dataplane` (`9401`) | `global.iris.products.intent.enabled` |\n| Iris console | `ui` | `iris-ui` | Always |\n\nEvery service is on by default. Set `enabled: false` for each one you don't install. A disabled service needs none of its values.\n\nInstall one release per namespace, and keep other Iris releases out of that namespace. The release is one tenant."
    },
    {
      "id": "prerequisites",
      "title": "Prerequisites",
      "role": "content",
      "text": "| Requirement | Details |\n| --- | --- |\n| Kubernetes | Kubernetes 1.28 or later. The baseline is 3 worker nodes with 12 vCPU and 24 GiB allocatable in total. The [preflight](#4-run-the-preflight) warns below it. |\n| Metrics API | `metrics.k8s.io/v1beta1`, so the HorizontalPodAutoscalers can scale. |\n| Helm | Helm 3.10 or later, with the Redis AI repository `https://helm.redis.io/ai`. Helm 4 isn't supported in this release. |\n| `kubectl` | Configured for the cluster and namespace. |\n| License | One suite license that covers every service you install. |\n| Redis databases | A metadata Redis for the Identity Service, plus the databases each service guide lists. |\n| Identity provider (IdP) | An OpenID Connect (OIDC) IdP for operator sign-in to the console and the control planes, with a confidential client for the console. To start without one, see [Admin token mode](#admin-token-mode). |\n| Ingress | An ingress controller, a host name for the console, and a Transport Layer Security (TLS) Secret for that host. |"
    },
    {
      "id": "1-create-the-namespace",
      "title": "1. Create the namespace",
      "role": "content",
      "text": "[code example]"
    },
    {
      "id": "2-create-the-shared-secrets",
      "title": "2. Create the shared Secrets",
      "role": "content",
      "text": "Create these Secrets in the release namespace. Each service guide lists that service's own Secrets in its suite section.\n\n| Secret | Key | Holds |\n| --- | --- | --- |\n| `iris-license` | `license.key` | The suite license. |\n| `ids-metadata` | `metadata.yaml` | The Identity Service metadata Redis connection. See [Create the metadata Secret](https://redis.io/docs/latest/operate/iris/identity-service/deploy#2-create-the-metadata-secret). |\n| `cluster-ca` | `ca.crt` | The certificate authority (CA) bundle every component trusts: the cluster CA from the `kube-root-ca.crt` ConfigMap, plus any private CA your Redis or IdP uses. |\n| `iris-ui-oidc` | `client-secret` | The console's client secret at your IdP. Register the redirect URI `<public-url>/auth/callback`. |\n| `ui-session-redis` | `urls` | The Redis URL for console sessions. |\n| `iris-tls` | `tls.crt`, `tls.key` | The TLS certificate for the console host. |\n\n[code example]\n\nThe chart generates every credential the components share, including each service's admin token. See [Credentials](#credentials)."
    },
    {
      "id": "3-write-iris-valuesyaml",
      "title": "3. Write `iris-values.yaml`",
      "role": "content",
      "text": "Set the values the services share once, under `global`. The services derive their tenant, license, CA trust, OIDC settings, and Identity Service wiring from them. A service value that differs from a derived one fails the render and names the field.\n\n[code example]\n\n| Value | Default | Meaning |\n| --- | --- | --- |\n| `global.iris.tenantId` | `default` | The release's one tenant. You can't change it later. |\n| `global.iris.license.existingSecret`, `global.iris.license.secretKey` | `iris-license`, `license.key` | The suite license Secret. |\n| `global.iris.publicURL` | None | The console's public origin. |\n| `global.iris.ingress.className`, `global.iris.ingress.tls.secretName` | None | The console Ingress class and TLS Secret. |\n| `global.iris.auth.oidc.issuer`, `global.iris.auth.oidc.jwksURI` | None | The IdP, set once for the console, every control plane, and the Identity Service. |\n| `global.iris.auth.oidc.audience` | `api://redis-iris` | The audience in operator access tokens. |\n| `global.iris.auth.oidc.roleClaims` | `[groups]` | The token claims that carry IdP groups. |\n| `global.iris.auth.roleBindings` | `[]` | IdP group to Iris role. `suite_admin` takes no `product`. `product_admin`, `operator`, and `viewer` take a `product`: `agent_memory`, `playbook`, `lens`, `context_gateway`, `intent`, or `identity`. |\n| `global.iris.workloadIdentity.issuer`, `global.iris.workloadIdentity.jwksURI` | The in-cluster API server | The ServiceAccount token issuer the Memory and Playbooks workers are verified against. On Amazon EKS, set both to the cluster's OIDC issuer. |\n| `global.iris.extraction.enabled` | `false` | Agent Playbooks FAQ extraction from Agent Memory. See [Extraction with the Redis Iris suite chart](https://redis.io/docs/latest/operate/iris/agent-playbook/self-managed/extraction#extraction-with-the-redis-iris-suite-chart). |\n| `global.tls.caCertSecret` | `\"\"` | The CA bundle Secret every component trusts. |\n\nThen add each service's values under its key, as its guide describes:\n\n- [Agent Memory](https://redis.io/docs/latest/operate/iris/agent-memory/self-managed/deploy#install-with-the-redis-iris-suite-chart), under `memory:`\n- [Agent Playbooks](https://redis.io/docs/latest/operate/iris/agent-playbook/self-managed/deploy#install-with-the-redis-iris-suite-chart), under `playbook:`\n- [Lens](https://redis.io/docs/latest/operate/iris/lens/self-managed/deploy#install-with-the-redis-iris-suite-chart), under `lens:`\n- [Context Gateway](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/deploy#install-with-the-redis-iris-suite-chart), under `contextGateway:`\n- [Intent Router](https://redis.io/docs/latest/operate/iris/intent-router/self-managed/deploy#install-with-the-redis-iris-suite-chart), under `intent:`"
    },
    {
      "id": "admin-token-mode",
      "title": "Admin token mode",
      "role": "content",
      "text": "Without an IdP, turn off console sign-in and the console Ingress. Operators then paste each service's admin token into the console, and `publicURL`, `ingress`, and `auth.oidc` aren't needed:\n\n[code example]\n\nUse admin token mode for evaluation, or as the break-glass path when your IdP is unavailable."
    },
    {
      "id": "4-run-the-preflight",
      "title": "4. Run the preflight",
      "role": "content",
      "text": "The chart includes a preflight that checks the Kubernetes version, baseline sizing, the Metrics API, the console's IngressClass, and that the workload identity issuer is reachable. Run it with the [`kubectl preflight`](https://troubleshoot.sh/docs/#installation) plugin, v0.124.0 or later:\n\n[code example]\n\nOn clusters that refuse anonymous access to the ServiceAccount issuer, such as kubeadm clusters, the workload identity check fails and prints the binding to create. The chart creates no cluster-scoped permissions:\n\n[code example]"
    },
    {
      "id": "5-install",
      "title": "5. Install",
      "role": "content",
      "text": "[code example]\n\nA missing or conflicting value fails the install and names the field to fix."
    },
    {
      "id": "6-verify-the-release",
      "title": "6. Verify the release",
      "role": "content",
      "text": "[code example]\n\nFor each installed service, the test creates a resource with the admin token, mints a scoped agent key, calls the data plane with it, calls the console, and then removes what it created. It creates its temporary Agent Memory store in Memory database `1`. If your Memory `databases` registry uses another key, set `tests.suiteVerify.databaseId`."
    },
    {
      "id": "credentials",
      "title": "Credentials",
      "role": "content",
      "text": "By default, the chart generates every shared credential once, as Secrets it keeps across upgrades, rollbacks, and uninstalls.\n\n| Secret | Key | Used by |\n| --- | --- | --- |\n| `iris-<service>-dataplane-credential` | `<service>-dp` | The service's data plane and the Identity Service |\n| `iris-<service>-internal-token` | `<service>` | The service's control plane and the Identity Service |\n| `iris-<service>-admin-token` | `token` | The service's admin API |\n| `iris-identity-service-control-token` | `token` | The Identity Service control API |\n| `iris-ui-session-key` | `key` | Console sessions, with `ui.sso.enabled` |\n\n`<service>` is `memory`, `playbook`, `lens`, `context-gateway`, or `intent`. Read an admin token with:\n\n[code example]\n\nTo rotate a credential, change its Secret in place. A rollback never restores an old value. To start over after `helm uninstall`, delete the Secrets yourself:\n\n[code example]\n\nTo supply your own credentials, for example for an offline render with Argo CD or Flux, set `global.iris.renderMode: gitops` and `global.iris.secrets.generate: false`. Then name two Secrets: `global.iris.secrets.dataplaneServiceCredentials.existingSecret`, with a `<service>-dp` key for each installed service, and `global.iris.secrets.controlplaneInternalTokens.existingSecret`, with a `<service>` key for each."
    },
    {
      "id": "availability",
      "title": "Availability",
      "role": "content",
      "text": "The chart runs two replicas of the Identity Service, the console, and every data plane, and one of each control plane. Data planes roll one surge pod at a time and remove an old pod only when the new one is ready, so leave room for one extra pod. Every Deployment with more than one replica gets a PodDisruptionBudget with `maxUnavailable: 1`. The rollout strategy and the PodDisruptionBudgets are fixed. Replica counts are yours to size."
    },
    {
      "id": "move-from-a-preview-or-standalone-install",
      "title": "Move from a preview or standalone install",
      "role": "content",
      "text": "Upgrading to `redis-iris` from preview charts (`0.x`) or from product charts installed on their own isn't supported. Reinstall instead, against the same Redis databases:\n\n1. Record your values.\n1. Run `helm uninstall` for every Iris release in the namespace.\n1. Write `iris-values.yaml` with the same Redis Secrets, and install `redis-iris`.\n\nData in those databases is kept, except from Agent Memory `0.0.x` and Agent Playbooks `0.1.x` previews, which can't be upgraded. Expect a few minutes of downtime."
    },
    {
      "id": "not-supported-in-this-release",
      "title": "Not supported in this release",
      "role": "content",
      "text": "| Feature | Status |\n| --- | --- |\n| FIPS profile (`global.security.profile: fips`) | The install fails. Planned for `1.1`. |\n| Helm 4 | Planned for `1.1`. |\n| Standalone product chart installs | Published as dependencies of `redis-iris` only. |"
    }
  ],
  "examples": [
    {
      "id": "1-create-the-namespace-ex0",
      "language": "bash",
      "code": "kubectl create namespace <namespace-name>",
      "section_id": "1-create-the-namespace"
    },
    {
      "id": "2-create-the-shared-secrets-ex0",
      "language": "bash",
      "code": "kubectl -n <namespace-name> create secret generic iris-license \\\n  --from-file=license.key=./license.key",
      "section_id": "2-create-the-shared-secrets"
    },
    {
      "id": "3-write-iris-valuesyaml-ex0",
      "language": "yaml",
      "code": "global:\n  tls:\n    caCertSecret: cluster-ca\n  iris:\n    tenantId: default\n    license:\n      existingSecret: iris-license\n    publicURL: https://<console-host>\n    ingress:\n      className: <ingress-class>\n      tls:\n        secretName: iris-tls\n    auth:\n      oidc:\n        issuer: https://<idp-host>/<issuer-path>\n        jwksURI: https://<idp-host>/<jwks-path>\n      roleBindings:\n        - { group: <admin-group>, role: suite_admin }\n        - { group: <memory-operators-group>, role: operator, product: agent_memory }\n    products:\n      contextGateway:\n        enabled: false\n\nidentityService:\n  metadata:\n    existingSecret: ids-metadata\n\nui:\n  sso:\n    clientId: <console-client-id>\n    clientCredential:\n      existingSecret: iris-ui-oidc\n    redis:\n      existingSecret: ui-session-redis",
      "section_id": "3-write-iris-valuesyaml"
    },
    {
      "id": "admin-token-mode-ex0",
      "language": "yaml",
      "code": "ui:\n  sso:\n    enabled: false\n  ingress:\n    enabled: false",
      "section_id": "admin-token-mode"
    },
    {
      "id": "4-run-the-preflight-ex0",
      "language": "bash",
      "code": "helm template iris redis-ai/redis-iris --version 1.0.0 -n <namespace-name> -f iris-values.yaml \\\n  --show-only templates/preflight.yaml \\\n  | yq '.stringData[\"preflight.yaml\"]' | kubectl preflight -",
      "section_id": "4-run-the-preflight"
    },
    {
      "id": "4-run-the-preflight-ex1",
      "language": "bash",
      "code": "kubectl create clusterrolebinding <namespace-name>-issuer-discovery \\\n  --clusterrole=system:service-account-issuer-discovery --group=system:unauthenticated",
      "section_id": "4-run-the-preflight"
    },
    {
      "id": "5-install-ex0",
      "language": "bash",
      "code": "helm repo add redis-ai https://helm.redis.io/ai\nhelm repo update redis-ai\nhelm install iris redis-ai/redis-iris \\\n  --version 1.0.0 \\\n  --namespace <namespace-name> \\\n  -f iris-values.yaml",
      "section_id": "5-install"
    },
    {
      "id": "6-verify-the-release-ex0",
      "language": "bash",
      "code": "helm test iris --namespace <namespace-name> --logs",
      "section_id": "6-verify-the-release"
    },
    {
      "id": "credentials-ex0",
      "language": "bash",
      "code": "kubectl -n <namespace-name> get secret iris-memory-admin-token -o jsonpath='{.data.token}' | base64 -d",
      "section_id": "credentials"
    },
    {
      "id": "credentials-ex1",
      "language": "bash",
      "code": "kubectl -n <namespace-name> delete secret -l app.kubernetes.io/component=credentials,app.kubernetes.io/name=redis-iris",
      "section_id": "credentials"
    }
  ]
}
