# Deploy Redis Context Gateway

```json metadata
{
  "schema_version": 2,
  "title": "Deploy Redis Context Gateway",
  "description": "Install Redis Context Gateway with an external Identity Service, then create a Gateway, mint an agent key, and make one authenticated call.",
  "categories": ["docs","operate","iris"],
  "tableOfContents": {"sections":[{"id":"1-create-the-namespace","title":"1. Create the namespace"},{"children":[{"id":"configure-the-identity-service-release-first","title":"Configure the Identity Service release first"},{"id":"create-the-connection-files","title":"Create the connection files"},{"id":"create-the-secrets","title":"Create the Secrets"}],"id":"2-create-secrets","title":"2. Create Secrets"},{"id":"3-create-gateway-valuesyaml","title":"3. Create gateway-values.yaml"},{"id":"before-you-install-check-your-values","title":"Before you install: check your values"},{"id":"4-install","title":"4. Install"},{"id":"5-verify-pods-and-health","title":"5. Verify pods and health"},{"id":"6-create-a-gateway","title":"6. Create a Gateway"},{"id":"7-mint-an-agent-key","title":"7. Mint an agent key"},{"id":"8-make-one-authenticated-call","title":"8. Make one authenticated call"},{"id":"install-with-the-redis-iris-suite-chart","title":"Install with the Redis Iris suite chart"},{"id":"next-steps","title":"Next steps"}]}

,
  "codeExamples": []
}
```


> [!NOTE]
> 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.

These 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.

You 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).

Before you begin, review the [prerequisites](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/prerequisites).

## 1. Create the namespace

```bash
kubectl create namespace <namespace-name>
```

## 2. Create Secrets

### Configure the Identity Service release first

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).

Set these values on the Identity Service release so that it checks Gateway grants and accepts the Data Plane's runtime token:

| Identity Service value | Setting |
| --- | --- |
| `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`. |
| `productValidation.products.context-gateway.baseURL` | The Control Plane Service, for example `http://gateway-redis-context-gateway-controlplane:9100`. |
| `productValidation.products.context-gateway.credential` | The same Secret as `controlplane.internalToken`. |
| `productValidation.products.context-gateway.enabled` | `true` |
| `runtime.apiKeyTenant.singleTenantID` | The same value as `tenantId`. |

If the Identity Service release also serves Agent Memory or Agent Playbooks, add these entries to its existing lists.

### Create the connection files

Save the Metadata Redis connection as `metadata.yaml`:

```yaml
metadata_db:
  urls: ["rediss://<metadata-user>:<password>@<metadata-host>:6379"]
```

Save the credential Redis connection as `credential-redis.yaml`:

```yaml
credential_storage:
  redis:
    urls: ["rediss://<credential-user>:<password>@<credential-host>:6379"]
```

Keep real URLs and passwords only in these files, and create Secrets from them.

### Create the Secrets

```bash
umask 077
openssl rand -base64 32 > k1
kubectl -n <namespace-name> create secret generic gateway-metadata --from-file=config.yaml=metadata.yaml
kubectl -n <namespace-name> create secret generic gateway-credential-redis --from-file=config.yaml=credential-redis.yaml
kubectl -n <namespace-name> create secret generic gateway-keyring --from-file=k1
kubectl -n <namespace-name> create secret generic gateway-license --from-file=license=./license
kubectl -n <namespace-name> create secret generic gateway-admin --from-file=token=./admin-token
kubectl -n <namespace-name> create secret generic gateway-grant-validation --from-file=token=./grant-token
kubectl -n <namespace-name> create secret generic gateway-runtime --from-file=token=./runtime-token
```

