{
  "schema_version": 2,
  "id": "operate/iris/context-gateway/self-managed/deploy",
  "title": "Deploy Redis Context Gateway",
  "url": "https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/deploy/",
  "summary": "Install Redis Context Gateway with an external Identity Service, then create a Gateway, mint an agent key, and make one authenticated call.",
  "tags": [
    "docs",
    "operate",
    "iris"
  ],
  "last_updated": "2026-11-03T16:45:14-08:00",
  "page_type": "content",
  "content_hash": "42dcba2126be86919d5805c2db1936323941819106876c5f12621823db4a312b",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "> [!NOTE]\n> For a supported install, see [Install with the Redis Iris suite chart](#install-with-the-redis-iris-suite-chart). The standalone steps on this page show what each value does.\n\nThese steps install the Context Gateway Control Plane and Data Plane with the `redis-context-gateway` Helm chart, and end with one authenticated Model Context Protocol (MCP) call.\n\nYou use three credentials along the way: the Control Plane admin token, the Identity Service control token, and an agent key. For what each credential unlocks, see [Credentials](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/authentication#credentials).\n\nBefore you begin, review the [prerequisites](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/prerequisites)."
    },
    {
      "id": "1-create-the-namespace",
      "title": "1. Create the namespace",
      "role": "content",
      "text": "[code example]"
    },
    {
      "id": "2-create-secrets",
      "title": "2. Create Secrets",
      "role": "content",
      "text": ""
    },
    {
      "id": "configure-the-identity-service-release-first",
      "title": "Configure the Identity Service release first",
      "role": "configuration",
      "text": "For every Identity Service setting, and for running one release that serves several products, see the [Identity Service guide](https://redis.io/docs/latest/operate/iris/identity-service).\n\nSet these values on the Identity Service release so that it checks Gateway grants and accepts the Data Plane's runtime token:\n\n| Identity Service value | Setting |\n| --- | --- |\n| `runtime.serviceCredentials[]` | A credential for the Data Plane, `name: context-gateway-dp` and `subject: context-gateway-dataplane`, with `allowedOperations: [api-key-introspect]` and `allowedProducts: [context-gateway]`, from the same Secret as `dataplane.runtimeToken`. With Data Plane sign-in on, add `subject-grant-lookup` to `allowedOperations`. |\n| `productValidation.products.context-gateway.baseURL` | The Control Plane Service, for example `http://gateway-redis-context-gateway-controlplane:9100`. |\n| `productValidation.products.context-gateway.credential` | The same Secret as `controlplane.internalToken`. |\n| `productValidation.products.context-gateway.enabled` | `true` |\n| `runtime.apiKeyTenant.singleTenantID` | The same value as `tenantId`. |\n\nIf the Identity Service release also serves Agent Memory or Agent Playbooks, add these entries to its existing lists."
    },
    {
      "id": "create-the-connection-files",
      "title": "Create the connection files",
      "role": "content",
      "text": "Save the Metadata Redis connection as `metadata.yaml`:\n\n[code example]\n\nSave the credential Redis connection as `credential-redis.yaml`:\n\n[code example]\n\nKeep real URLs and passwords only in these files, and create Secrets from them."
    },
    {
      "id": "create-the-secrets",
      "title": "Create the Secrets",
      "role": "content",
      "text": "[code example]\n\nCreate a `databaseConnections` Secret for the registered databases. See [Database registry](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/configuration#database-registry)."
    },
    {
      "id": "3-create-gateway-valuesyaml",
      "title": "3. Create `gateway-values.yaml`",
      "role": "content",
      "text": "Save this file, replacing the angle-bracket placeholders with your tenant and public Data Plane origin. The chart's default images match its version, so the file sets no image values. It uses the Secrets created in step 2 and an Identity Service release named `ids` in the same namespace.\n\n[code example]\n\nThis configuration starts without cache or compression. Add [registered databases](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/configuration#database-registry) and feature settings when you need them.\n\nWhen `identityService.baseURL` is an in-cluster `http://` address, such as `http://ids-iris-identity-service:9200` for an Identity Service release named `ids`, also set `identityService.allowInsecureTransport: true`."
    },
    {
      "id": "before-you-install-check-your-values",
      "title": "Before you install: check your values",
      "role": "content",
      "text": "Check each value in `gateway-values.yaml` before you install. If one is wrong, you see the symptom in its row.\n\n| Check | Symptom | Fix |\n| --- | --- | --- |\n| `tenantId` equals the Identity Service's `runtime.apiKeyTenant.singleTenantID` | Pods Ready, but minting an agent key for a Gateway fails | Set both to the same tenant. |\n| `publicBaseURL` is the Data Plane origin that MCP clients reach | `mcpEndpoint` in Gateway responses points to an address clients cannot reach, and identity provider sign-in fails | Set the public origin, including `https://`. |\n| `identityService.allowInsecureTransport` is `true` for an `http://` Identity Service URL | Rendering fails with `HTTP Identity Service requires explicit allowInsecureTransport`. | Set it, or use an `https://` URL. |\n| The admin, internal, and runtime tokens come from three different Secrets or keys | Rendering fails, or the Identity Service cannot check keys | Create three distinct token files. |\n| `license` points to a valid license | The Control Plane's `/health/readiness` answers `503`, and an invalid license stops either plane at startup | Mount the license file as issued. |\n| Any `image.repository` or `image.tag` override names an image your cluster can pull | Pods `ImagePullBackOff` | Remove the overrides to use the chart's default images, or mirror those images unchanged. |"
    },
    {
      "id": "4-install",
      "title": "4. Install",
      "role": "content",
      "text": "[code example]\n\nUse a published chart version. A merged server change does not by itself publish a chart or image."
    },
    {
      "id": "5-verify-pods-and-health",
      "title": "5. Verify pods and health",
      "role": "content",
      "text": "[code example]\n\nRun each port-forward in its own terminal and leave it running:\n\n[code example]\n\n[code example]\n\n[code example]\n\nThen check readiness on both planes:\n\n[code example]"
    },
    {
      "id": "6-create-a-gateway",
      "title": "6. Create a Gateway",
      "role": "content",
      "text": "[code example]\n\nThe response carries `gatewayId` (a `gw_`-prefixed ID) and `mcpEndpoint`. Use that ID in the grant in step 7. The advertised endpoint must be reachable from the shell that makes the MCP calls."
    },
    {
      "id": "7-mint-an-agent-key",
      "title": "7. Mint an agent key",
      "role": "content",
      "text": "[code example]\n\n> [!WARNING]\n> The response's `token` is the agent key. It is shown only once, so save it in your secret manager."
    },
    {
      "id": "8-make-one-authenticated-call",
      "title": "8. Make one authenticated call",
      "role": "content",
      "text": "Send an initialization request to the advertised endpoint. These commands use protocol version `2025-06-18`, which the Gateway supports.\n\n[code example]\n\nThe Gateway is stateless, so no session ID needs to be retained between these requests. A new full-mode Gateway with no Upstreams and compression off returns an empty tool list. Save the key in your secret manager, then remove `agent-key.json`."
    },
    {
      "id": "install-with-the-redis-iris-suite-chart",
      "title": "Install with the Redis Iris suite chart",
      "role": "setup",
      "text": "The `redis-iris` Helm chart installs Context Gateway with the Identity Service and the user interface (UI) in one release. Context Gateway is on by default, and `global.iris.products.contextGateway.enabled: false` leaves it out. Put the Context Gateway values under the `contextGateway:` key.\n\nThe suite derives these values from `global.iris` and registers Context Gateway with its Identity Service. Leave them unset under `contextGateway:`, because a value that differs fails the render:\n\n- `tenantId` and `license`\n- `identityService.baseURL` and `identityService.allowInsecureTransport`\n- `dataplane.runtimeToken` and `controlplane.internalToken`, which the suite supplies as Kubernetes Secrets\n- `controlplane.config.auth.oidc`, when `global.iris.auth.oidc` sets an issuer\n\nThe suite also fixes `fullnameOverride`, both `service.port` values, `dataplane.strategy`, and `podDisruptionBudget.enabled`. `tls.caBundle` defaults to `global.tls.caCertSecret`. The Data Plane defaults to two replicas, and `controlplane.adminToken` reads the `iris-context-gateway-admin-token` Secret, which the suite generates by default.\n\nYou set `publicBaseURL`, which must be an `https://` origin with no path, the metadata and credential storage references, and either `dataplane.ingress` or your own routing to `redis-context-gateway-dataplane:8083`:\n\n[code example]\n\n[code example]\n\nThe rest of this guide applies to the values under `contextGateway:`, except the Identity Service settings in step 2, which the suite configures. In the `kubectl` commands, use the suite's fixed names: `redis-context-gateway-controlplane`, `redis-context-gateway-dataplane`, and `iris-identity-service`."
    },
    {
      "id": "next-steps",
      "title": "Next steps",
      "role": "content",
      "text": "- [API examples](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/api-examples) to register an Upstream and hand off to a developer.\n- [Operations](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/operations) for credential rotation and upgrades."
    }
  ],
  "examples": [
    {
      "id": "1-create-the-namespace-ex0",
      "language": "bash",
      "code": "kubectl create namespace <namespace-name>",
      "section_id": "1-create-the-namespace"
    },
    {
      "id": "create-the-connection-files-ex0",
      "language": "yaml",
      "code": "metadata_db:\n  urls: [\"rediss://<metadata-user>:<password>@<metadata-host>:6379\"]",
      "section_id": "create-the-connection-files"
    },
    {
      "id": "create-the-connection-files-ex1",
      "language": "yaml",
      "code": "credential_storage:\n  redis:\n    urls: [\"rediss://<credential-user>:<password>@<credential-host>:6379\"]",
      "section_id": "create-the-connection-files"
    },
    {
      "id": "create-the-secrets-ex0",
      "language": "bash",
      "code": "umask 077\nopenssl rand -base64 32 > k1\nkubectl -n <namespace-name> create secret generic gateway-metadata --from-file=config.yaml=metadata.yaml\nkubectl -n <namespace-name> create secret generic gateway-credential-redis --from-file=config.yaml=credential-redis.yaml\nkubectl -n <namespace-name> create secret generic gateway-keyring --from-file=k1\nkubectl -n <namespace-name> create secret generic gateway-license --from-file=license=./license\nkubectl -n <namespace-name> create secret generic gateway-admin --from-file=token=./admin-token\nkubectl -n <namespace-name> create secret generic gateway-grant-validation --from-file=token=./grant-token\nkubectl -n <namespace-name> create secret generic gateway-runtime --from-file=token=./runtime-token",
      "section_id": "create-the-secrets"
    },
    {
      "id": "3-create-gateway-valuesyaml-ex0",
      "language": "yaml",
      "code": "tenantId: <tenant-id>\npublicBaseURL: https://<gateway-host>\nidentityService:\n  baseURL: http://ids-iris-identity-service:9200\n  allowInsecureTransport: true\nlicense:\n  existingSecret: gateway-license\nmetadataDB:\n  existingSecret: gateway-metadata\n  secretKey: config.yaml\ncredentialStorage:\n  provider: redis\n  redis:\n    connection:\n      existingSecret: gateway-credential-redis\n      secretKey: config.yaml\n    keyring:\n      existingSecret: gateway-keyring\n    keyFiles:\n      k1: k1\n    activeKeyId: k1\ncontrolplane:\n  adminToken:\n    existingSecret: gateway-admin\n    secretKey: token\n  internalToken:\n    existingSecret: gateway-grant-validation\n    secretKey: token\ndataplane:\n  runtimeToken:\n    existingSecret: gateway-runtime\n    secretKey: token",
      "section_id": "3-create-gateway-valuesyaml"
    },
    {
      "id": "4-install-ex0",
      "language": "bash",
      "code": "helm repo add redis-ai https://helm.redis.io/ai\nhelm repo update redis-ai\nhelm install gateway redis-ai/redis-context-gateway \\\n  --version 1.0.0 \\\n  --namespace <namespace-name> \\\n  -f gateway-values.yaml \\\n  --wait --timeout 5m",
      "section_id": "4-install"
    },
    {
      "id": "5-verify-pods-and-health-ex0",
      "language": "bash",
      "code": "kubectl -n <namespace-name> rollout status deployment/gateway-redis-context-gateway-controlplane\nkubectl -n <namespace-name> rollout status deployment/gateway-redis-context-gateway-dataplane",
      "section_id": "5-verify-pods-and-health"
    },
    {
      "id": "5-verify-pods-and-health-ex1",
      "language": "bash",
      "code": "kubectl -n <namespace-name> port-forward svc/gateway-redis-context-gateway-controlplane 9100:9100",
      "section_id": "5-verify-pods-and-health"
    },
    {
      "id": "5-verify-pods-and-health-ex2",
      "language": "bash",
      "code": "kubectl -n <namespace-name> port-forward svc/gateway-redis-context-gateway-dataplane 8083:8083",
      "section_id": "5-verify-pods-and-health"
    },
    {
      "id": "5-verify-pods-and-health-ex3",
      "language": "bash",
      "code": "kubectl -n <namespace-name> port-forward svc/ids-iris-identity-service 9200:9200",
      "section_id": "5-verify-pods-and-health"
    },
    {
      "id": "5-verify-pods-and-health-ex4",
      "language": "bash",
      "code": "curl -sS http://localhost:9100/health/readiness\ncurl -sS http://localhost:8083/health/readiness",
      "section_id": "5-verify-pods-and-health"
    },
    {
      "id": "6-create-a-gateway-ex0",
      "language": "bash",
      "code": "umask 077\ncurl --fail-with-body --silent --show-error \\\n  -X POST http://localhost:9100/iris/v1/context-gateway/gateways \\\n  -H \"Authorization: Bearer <admin-token>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\": \"my-gateway\", \"toolExposureMode\": \"FULL\"}' > gateway.json\nexport GATEWAY_ID=\"$(jq -er '.gatewayId' gateway.json)\"\nexport MCP_ENDPOINT=\"$(jq -er '.mcpEndpoint' gateway.json)\"",
      "section_id": "6-create-a-gateway"
    },
    {
      "id": "7-mint-an-agent-key-ex0",
      "language": "bash",
      "code": "jq -n --arg tenant '<tenant-id>' --arg gateway \"$GATEWAY_ID\" \\\n  '{name:\"my-agent-key\",grants:[{tenant:$tenant,product:\"context-gateway\",resourceType:\"gateway\",resourceId:$gateway,actions:[\"use\"]}]}' > agent-grant.json\ncurl --fail-with-body --silent --show-error \\\n  -X POST http://localhost:9200/v1/api-keys \\\n  -H \"Authorization: Bearer <identity-service-control-token>\" \\\n  -H \"Content-Type: application/json\" \\\n  --data-binary @agent-grant.json > agent-key.json\nexport AGENT_KEY=\"$(jq -er '.token' agent-key.json)\"",
      "section_id": "7-mint-an-agent-key"
    },
    {
      "id": "8-make-one-authenticated-call-ex0",
      "language": "bash",
      "code": "curl --fail-with-body --silent --show-error \"$MCP_ENDPOINT\" \\\n  -H \"Authorization: Bearer $AGENT_KEY\" \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":{},\"clientInfo\":{\"name\":\"gateway-smoke\",\"version\":\"1.0\"}}}'\n\ncurl --fail-with-body --silent --show-error \"$MCP_ENDPOINT\" \\\n  -H \"Authorization: Bearer $AGENT_KEY\" \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Mcp-Protocol-Version: 2025-06-18' \\\n  -d '{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}'\n\ncurl --fail-with-body --silent --show-error \"$MCP_ENDPOINT\" \\\n  -H \"Authorization: Bearer $AGENT_KEY\" \\\n  -H 'Content-Type: application/json' \\\n  -H 'Accept: application/json, text/event-stream' \\\n  -H 'Mcp-Protocol-Version: 2025-06-18' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}'",
      "section_id": "8-make-one-authenticated-call"
    },
    {
      "id": "install-with-the-redis-iris-suite-chart-ex0",
      "language": "yaml",
      "code": "contextGateway:\n  publicBaseURL: https://mcp.example.com\n  metadataDB:\n    existingSecret: gateway-metadata\n  credentialStorage:\n    provider: redis\n    redis:\n      connection:\n        existingSecret: gateway-credential-redis\n      keyring:\n        existingSecret: gateway-keyring",
      "section_id": "install-with-the-redis-iris-suite-chart"
    },
    {
      "id": "install-with-the-redis-iris-suite-chart-ex1",
      "language": "bash",
      "code": "helm install iris redis-ai/redis-iris \\\n  --version 1.0.0 \\\n  --namespace <namespace-name> \\\n  -f iris-values.yaml",
      "section_id": "install-with-the-redis-iris-suite-chart"
    }
  ]
}