Create a `databaseConnections` Secret for the registered databases. See [Database registry](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/configuration#database-registry).

## 3. Create `gateway-values.yaml`

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.

```yaml
tenantId: <tenant-id>
publicBaseURL: https://<gateway-host>
identityService:
  baseURL: http://ids-iris-identity-service:9200
  allowInsecureTransport: true
license:
  existingSecret: gateway-license
metadataDB:
  existingSecret: gateway-metadata
  secretKey: config.yaml
credentialStorage:
  provider: redis
  redis:
    connection:
      existingSecret: gateway-credential-redis
      secretKey: config.yaml
    keyring:
      existingSecret: gateway-keyring
    keyFiles:
      k1: k1
    activeKeyId: k1
controlplane:
  adminToken:
    existingSecret: gateway-admin
    secretKey: token
  internalToken:
    existingSecret: gateway-grant-validation
    secretKey: token
dataplane:
  runtimeToken:
    existingSecret: gateway-runtime
    secretKey: token
```

This 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.

When `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`.

## Before you install: check your values

Check each value in `gateway-values.yaml` before you install. If one is wrong, you see the symptom in its row.

| Check | Symptom | Fix |
| --- | --- | --- |
| `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. |
| `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://`. |
| `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. |
| 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. |
| `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. |
| 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. |

## 4. Install

```bash
helm repo add redis-ai https://helm.redis.io/ai
helm repo update redis-ai
helm install gateway redis-ai/redis-context-gateway \
  --version 1.0.0 \
  --namespace <namespace-name> \
  -f gateway-values.yaml \
  --wait --timeout 5m
```

Use a published chart version. A merged server change does not by itself publish a chart or image.

## 5. Verify pods and health

```bash
kubectl -n <namespace-name> rollout status deployment/gateway-redis-context-gateway-controlplane
kubectl -n <namespace-name> rollout status deployment/gateway-redis-context-gateway-dataplane
```

Run each port-forward in its own terminal and leave it running:

```bash
kubectl -n <namespace-name> port-forward svc/gateway-redis-context-gateway-controlplane 9100:9100
```

```bash
kubectl -n <namespace-name> port-forward svc/gateway-redis-context-gateway-dataplane 8083:8083
```

```bash
kubectl -n <namespace-name> port-forward svc/ids-iris-identity-service 9200:9200
```

Then check readiness on both planes:

```bash
curl -sS http://localhost:9100/health/readiness
curl -sS http://localhost:8083/health/readiness
```

## 6. Create a Gateway

```bash
umask 077
curl --fail-with-body --silent --show-error \
  -X POST http://localhost:9100/iris/v1/context-gateway/gateways \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-gateway", "toolExposureMode": "FULL"}' > gateway.json
export GATEWAY_ID="$(jq -er '.gatewayId' gateway.json)"
export MCP_ENDPOINT="$(jq -er '.mcpEndpoint' gateway.json)"
```

The 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.

## 7. Mint an agent key

```bash
jq -n --arg tenant '<tenant-id>' --arg gateway "$GATEWAY_ID" \
  '{name:"my-agent-key",grants:[{tenant:$tenant,product:"context-gateway",resourceType:"gateway",resourceId:$gateway,actions:["use"]}]}' > agent-grant.json
curl --fail-with-body --silent --show-error \
  -X POST http://localhost:9200/v1/api-keys \
  -H "Authorization: Bearer <identity-service-control-token>" \
  -H "Content-Type: application/json" \
  --data-binary @agent-grant.json > agent-key.json
export AGENT_KEY="$(jq -er '.token' agent-key.json)"
```

> [!WARNING]
> The response's `token` is the agent key. It is shown only once, so save it in your secret manager.

## 8. Make one authenticated call

Send an initialization request to the advertised endpoint. These commands use protocol version `2025-06-18`, which the Gateway supports.

```bash
curl --fail-with-body --silent --show-error "$MCP_ENDPOINT" \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"gateway-smoke","version":"1.0"}}}'

curl --fail-with-body --silent --show-error "$MCP_ENDPOINT" \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Mcp-Protocol-Version: 2025-06-18' \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

curl --fail-with-body --silent --show-error "$MCP_ENDPOINT" \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Mcp-Protocol-Version: 2025-06-18' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

The 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`.

## Install with the Redis Iris suite chart

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.

The 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:

- `tenantId` and `license`
- `identityService.baseURL` and `identityService.allowInsecureTransport`
- `dataplane.runtimeToken` and `controlplane.internalToken`, which the suite supplies as Kubernetes Secrets
- `controlplane.config.auth.oidc`, when `global.iris.auth.oidc` sets an issuer

The 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.

You 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`:

```yaml
contextGateway:
  publicBaseURL: https://mcp.example.com
  metadataDB:
    existingSecret: gateway-metadata
  credentialStorage:
    provider: redis
    redis:
      connection:
        existingSecret: gateway-credential-redis
      keyring:
        existingSecret: gateway-keyring
```

```bash
helm install iris redis-ai/redis-iris \
  --version 1.0.0 \
  --namespace <namespace-name> \
  -f iris-values.yaml
```

The 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`.

## Next steps

- [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.
- [Operations](https://redis.io/docs/latest/operate/iris/context-gateway/self-managed/operations) for credential rotation and upgrades.

