From 4d72c28c202664777cf448dae6bec6e7ba77e23d Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Fri, 4 Sep 2026 13:46:20 +0300 Subject: [PATCH 01/10] MOD-17747: Add self-managed LangCache documentation Document LangCache on-prem (self-managed) deployment and usage, based on the self-managed Redis Agent Memory (RAM) docs and verified against the LangCache ADR/TDD, Helm chart, and controlplane-onprem/dataplane source. Adds content/operate/iris/langcache/self-managed/: - _index.md, plan-deployment.md, prerequisites.md - deploy-static.md, deploy-control-plane.md, data-plane-configuration.md - authentication.md - control-plane-api-reference.md + generated openapi-control-plane.json - operations.md, reference.md, api-examples.md Also adds one link from the existing LangCache Cloud index page (content/operate/iris/langcache/_index.md) to the new self-managed section, mirroring the Agent Memory index's "Deployment options" pattern. Co-Authored-By: Claude Sonnet 5 --- content/operate/iris/langcache/_index.md | 2 + .../iris/langcache/self-managed/_index.md | 119 ++ .../langcache/self-managed/api-examples.md | 184 +++ .../langcache/self-managed/authentication.md | 203 +++ .../control-plane-api-reference.md | 10 + .../openapi-control-plane.json | 1187 +++++++++++++++++ .../self-managed/data-plane-configuration.md | 155 +++ .../self-managed/deploy-control-plane.md | 266 ++++ .../langcache/self-managed/deploy-static.md | 117 ++ .../iris/langcache/self-managed/operations.md | 147 ++ .../langcache/self-managed/plan-deployment.md | 47 + .../langcache/self-managed/prerequisites.md | 159 +++ .../iris/langcache/self-managed/reference.md | 60 + 13 files changed, 2656 insertions(+) create mode 100644 content/operate/iris/langcache/self-managed/_index.md create mode 100644 content/operate/iris/langcache/self-managed/api-examples.md create mode 100644 content/operate/iris/langcache/self-managed/authentication.md create mode 100644 content/operate/iris/langcache/self-managed/control-plane-api-reference.md create mode 100644 content/operate/iris/langcache/self-managed/control-plane-api-reference/openapi-control-plane.json create mode 100644 content/operate/iris/langcache/self-managed/data-plane-configuration.md create mode 100644 content/operate/iris/langcache/self-managed/deploy-control-plane.md create mode 100644 content/operate/iris/langcache/self-managed/deploy-static.md create mode 100644 content/operate/iris/langcache/self-managed/operations.md create mode 100644 content/operate/iris/langcache/self-managed/plan-deployment.md create mode 100644 content/operate/iris/langcache/self-managed/prerequisites.md create mode 100644 content/operate/iris/langcache/self-managed/reference.md diff --git a/content/operate/iris/langcache/_index.md b/content/operate/iris/langcache/_index.md index 4f84438dc6..14c56ea073 100644 --- a/content/operate/iris/langcache/_index.md +++ b/content/operate/iris/langcache/_index.md @@ -19,6 +19,8 @@ LangCache is a semantic caching service available as a REST API that stores LLM For more information about how LangCache works, see the [LangCache overview]({{< relref "/develop/ai/context-engine/langcache" >}}). +To deploy LangCache on your own Kubernetes infrastructure instead of Redis Cloud, see [self-managed LangCache]({{< relref "/operate/iris/langcache/self-managed" >}}). + ## LLM cost reduction with LangCache {{< embed-md "langcache-cost-reduction.md" >}} diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md new file mode 100644 index 0000000000..e3e27855ab --- /dev/null +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -0,0 +1,119 @@ +--- +Title: Self-managed LangCache +alwaysopen: false +categories: +- docs +- operate +- iris +description: Deploy, configure, secure, and operate LangCache on a self-managed Kubernetes cluster. +linkTitle: Self-managed +weight: 40 +hideListLinks: true +--- + +LangCache is a semantic caching service that stores LLM responses for fast, +cheaper retrieval. Applications send prompts to LangCache, which returns a +cached response for a semantically similar prior prompt or calls out to your +embedding provider and stores a new entry when there is no match. + +This guide covers deployment, configuration, security, and operations for +self-managed LangCache. + +The [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) +is the shared Data Plane API for Redis Cloud and self-managed deployments. The +[Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}) +documents the self-managed admin endpoints for caches. + +{{< note >}} +Self-managed LangCache is available as a private preview. You need a license +key and access to the container images and Helm chart. Contact your Redis +representative or [contact sales](https://redis.io/contact/). +{{< /note >}} + +## What you are deploying + +A standard self-managed LangCache deployment contains: + +| Component | Purpose | Default service | +| --- | --- | --- | +| LangCache Data Plane | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:8080` | +| LangCache Control Plane | Optional admin API for creating and managing caches. | `langcache-controlplane:9100` | +| Identity Service | Shared suite service that issues and validates LangCache agent keys for Control Plane managed caches. | `iris-identity-service:9200` | +| Cache Redis | Holds cache entries and RediSearch vector indexes. | Customer-provided | +| Metadata Redis | Holds Control Plane cache records and, when agent-key auth is used, key/grant records. | Required for Control Plane managed caches | + +### How the components work together + +The Data Plane handles runtime cache requests. The optional Control Plane +handles cache administration. + +| Flow | Caller | Service | Backing Redis | +| --- | --- | --- | --- | +| Cache administration | Platform admin | LangCache Control Plane | Metadata Redis, Cache Redis (to provision the index) | +| Agent-key issuance and grants | Platform admin | Identity Service | Metadata Redis | +| Runtime cache requests | Agent, app, or gateway | LangCache Data Plane | Cache Redis | + +1. Platform admins use the Control Plane to create and manage caches. +1. The Control Plane writes cache records to Metadata Redis and synchronously + provisions the RediSearch vector index in Cache Redis. +1. When agent-key auth is used, platform admins mint keys and grants through + the Identity Service. +1. Agents and applications call the Data Plane with a cache ID. +1. The Data Plane resolves cache metadata (static config or, for Control Plane + managed caches, Metadata Redis) and reads or writes entries in Cache Redis. + +### API surfaces + +All Data Plane APIs are scoped to a cache. A cache is the logical isolation +boundary for cached entries. + +| API surface | Endpoint prefix | Purpose | +| --- | --- | --- | +| Cache entries | `/v1/caches/{cacheId}/entries` | Set, search, delete, and flush cached entries. | +| Conversational search | `/v1/caches/{cacheId}/conversations/search` | Search using conversation history context. | +| Cache health | `/v1/caches/{cacheId}/health` | Cache-scoped health status. | +| Control Plane | `/v1/caches`, `/v1/embedding-providers` | Self-managed administration for caches. | + +## Deployment modes + +Start with [Plan a deployment]({{< relref "/operate/iris/langcache/self-managed/plan-deployment" >}}) +to choose between static caches and Control Plane managed caches. + +| If you need to | Go to | +| --- | --- | +| Review software, Redis, network, Secret, image, and sizing requirements | [Prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) | +| Prepare `dataplane.config.yaml` for either deployment mode | [Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}) | +| Deploy a first-install or single-cache setup without the Control Plane | [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) | +| Deploy runtime cache administration | [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) | + +Do not combine static `metadata.caches` with Control Plane managed cache +metadata in the same Data Plane process. Static caches do not use Metadata +Redis. Control Plane managed caches use `metadata.loader: live` and require +Metadata Redis. + +{{< warning >}} +Do not expose an auth-disabled Data Plane to untrusted callers. Static caches +default to no Data Plane authentication; any caller that can reach the API can +read or write cached entries for configured caches. Use that mode only when +Kubernetes NetworkPolicy, private service exposure, ingress/gateway policy, +service mesh, or equivalent controls restrict access to trusted components. +{{< /warning >}} + +## Availability and packaging + +Self-managed LangCache is newer than self-managed Redis Agent Memory (RAM) and +its packaging is still catching up: + +- The published `langcache` Helm chart currently deploys only the Data Plane. + It does not yet have a `controlplane.enabled` toggle like the RAM chart. + [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) + shows how to run the Control Plane as a plain Kubernetes Deployment using the + Control Plane container image until chart support ships. +- Control Plane managed caches with agent-key Data Plane authentication depend + on the shared Identity Service, the same suite component RAM's chart + installs as `redis-agent-memory-identity-service`. LangCache's chart does + not template it yet either; see + [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). +- There is currently no public Docker Hub or Helm repository for LangCache + self-managed artifacts. Get the chart and images from your Redis + representative. diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md new file mode 100644 index 0000000000..e6158e3484 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -0,0 +1,184 @@ +--- +Title: Self-managed API examples +alwaysopen: false +categories: +- docs +- operate +- iris +description: Use curl examples with the LangCache self-managed Control Plane and Data Plane APIs. +linkTitle: Self-managed API examples +weight: 70 +hideListLinks: true +--- + +These examples show self-managed Control Plane and Data Plane requests. + +They assume either an auth-disabled private Data Plane, the legacy per-cache +token described in [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}), +or agent-key auth for a Control Plane managed cache. + +For the complete shared Data Plane schema, see the +[LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}). +For the self-managed admin schema, see the +[Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}). + +## Control Plane API examples + +Set variables: + +```bash +CP_URL="http://localhost:9100" +LC_ADMIN_TOKEN="" +``` + +List caches: + +```bash +curl -sS "$CP_URL/v1/caches" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" +``` + +Create a cache: + +```bash +curl -sS -X POST "$CP_URL/v1/caches" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-cache", + "databaseId": "cache-primary", + "defaultSearchThreshold": 0.9, + "defaultTtlMillis": -1, + "attributes": [] + }' +``` + +Response: + +```json +{ + "cacheId": "0123456789abcdef0123456789abcdef" +} +``` + +`databaseId` must match an entry in the Control Plane's configured +`databases` registry. `defaultSearchThreshold` is a float between 0 and 1. +`defaultTtlMillis` is `-1` for no expiration, or a positive number of +milliseconds. + +Get a cache: + +```bash +curl -sS "$CP_URL/v1/caches/" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" +``` + +Response fields include `status` (`PROVISIONING`, `READY`, or +`UNAVAILABLE`), the deployment's `embeddingProvider`/`embeddingModel`/ +`embeddingDimensions`, and the resolved `databaseName`. + +Update a cache: + +```bash +curl -sS -X PATCH "$CP_URL/v1/caches/" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "defaultSearchThreshold": 0.85 + }' +``` + +Flush a cache's entries without deleting the cache: + +```bash +curl -sS -X DELETE "$CP_URL/v1/caches//entries" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" +``` + +Delete a cache: + +```bash +curl -sS -X DELETE "$CP_URL/v1/caches/?flush=true" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" +``` + +List the deployment's configured embedding providers and models: + +```bash +curl -sS "$CP_URL/v1/embedding-providers" \ + -H "Authorization: Bearer $LC_ADMIN_TOKEN" +``` + +## Data Plane API examples + +Set variables: + +```bash +DP_URL="http://localhost:8080" +CACHE_ID="" +LC_TOKEN="" +``` + +For auth-disabled deployments, omit the `Authorization` header and rely on +the deployment's hosting controls. + +### Set a cache entry + +```bash +curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries" \ + -H "Authorization: Bearer $LC_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "What is the capital of France?", + "response": "The capital of France is Paris." + }' +``` + +### Search for a cached response + +```bash +curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries/search" \ + -H "Authorization: Bearer $LC_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "What'"'"'s the capital city of France?" + }' +``` + +### Delete a specific entry + +```bash +curl -sS -X DELETE "$DP_URL/v1/caches/$CACHE_ID/entries/" \ + -H "Authorization: Bearer $LC_TOKEN" +``` + +### Delete entries matching attributes + +```bash +curl -sS -X DELETE "$DP_URL/v1/caches/$CACHE_ID/entries" \ + -H "Authorization: Bearer $LC_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "attributes": { + "topic": "geography" + } + }' +``` + +### Flush all entries in a cache + +```bash +curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/flush" \ + -H "Authorization: Bearer $LC_TOKEN" +``` + +### Check cache health + +```bash +curl -sS "$DP_URL/v1/caches/$CACHE_ID/health" \ + -H "Authorization: Bearer $LC_TOKEN" +``` + +For the full request and response schema for these operations, including +conversational search, see the +[LangCache API reference]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}). diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md new file mode 100644 index 0000000000..7d844231da --- /dev/null +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -0,0 +1,203 @@ +--- +Title: Authentication and authorization +alwaysopen: false +categories: +- docs +- operate +- iris +description: Configure LangCache self-managed Control Plane authentication and Data Plane auth modes. +linkTitle: Authentication and authorization +weight: 60 +hideListLinks: true +--- + +Self-managed LangCache uses separate authentication models for the Control +Plane and the Data Plane, and the Data Plane auth model differs between +static and Control Plane managed caches. + +## Control Plane admin token + +Control Plane management endpoints require: + +```http +Authorization: Bearer +``` + +Production deployments should read the token from a mounted Secret file: + +```yaml +profile: prod + +auth: + type: admin-token + admin_token: + token_file: /etc/controlplane-onprem/admin/token +``` + +The Control Plane reads the token file on each request, so rotating the +Secret does not require a Control Plane redeploy. + +## Data Plane auth modes + +Choose the Data Plane auth mode based on the deployment mode and how callers +reach the Data Plane. + +| Mode | Deployment mode | Config | Use when | +| --- | --- | --- | --- | +| Auth-disabled | Static caches | `auth.enabled: false` (default) | The Data Plane is reachable only by trusted internal components. | +| Legacy per-cache token | Static caches | `auth.enabled: true`, `auth.passphrase: ` | You need per-cache API-key-style tokens without deploying the Control Plane or Identity Service. | +| Agent-key authentication | Control Plane managed caches | `auth.agent_keys.enabled: true` | LangCache should validate agent keys and enforce per-cache grants through the shared Identity Service. | + +### Auth-disabled Data Plane (static caches) + +```yaml +auth: + enabled: false +``` + +{{< warning >}} +Do not expose an auth-disabled Data Plane to untrusted callers. Any caller +that can reach the API can read or write cached entries for every configured +cache. +{{< /warning >}} + +### Legacy per-cache token (static caches) + +Static caches also support the same symmetric, per-cache token scheme used by +LangCache on Redis Cloud. Enable it and set a passphrase: + +```yaml +auth: + enabled: true + passphrase: "" +``` + +Generate a token for a cache with the `generate-auth-token` binary shipped in +the Data Plane image: + +```bash +generate-auth-token \ + --config=/etc/langcache/dataplane.config.yaml \ + --username= \ + --password= \ + --resourceID= +``` + +The command prints a token. Send it as: + +```http +Authorization: Bearer +``` + +Treat the token as an opaque credential. There is no Control Plane endpoint +to mint, list, or revoke these tokens; manage the passphrase and any +generated tokens as part of your Secret material. + +### Agent-key authentication (Control Plane managed caches) + +Agent-key auth requires Control Plane managed caches and is served by the +on-prem-hardened Data Plane binary. That binary rejects static caches and +every other auth method, so `auth.agent_keys.enabled` is effectively the only +supported setting when you deploy this mode. + +Unlike Redis Agent Memory's simpler shared-secret Data Plane auth, LangCache +agent keys are issued and validated by the **Identity Service**, a suite +component shared with RAM (RAM's chart installs it as +`redis-agent-memory-identity-service`; the published image is +`redislabs/iris-identity-service`). The LangCache `langcache` Helm chart does +not template the Identity Service yet, so deploy it the same way you deploy +the [Control Plane]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}): +as a plain Kubernetes Deployment using the published image, pointed at the +same Metadata Redis. + +Data Plane config for agent-key auth: + +```yaml +auth: + agent_keys: + enabled: true + product: langcache + introspection: + base_url: https://iris-identity-service:9200 + product: langcache + credential: + token_file: /etc/langcache/introspection/token +``` + +- `introspection.base_url` is the Identity Service's base URL. It must be + `https://` unless you explicitly allow insecure transport for a lab + environment. +- `introspection.product` must be `langcache`; a different value fails + Data Plane startup. +- `introspection.credential` is the shared credential the Data Plane presents + to the Identity Service when introspecting a key. + +Clients send agent keys as Bearer credentials: + +```http +Authorization: Bearer +``` + +Treat agent keys as opaque credentials. Do not parse their contents. + +## Cache authorization and grants + +For agent-key requests, LangCache checks both identity and resource +authorization through the Identity Service: + +1. The key exists and its secret validates. +2. The key has a grant for the requested cache resource, keyed as + `lc-cache:`. +3. The grant includes the permission required by the operation. + +Grant actions: + +| Action | Meaning | +| --- | --- | +| `read` | Read and search cache entries. | +| `write` | Mutate cache entries. `write` implies `read`. | +| `full` | Full cache administration through the grant. `full` implies `write`. | + +Mint and manage agent keys directly against the Identity Service (not the +LangCache Control Plane): + +```bash +curl -sS -X POST "$IDENTITY_SERVICE_URL/v1/api-keys" \ + -H "Authorization: Bearer $IDENTITY_SERVICE_CONTROL_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-agent-key", + "grants": [ + { + "product": "langcache", + "resourceType": "lc-cache", + "resourceId": "", + "actions": ["read", "write"] + } + ] + }' +``` + +{{< note >}} +The Identity Service is a shared, cross-product component. A full +self-managed deployment and administration guide for it is out of scope for +this LangCache-specific documentation; see your Redis representative or the +self-managed Redis Agent Memory Helm chart for a working reference +deployment of `iris-identity-service` until dedicated Identity Service docs +are published. +{{< /note >}} + +## Gateway and identity provider integration + +Use a gateway when it owns external authentication and coarse policy. For +example, a gateway can authenticate callers through an identity provider +before it forwards requests to LangCache. + +Gateway rules: + +- The gateway owns external authentication and perimeter policy. +- LangCache owns cache-level authorization through the Identity Service. +- LangCache agent keys or legacy tokens are stored and forwarded by trusted + infrastructure or trusted applications. +- Callers must not be able to bypass the gateway and reach the Data Plane + directly unless they also present a valid LangCache credential. diff --git a/content/operate/iris/langcache/self-managed/control-plane-api-reference.md b/content/operate/iris/langcache/self-managed/control-plane-api-reference.md new file mode 100644 index 0000000000..6df3d76a54 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/control-plane-api-reference.md @@ -0,0 +1,10 @@ +--- +Title: LangCache Control Plane API reference +linkTitle: Control Plane API reference +layout: apireference +type: page +weight: 80 +params: + sourcefile: ./openapi-control-plane.json + sortOperationsAlphabetically: false +--- diff --git a/content/operate/iris/langcache/self-managed/control-plane-api-reference/openapi-control-plane.json b/content/operate/iris/langcache/self-managed/control-plane-api-reference/openapi-control-plane.json new file mode 100644 index 0000000000..7b65833bf4 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/control-plane-api-reference/openapi-control-plane.json @@ -0,0 +1,1187 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "LangCacheControlPlaneService", + "version": "1.0.0", + "description": "Administrative API for the on-prem Redis LangCache control plane." + }, + "paths": { + "/v1/caches": { + "get": { + "operationId": "ListCaches", + "responses": { + "200": { + "description": "ListCaches 200 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListCachesResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "403": { + "description": "ForbiddenError 403 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + }, + "post": { + "operationId": "CreateCache", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCacheRequestContent" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "CreateCache 201 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateCacheResponseContent" + } + } + } + }, + "400": { + "description": "BadRequestError 400 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "403": { + "description": "ForbiddenError 403 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + } + }, + "424": { + "description": "FailedDependencyError 424 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + } + }, + "/v1/caches/{cacheId}": { + "delete": { + "operationId": "DeleteCache", + "parameters": [ + { + "name": "cacheId", + "in": "path", + "schema": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "required": true + }, + { + "name": "flush", + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "DeleteCache 200 response" + }, + "400": { + "description": "BadRequestError 400 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "404": { + "description": "NotFoundError 404 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + }, + "get": { + "operationId": "GetCache", + "parameters": [ + { + "name": "cacheId", + "in": "path", + "schema": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "required": true + } + ], + "responses": { + "200": { + "description": "GetCache 200 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetCacheResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "403": { + "description": "ForbiddenError 403 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenErrorResponseContent" + } + } + } + }, + "404": { + "description": "NotFoundError 404 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + }, + "patch": { + "operationId": "UpdateCache", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CachePatch" + } + } + }, + "required": true + }, + "parameters": [ + { + "name": "cacheId", + "in": "path", + "schema": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "required": true + } + ], + "responses": { + "201": { + "description": "UpdateCache 201 response" + }, + "400": { + "description": "BadRequestError 400 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "404": { + "description": "NotFoundError 404 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + } + }, + "/v1/caches/{cacheId}/entries": { + "delete": { + "operationId": "FlushCache", + "parameters": [ + { + "name": "cacheId", + "in": "path", + "schema": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "required": true + } + ], + "responses": { + "204": { + "description": "FlushCache 204 response" + }, + "400": { + "description": "BadRequestError 400 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestErrorResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "404": { + "description": "NotFoundError 404 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundErrorResponseContent" + } + } + } + }, + "424": { + "description": "FailedDependencyError 424 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FailedDependencyErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + } + }, + "/v1/embedding-providers": { + "get": { + "operationId": "ListEmbeddingProviders", + "responses": { + "200": { + "description": "ListEmbeddingProviders 200 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListEmbeddingProvidersResponseContent" + } + } + } + }, + "401": { + "description": "AuthenticationError 401 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationErrorResponseContent" + } + } + } + }, + "500": { + "description": "UnexpectedError 500 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnexpectedErrorResponseContent" + } + } + } + }, + "503": { + "description": "ServiceUnavailableError 503 response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceUnavailableErrorResponseContent" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AuthenticationErrorResponseContent": { + "type": "object", + "description": "Authentication credentials are missing, malformed, or invalid.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 401, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/AuthenticationErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "AuthenticationErrorType": { + "type": "string", + "description": "Problem type URI for authentication errors.", + "enum": [ + "/errors/authentication-failed" + ] + }, + "BadRequestErrorResponseContent": { + "type": "object", + "description": "Request validation or input decoding failed.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 400, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/BadRequestErrorType" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FieldError" + }, + "description": "Optional field-level validation errors." + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "BadRequestErrorType": { + "type": "string", + "description": "Problem type URI for bad request errors.", + "enum": [ + "/errors/invalid-data" + ] + }, + "CacheFailure": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "occurredAt": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "message", + "occurredAt" + ] + }, + "CacheOutput": { + "type": "object", + "properties": { + "cacheId": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "name": { + "type": "string", + "maxLength": 64, + "minLength": 1 + }, + "databaseId": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$" + }, + "databaseName": { + "type": "string" + }, + "defaultSearchThreshold": { + "type": "number", + "maximum": 1, + "minimum": 0, + "format": "float" + }, + "defaultTtlMillis": { + "type": "integer", + "minimum": -1, + "format": "int64" + }, + "attributes": { + "type": "array", + "items": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9_-]+$" + }, + "maxItems": 5 + }, + "searchStrategies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchStrategy" + } + }, + "embeddingProvider": { + "type": "string" + }, + "embeddingModel": { + "type": "string" + }, + "embeddingDimensions": { + "type": "integer", + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/CacheStatus" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "failure": { + "$ref": "#/components/schemas/CacheFailure" + } + }, + "required": [ + "attributes", + "cacheId", + "createdAt", + "databaseId", + "databaseName", + "defaultSearchThreshold", + "defaultTtlMillis", + "embeddingDimensions", + "embeddingModel", + "embeddingProvider", + "name", + "searchStrategies", + "status" + ] + }, + "CachePatch": { + "type": "object", + "properties": { + "defaultSearchThreshold": { + "type": "number", + "maximum": 1, + "minimum": 0, + "format": "float" + }, + "defaultTtlMillis": { + "type": "integer", + "minimum": -1, + "format": "int64" + }, + "searchStrategies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchStrategy" + }, + "maxItems": 2, + "minItems": 1, + "uniqueItems": true + } + } + }, + "CacheStatus": { + "type": "string", + "enum": [ + "PROVISIONING", + "READY", + "UNAVAILABLE" + ] + }, + "CreateCacheRequestContent": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 64, + "minLength": 1 + }, + "databaseId": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$" + }, + "defaultSearchThreshold": { + "type": "number", + "maximum": 1, + "minimum": 0, + "format": "float" + }, + "defaultTtlMillis": { + "type": "integer", + "minimum": -1, + "format": "int64" + }, + "attributes": { + "type": "array", + "items": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9_-]+$" + }, + "maxItems": 5 + }, + "searchStrategies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchStrategy" + } + } + }, + "required": [ + "attributes", + "databaseId", + "defaultSearchThreshold", + "defaultTtlMillis", + "name" + ] + }, + "CreateCacheResponseContent": { + "type": "object", + "properties": { + "cacheId": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + } + }, + "required": [ + "cacheId" + ] + }, + "EmbeddingModel": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "dimensions": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "dimensions", + "name" + ] + }, + "EmbeddingProvider": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "models": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EmbeddingModel" + } + } + }, + "required": [ + "models", + "name" + ] + }, + "FailedDependencyErrorResponseContent": { + "type": "object", + "description": "A dependent resource required to process the request is unavailable or unhealthy.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 424, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/FailedDependencyErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "FailedDependencyErrorType": { + "type": "string", + "description": "Problem type URI for failed-dependency errors.", + "enum": [ + "/errors/resource-unavailable", + "/errors/database-out-of-memory" + ] + }, + "FieldError": { + "type": "object", + "description": "Validation error details for a single request field.", + "properties": { + "field": { + "type": "string", + "description": "Name of the invalid request field." + }, + "rule": { + "type": "string", + "description": "Validation rule that was violated." + }, + "message": { + "type": "string", + "description": "Human-readable validation error message." + } + }, + "required": [ + "field", + "message", + "rule" + ] + }, + "ForbiddenErrorResponseContent": { + "type": "object", + "description": "The caller is authenticated but not allowed to access the requested resource.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 403, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/ForbiddenErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "ForbiddenErrorType": { + "type": "string", + "description": "Problem type URI for authorization errors.", + "enum": [ + "/errors/insufficient-permissions" + ] + }, + "GetCacheResponseContent": { + "type": "object", + "properties": { + "cacheId": { + "type": "string", + "maxLength": 32, + "minLength": 32, + "pattern": "^[0-9a-f]{32}$" + }, + "name": { + "type": "string", + "maxLength": 64, + "minLength": 1 + }, + "databaseId": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9-]+$" + }, + "databaseName": { + "type": "string" + }, + "defaultSearchThreshold": { + "type": "number", + "maximum": 1, + "minimum": 0, + "format": "float" + }, + "defaultTtlMillis": { + "type": "integer", + "minimum": -1, + "format": "int64" + }, + "attributes": { + "type": "array", + "items": { + "type": "string", + "maxLength": 32, + "minLength": 1, + "pattern": "^[A-Za-z0-9_-]+$" + }, + "maxItems": 5 + }, + "searchStrategies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchStrategy" + } + }, + "embeddingProvider": { + "type": "string" + }, + "embeddingModel": { + "type": "string" + }, + "embeddingDimensions": { + "type": "integer", + "format": "int32" + }, + "status": { + "$ref": "#/components/schemas/CacheStatus" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "failure": { + "$ref": "#/components/schemas/CacheFailure" + } + }, + "required": [ + "attributes", + "cacheId", + "createdAt", + "databaseId", + "databaseName", + "defaultSearchThreshold", + "defaultTtlMillis", + "embeddingDimensions", + "embeddingModel", + "embeddingProvider", + "name", + "searchStrategies", + "status" + ] + }, + "ListCachesResponseContent": { + "type": "object", + "properties": { + "caches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CacheOutput" + } + } + }, + "required": [ + "caches" + ] + }, + "ListEmbeddingProvidersResponseContent": { + "type": "object", + "properties": { + "embeddingProviders": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EmbeddingProvider" + } + } + }, + "required": [ + "embeddingProviders" + ] + }, + "NotFoundErrorResponseContent": { + "type": "object", + "description": "The requested resource does not exist.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 404, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/NotFoundErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "NotFoundErrorType": { + "type": "string", + "description": "Problem type URI for not-found errors.", + "enum": [ + "/errors/resource-not-found" + ] + }, + "SearchStrategy": { + "type": "string", + "enum": [ + "exact", + "semantic" + ], + "x-enumNames": [ + "SearchStrategyExact", + "SearchStrategySemantic" + ] + }, + "ServiceUnavailableErrorResponseContent": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 503, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/ServiceUnavailableErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "ServiceUnavailableErrorType": { + "type": "string", + "enum": [ + "/errors/service-unavailable" + ] + }, + "UnexpectedErrorResponseContent": { + "type": "object", + "description": "The service failed with an unexpected internal error.", + "properties": { + "title": { + "type": "string", + "description": "A short, human-readable summary of the problem\n type. It SHOULD NOT change from occurrence to occurrence of the\n problem, except for purposes of localization (e.g., using\n proactive content negotiation; see [RFC7231], Section 3.4)." + }, + "status": { + "type": "integer", + "default": 500, + "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.", + "format": "int32" + }, + "detail": { + "type": "string", + "description": "A human-readable explanation specific to this occurrence of the problem." + }, + "instance": { + "type": "string", + "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced." + }, + "type": { + "$ref": "#/components/schemas/UnexpectedErrorType" + } + }, + "required": [ + "status", + "title", + "type" + ] + }, + "UnexpectedErrorType": { + "type": "string", + "description": "Problem type URI for unexpected internal errors.", + "enum": [ + "/errors/unexpected-error" + ] + } + } + } +} diff --git a/content/operate/iris/langcache/self-managed/data-plane-configuration.md b/content/operate/iris/langcache/self-managed/data-plane-configuration.md new file mode 100644 index 0000000000..2871a8472c --- /dev/null +++ b/content/operate/iris/langcache/self-managed/data-plane-configuration.md @@ -0,0 +1,155 @@ +--- +Title: Data Plane configuration +alwaysopen: false +categories: +- docs +- operate +- iris +description: Configure the LangCache Data Plane for static caches or Control Plane managed caches. +linkTitle: Data Plane configuration +weight: 30 +hideListLinks: true +--- + +The Data Plane reads `dataplane.config.yaml` from a Kubernetes Secret. Use one +cache mode: static caches or Control Plane managed caches. The two modes use +different Data Plane binaries and config shapes. + +## Shared settings + +| Setting | Purpose | +| --- | --- | +| `server.port` | Data Plane bind port. | +| `client_side_cache` | In-memory response caching for repeated lookups. | +| `client_pool` | Redis client pool sizing. | +| `profile` | `prod`, `dev`, or `test`. | + +## Static caches example + +Use this config when caches are declared directly under `metadata.caches`. +This is the mode the published `langcache` Helm chart deploys today. + +```yaml +server: + port: 8080 + +profile: prod + +metadata: + loader: static + cache_ttl: 1m + caches: + # metadata.caches is a list; each entry is one cache. + - id: my-cache + urls: + - redis://cache-redis:6379 + index: idx:my-cache + model: + type: openai + name: text-embedding-3-large + dimensions: 3072 + # key: "" # optional per-cache override + attributes: [] + default_ttl: 60000 + default_search_threshold: 0.9 + search_strategies: + default_strategies: + - semantic + +embeddings: + openai: + default: + base_url: https://api.openai.com + +client_side_cache: + enabled: true + default_ttl: 1m + max_items: 30000 + +client_pool: + enable: true + max_size: 10000 + client_acquisition_timeout_ms: 2000 +``` + +Static caches carry Redis URLs and embedding settings directly in config. +Data Plane auth for this mode is disabled by default; see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) +to enable the legacy per-cache token auth. + +Provision the cache's RediSearch index before or during first start. The +`provision-cache-index` binary shipped in the Data Plane image reads the same +config and creates or repairs the index for every entry in `metadata.caches`: + +```bash +provision-cache-index --config=/etc/langcache/dataplane.config.yaml +``` + +The chart can run this automatically as an init container with +`initProvisioner.enabled: true`. + +## Control Plane managed caches example + +Use this config when the Data Plane serves caches created by the Control +Plane. This mode uses the on-prem-hardened Data Plane binary, requires +Metadata Redis, and only supports agent-key authentication through the shared +Identity Service. + +```yaml +server: + port: 9000 + +profile: prod + +metadata: + urls: + - redis://redis-meta:6379 + cache_ttl: 1m + +databases: + cache-primary: + name: cache-primary + urls: + - redis://cache-primary:6379 + +auth: + agent_keys: + enabled: true + product: langcache + introspection: + base_url: https://iris-identity-service:9200 + product: langcache + credential: + token_file: /etc/langcache/introspection/token + +embedding: + provider: openai + models: + default_embedding_model: text-embedding-3-large + dimensions: 3072 + credentials: + type: static + api_key: "" + +license: + license_path: /etc/langcache/license +``` + +The `databases` map must use the same logical `` keys (here, +`cache-primary`) as the Control Plane's `controlplane-onprem.config.yaml`, so +both processes resolve `databaseId` to the same Cache Redis target. The +`embedding` block must match the Control Plane's configured provider, model, +and dimensions exactly; Control Plane managed caches cannot select a +different embedding model or supply per-cache credentials. + +For the Identity Service introspection settings, see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). + +## Secret key + +Create the Data Plane config Secret with the key `dataplane.config.yaml`: + +```bash +kubectl -n create secret generic langcache-config \ + --from-file=dataplane.config.yaml=./dataplane.config.yaml +``` diff --git a/content/operate/iris/langcache/self-managed/deploy-control-plane.md b/content/operate/iris/langcache/self-managed/deploy-control-plane.md new file mode 100644 index 0000000000..629a195f95 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/deploy-control-plane.md @@ -0,0 +1,266 @@ +--- +Title: Deploy with Control Plane managed caches +alwaysopen: false +categories: +- docs +- operate +- iris +description: Deploy LangCache with caches managed by the self-managed Control Plane. +linkTitle: Deploy with Control Plane managed caches +weight: 50 +hideListLinks: true +--- + +Use Control Plane managed caches when operators need to create or manage +caches at runtime. In this mode, the Data Plane reads cache records from +Metadata Redis, and the Control Plane provisions the RediSearch index in +Cache Redis when it creates a cache. + +{{< note >}} +The published `langcache` Helm chart currently templates only the Data Plane. +This page deploys the Control Plane, and (for agent-key auth) the Identity +Service, as plain Kubernetes manifests using the images provided by your +Redis representative. Chart support for these components is expected in a +future release; check with your Redis representative for the current state. +{{< /note >}} + +Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) +and create `dataplane.config.yaml` from the +[Control Plane managed caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}). + +## Create the namespace + +```bash +kubectl create namespace +``` + +## Create shared Secrets + +Create the license Secret: + +```bash +kubectl -n create secret generic langcache-license \ + --from-file=license=./license +``` + +Create the Data Plane config Secret: + +```bash +kubectl -n create secret generic langcache-config \ + --from-file=dataplane.config.yaml=./dataplane.config.yaml +``` + +## Create the Control Plane config + +Create `controlplane-onprem.config.yaml`: + +```yaml +profile: prod + +auth: + type: admin-token + admin_token: + token_file: /etc/controlplane-onprem/admin/token + +license: + license_path: /etc/langcache/license + +metadata: + urls: + - redis://redis-meta:6379 + +databases: + cache-primary: + name: cache-primary + urls: + - redis://cache-primary:6379 + +embedders: + openai: + models: + - model: text-embedding-3-large + dimensions: 3072 +``` + +The Control Plane's `embedders` block must describe exactly one provider with +exactly one model; it is the embedding contract that cache creation and the +Data Plane's `embedding` config must agree on. It must not set +`authorized: true` — on-prem cache creation cannot accept per-cache embedding +credentials. + +Create the Control Plane config Secret: + +```bash +kubectl -n create secret generic langcache-controlplane-config \ + --from-file=controlplane-onprem.config.yaml=./controlplane-onprem.config.yaml +``` + +Bring your own admin token: + +```bash +kubectl -n create secret generic langcache-controlplane-admin-token \ + --from-literal=token='' +``` + +## Deploy the Control Plane + +Until the Control Plane is packaged in the Helm chart, deploy it directly. +Adjust the image reference to the one provided by your Redis representative: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: langcache-controlplane + namespace: +spec: + replicas: 1 + selector: + matchLabels: + app: langcache-controlplane + template: + metadata: + labels: + app: langcache-controlplane + spec: + containers: + - name: controlplane + image: /langcache-controlplane-onprem: + args: ["--config=/etc/controlplane-onprem/config/controlplane-onprem.config.yaml"] + ports: + - name: http + containerPort: 9100 + volumeMounts: + - name: config + mountPath: /etc/controlplane-onprem/config + readOnly: true + - name: admin-token + mountPath: /etc/controlplane-onprem/admin + readOnly: true + - name: license + mountPath: /etc/langcache + readOnly: true + readinessProbe: + httpGet: + path: /health/readiness + port: http + livenessProbe: + httpGet: + path: /health/liveness + port: http + volumes: + - name: config + secret: + secretName: langcache-controlplane-config + - name: admin-token + secret: + secretName: langcache-controlplane-admin-token + - name: license + secret: + secretName: langcache-license +--- +apiVersion: v1 +kind: Service +metadata: + name: langcache-controlplane + namespace: +spec: + selector: + app: langcache-controlplane + ports: + - name: http + port: 9100 + targetPort: http +``` + +```bash +kubectl apply -f langcache-controlplane.yaml +``` + +## Create Helm values for the Data Plane + +Create SHA-256 checksums for externally managed Secrets. These values are +used by Helm values to roll pods after Secret changes; they are not used to +validate Secret integrity. + +{{< multitabs id="langcache-control-plane-secret-checksums" +tab1="Linux" +tab2="macOS" >}} + +```bash +LICENSE_CHECKSUM="$(sha256sum ./license | awk '{print $1}')" +CONFIG_CHECKSUM="$(sha256sum ./dataplane.config.yaml | awk '{print $1}')" +``` + +-tab-sep- + +```bash +LICENSE_CHECKSUM="$(shasum -a 256 ./license | awk '{print $1}')" +CONFIG_CHECKSUM="$(shasum -a 256 ./dataplane.config.yaml | awk '{print $1}')" +``` + +{{< /multitabs >}} + +Create `langcache-values.yaml`: + +```yaml +image: + repository: /langcache-dataplane + tag: "" + +config: + existingSecret: langcache-config + existingSecretChecksum: "" +``` + +The chart values shown throughout this guide reflect the current `langcache` +chart, which does not yet expose license or Control Plane fields. Once your +chart provides `controlplane.enabled` (or similar) support, prefer that over +the manual Deployment above. + +## Install the Data Plane chart + +```bash +helm install langcache ./langcache \ + --namespace \ + --create-namespace \ + -f langcache-values.yaml +``` + +## Verify the deployment + +Check pods: + +```bash +kubectl -n get pods +``` + +Port-forward the Data Plane: + +```bash +kubectl -n port-forward svc/langcache 9000:9000 +``` + +```bash +curl http://localhost:9000/health +``` + +Port-forward the Control Plane: + +```bash +kubectl -n port-forward svc/langcache-controlplane 9100:9100 +``` + +Verify the admin API: + +```bash +curl -H "Authorization: Bearer " \ + http://localhost:9100/v1/caches +``` + +For the full self-managed admin API schema, see the +[Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}). + +After you deploy Control Plane managed caches, configure Data Plane +agent-key authentication and the Identity Service in +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). diff --git a/content/operate/iris/langcache/self-managed/deploy-static.md b/content/operate/iris/langcache/self-managed/deploy-static.md new file mode 100644 index 0000000000..14c563fa14 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/deploy-static.md @@ -0,0 +1,117 @@ +--- +Title: Deploy with static caches +alwaysopen: false +categories: +- docs +- operate +- iris +description: Deploy LangCache with static caches and no Control Plane. +linkTitle: Deploy with static caches +weight: 40 +hideListLinks: true +--- + +Use static caches for a first install or a private single-cache deployment. +In this mode, caches are declared directly in Data Plane configuration. The +deployment does not include the Control Plane and does not use Metadata +Redis. This is the mode the published `langcache` Helm chart deploys today. + +Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) +and create `dataplane.config.yaml` from the +[static caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}}). + +## Create the namespace + +```bash +kubectl create namespace +``` + +## Create the config Secret + +```bash +kubectl -n create secret generic langcache-config \ + --from-file=dataplane.config.yaml=./dataplane.config.yaml +``` + +## Create Helm values + +Create `langcache-values.yaml`: + +```yaml +image: + repository: /langcache + tag: "" + +config: + existingSecret: langcache-config + +initProvisioner: + enabled: true + config: /etc/langcache/dataplane.config.yaml +``` + +`config.existingSecret` points the chart at the config Secret you created. +`initProvisioner.enabled: true` runs `provision-cache-index --ignore` as an +init container so cache indexes exist before the Data Plane starts, without +recreating indexes that already exist. + +## Install the chart + +Install from the chart package provided by your Redis representative: + +```bash +helm install langcache ./langcache \ + --namespace \ + --create-namespace \ + -f langcache-values.yaml +``` + +On small clusters, install without `--atomic --wait`, then watch pod status: + +```bash +kubectl -n get pods -w +``` + +If you want Helm to wait, set an explicit timeout that matches the +environment: + +```bash +helm install langcache ./langcache \ + --namespace \ + --create-namespace \ + -f langcache-values.yaml \ + --wait \ + --timeout 15m +``` + +## Verify the deployment + +Check pods: + +```bash +kubectl -n get pods -l app.kubernetes.io/name=langcache +``` + +Port-forward the Data Plane: + +```bash +kubectl -n port-forward svc/langcache 8080:8080 +``` + +Check health endpoints: + +```bash +curl http://localhost:8080/health +curl http://localhost:8080/health/liveness +curl http://localhost:8080/health/readiness +``` + +Check the configured cache: + +```bash +curl http://localhost:8080/v1/caches/my-cache/health +``` + +Do not expose an auth-disabled Data Plane to untrusted callers. Use +Kubernetes NetworkPolicy, private service exposure, ingress, gateway, service +mesh, or equivalent controls to restrict access. diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md new file mode 100644 index 0000000000..10823a9d8b --- /dev/null +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -0,0 +1,147 @@ +--- +Title: Operations +alwaysopen: false +categories: +- docs +- operate +- iris +description: Operate self-managed LangCache with backups, secret rotation, updates, and FIPS posture. +linkTitle: Operations +weight: 90 +hideListLinks: true +--- + +## Backups + +- Back up Cache Redis according to the customer's cache-retention policy. + LangCache can rebuild the RediSearch index from existing entries, but losing + the underlying hashes loses cached responses. +- Back up Metadata Redis for Control Plane managed caches. Losing metadata + removes Control Plane cache records. +- Back up any external secret manager material used to recreate Kubernetes + Secrets, including the license, Data Plane config, Control Plane config, + and admin-token Secrets. +- For Metadata Redis, use persistent storage and an eviction policy that does + not evict cache records under memory pressure. + +## Secret rotation + +Rotate the Control Plane admin token by updating +`langcache-controlplane-admin-token`. The Control Plane reads the token on +use, so changing the token value does not require a Control Plane redeploy. + +```bash +kubectl -n create secret generic langcache-controlplane-admin-token \ + --from-literal=token='' \ + --dry-run=client \ + -o yaml | kubectl apply -f - +``` + +Rotate the LangCache license by updating the license Secret and changing +`config.existingSecretChecksum` (or the equivalent value for your chart +version) so Helm rolls the Data Plane pods. + +```bash +kubectl -n create secret generic langcache-license \ + --from-file=license=./license \ + --dry-run=client \ + -o yaml | kubectl apply -f - +``` + +Calculate the new SHA-256 checksum. This value is used by Helm values to roll +pods after the license Secret changes; it is not used to validate Secret +integrity. + +{{< multitabs id="langcache-license-secret-checksum" +tab1="Linux" +tab2="macOS" >}} + +```bash +LICENSE_CHECKSUM="$(sha256sum ./license | awk '{print $1}')" +``` + +-tab-sep- + +```bash +LICENSE_CHECKSUM="$(shasum -a 256 ./license | awk '{print $1}')" +``` + +{{< /multitabs >}} + +Apply the updated values and verify the workload rolled: + +```bash +helm upgrade langcache ./langcache \ + --namespace \ + -f langcache-values.yaml + +kubectl -n rollout status deploy/langcache +``` + +Rotate agent keys minted for Control Plane managed caches through the +Identity Service, as described in +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). + +Rotate the legacy static-cache token by regenerating it with +`generate-auth-token` and redistributing it to callers; there is no server +side revocation for this token type, so also consider rotating +`auth.passphrase` if a token may have leaked. + +## Updates + +For every update: + +1. Update chart version and image tags. +2. Recalculate Secret checksums for changed files. +3. Run `helm upgrade`. +4. Verify pod rollout and health endpoints. + +```bash +helm upgrade langcache ./langcache \ + --namespace \ + -f langcache-values.yaml +``` + +On small clusters, avoid `--atomic` unless the timeout and capacity are known +to be sufficient. If you deployed the Control Plane as a plain manifest, +update its image tag and re-apply the manifest, then verify its rollout the +same way. + +## FIPS-oriented posture + +The on-prem-hardened Control Plane and Data Plane binaries (used for Control +Plane managed caches) are built with a FIPS-oriented Go toolchain profile and +reject configuration that: + +- uses non-`rediss://` URLs for `metadata.urls`, `databases..urls`, or + the Control Plane's `metadata.urls`; or +- otherwise fails the shared FIPS Redis-URL posture check used across the + Redis AI Services products. + +This is not a formal FIPS 140 compliance or validation claim. Treat it as a +deployment posture and guardrail that must still be reviewed against the +customer's compliance boundary. + +The static-caches Data Plane image (used by the published `langcache` chart +today) does not build with this FIPS profile; it is the same image used for +LangCache on Redis Cloud. + +The LangCache API listener itself speaks HTTP inside the cluster. Edge TLS +termination is owned by the hosting environment, such as ingress, service +mesh, or external load balancer. Outbound TLS to Redis and the embedding +provider is configured through LangCache config and is covered by the +posture checks for Control Plane managed caches. + +## Network policy + +For auth-disabled Data Plane deployments, restrict access to trusted callers. +For agent-key deployments behind a gateway, prevent direct bypass paths +unless the direct caller also has a valid LangCache credential. + +There is no bundled NetworkPolicy reference manifest for LangCache yet +(unlike the self-managed Redis Agent Memory chart's +`networkpolicy.reference.yaml`). Write a NetworkPolicy for your cluster's CNI +that default-denies ingress to the LangCache Data Plane and Control Plane +pods, then allows TCP traffic on the Data Plane port (`8080` for static +caches, `9000` for Control Plane managed caches) and the Control Plane port +(`9100`) from approved callers only. diff --git a/content/operate/iris/langcache/self-managed/plan-deployment.md b/content/operate/iris/langcache/self-managed/plan-deployment.md new file mode 100644 index 0000000000..8b7a03eb4a --- /dev/null +++ b/content/operate/iris/langcache/self-managed/plan-deployment.md @@ -0,0 +1,47 @@ +--- +Title: Plan a self-managed LangCache deployment +alwaysopen: false +categories: +- docs +- operate +- iris +description: Choose a self-managed LangCache deployment mode before installing the Helm chart. +linkTitle: Plan a deployment +weight: 10 +hideListLinks: true +--- + +Choose the deployment mode before you create Redis databases, configuration +Secrets, or Helm values. + +## Deployment modes + +{{< table-scrollable >}} +| Mode | What it deploys | Redis databases | Data Plane auth | Start here | +| --- | --- | --- | --- | --- | +| Static caches | Data Plane only. Caches are declared directly in `dataplane.config.yaml`. | Cache Redis. | Disabled by default. Protect access with Kubernetes, ingress, gateway, or service-mesh controls, or enable the legacy per-cache token auth described in [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). | [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) | +| Control Plane managed caches | Data Plane, Control Plane, and (for agent-key auth) the shared Identity Service. Caches are created and managed at runtime. | Cache Redis and Metadata Redis. | Agent-key authentication through the Identity Service. | [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) | +{{< /table-scrollable >}} + +## Mode rules + +Do not combine static `metadata.caches` with Control Plane managed cache +metadata in the same Data Plane process. Static caches do not use Metadata +Redis. Control Plane managed caches use `metadata.loader: live` and require +Metadata Redis. + +Static caches use one embedding contract per cache, configured directly in +`dataplane.config.yaml`. Control Plane managed caches use one embedding +contract for the whole deployment: the Control Plane and Data Plane must be +configured with the same provider, model, and dimensions, and cache creation +cannot override it or supply per-cache embedding credentials. + +The walkthroughs in this section use `langcache` as the Helm release name for +the Data Plane. If you choose a different release name, update +release-derived service and deployment names in the verification commands. + +## Before you deploy + +1. Review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}). +1. Prepare the appropriate [Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}). +1. Follow either [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) or [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}). diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md new file mode 100644 index 0000000000..adf9bb676d --- /dev/null +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -0,0 +1,159 @@ +--- +Title: Self-managed LangCache prerequisites +alwaysopen: false +categories: +- docs +- operate +- iris +description: Review software, Redis, network, Secret, image, and sizing prerequisites for self-managed LangCache. +linkTitle: Prerequisites +weight: 20 +hideListLinks: true +--- + +LangCache self-managed is distributed as container images plus a Helm chart. +The published `langcache` chart deploys the LangCache Data Plane. The Control +Plane and, for Control Plane managed caches, the shared Identity Service are +distributed as container images that you deploy alongside the chart; see +[Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}). + +You provide the Redis databases, embedding provider credentials, Kubernetes +exposure, and license material used by the deployment. + +{{< note >}} +This guide is for system administrators deploying LangCache on a self-managed +Kubernetes cluster. +{{< /note >}} + +## What you need + +| Item | Where it comes from | +| ---- | ------------------- | +| Container images | LangCache Data Plane image, and, when the Control Plane is used, the LangCache Control Plane image. Provided by your Redis representative. | +| Helm chart | `langcache` chart, provided by your Redis representative. | +| Identity Service image | `redislabs/iris-identity-service` on Docker Hub, needed only for Control Plane managed caches with agent-key Data Plane authentication. | +| Redis databases | You provide Cache Redis and, for Control Plane managed caches, Metadata Redis. | +| License key | Contact your Redis representative or [contact sales](https://redis.io/contact/). | +| Provider credentials | You provide embedding provider credentials (currently an OpenAI-compatible provider). | + +{{< note >}} +LangCache self-managed does not yet have a public Docker Hub or Helm +repository the way self-managed Redis Agent Memory does. Get the chart +package and image references from your Redis representative and mirror them +into your own registry if needed. +{{< /note >}} + +## Required software + +| Software | Minimum version | Purpose | +| -------- | --------------- | ------- | +| Kubernetes | 1.19+ | Orchestration | +| kubectl | 1.19+ | Kubernetes CLI | +| Helm | 3.x | Package manager for the Data Plane chart | + +## Redis databases + +The Helm chart does not deploy Redis databases. Provision the Redis databases +outside the LangCache chart and pass their URLs in `dataplane.config.yaml` +and, when the Control Plane is used, `controlplane-onprem.config.yaml`. + +Cache Redis must support RediSearch with vector search, because LangCache +creates a RediSearch vector index per cache. Metadata Redis does not need that +capability. + +### Static caches + +Use static caches for a first install or a private single-cache deployment. +Caches are declared directly in `dataplane.config.yaml`. The Control Plane +and Metadata Redis are not used. + +{{< table-scrollable >}} +| Redis database | Required when | Configure in `dataplane.config.yaml` | Purpose | +| --- | --- | --- | --- | +| Cache Redis | Always | `metadata.caches[].urls` | Cache entry hashes and RediSearch vector indexes. | +{{< /table-scrollable >}} + +### Control Plane managed caches + +Use Control Plane managed caches when operators need to create or manage +caches at runtime. The Data Plane and Control Plane must resolve the same +`databaseId` to the same Cache Redis target and point at the same Metadata +Redis. + +{{< table-scrollable >}} +| Redis database | Required when | Configure in `dataplane.config.yaml` | Configure in `controlplane-onprem.config.yaml` | Purpose | +| --- | --- | --- | --- | --- | +| Cache Redis | Always | `databases..urls` | `databases..urls` | Cache entries for Control Plane managed caches. Both processes must define the same ``. | +| Metadata Redis | Always | `metadata.urls` | `metadata.urls` | Cache records and, for agent-key auth, key/grant records managed by the Identity Service. | +{{< /table-scrollable >}} + +For a lab deployment, Cache Redis and Metadata Redis can point to the same +Redis endpoint if it has the required modules and capacity. For production, +separate them so cache data and control metadata can be scaled, backed up, +and operated independently. + +### Metadata Redis durability + +Metadata Redis is small compared with Cache Redis, but it is operationally +critical. Use persistent storage, Redis authentication, network isolation, +and TLS where required. Avoid eviction of metadata keys; losing metadata +removes Control Plane cache records. + +## Network access + +- **Connected install:** the cluster must be able to pull the LangCache + images and, for Control Plane managed caches, the `iris-identity-service` + image. +- **Air-gapped install:** mirror the images into an internal registry. +- **Runtime access:** LangCache pods must reach the Redis databases and the + embedding provider endpoint used by the deployment. +- **Data Plane exposure:** use NetworkPolicy, ingress, gateway, service mesh, + private load balancer, or equivalent controls to restrict API access. + +## Credentials and Secrets + +The Data Plane chart consumes configuration and license material from +Kubernetes Secrets: + +| Secret | Required when | Default key | +| --- | --- | --- | +| LangCache license Secret | Always for the on-prem-hardened images | `license` | +| LangCache Data Plane config Secret | Always | `dataplane.config.yaml` | +| Control Plane config Secret | Control Plane used | `controlplane-onprem.config.yaml` | +| Control Plane admin-token Secret | Control Plane used | `token` | + +The config file is commonly mounted as a Secret because it can contain +embedding provider API keys and Redis URLs may include credentials. + +## System requirements + +Default chart values for the published `langcache` chart: + +| Component | Default | Purpose | +| --------- | ------- | ------- | +| LangCache Data Plane | 1 replica, autoscaling disabled | Data Plane API traffic | + +For production, review `replicaCount` and `autoscaling` and size explicitly +for the expected request volume; the chart's defaults are intended for a +first install, not a production HA recommendation. + +## Helm values to review + +The walkthroughs use `langcache` as the Helm release name. The generated +service and deployment names in the verification steps assume that release +name. + +{{< table-scrollable >}} +| Area | Values | Use when | +| --- | --- | --- | +| Image | `image.repository`, `image.tag`, `imagePullSecrets` | Selecting a release or private registry image. | +| Config | `config`, or `existingSecret`/`existingSecretChecksum` for an externally managed config Secret | Providing `dataplane.config.yaml` content. | +| Capacity | `resources`, `autoscaling.*` | Tuning request capacity or memory footprint. | +| Scheduling | `nodeSelector`, `affinity`, `tolerations` | Controlling pod placement. | +| Networking | `service.type`, `ingress.*` | Exposing LangCache outside the cluster. | +| Naming | `fullnameOverride` | Running more than one LangCache release in a namespace. | +| Service account | `serviceAccount.*` | Matching customer namespace security policy. | +| Cache-index provisioning | `initProvisioner.enabled`, `initProvisioner.config` | Running the `provision-cache-index` init container against static caches before the Data Plane starts. | +{{< /table-scrollable >}} + +Do not use floating image tags in production. diff --git a/content/operate/iris/langcache/self-managed/reference.md b/content/operate/iris/langcache/self-managed/reference.md new file mode 100644 index 0000000000..7dd0e58aaf --- /dev/null +++ b/content/operate/iris/langcache/self-managed/reference.md @@ -0,0 +1,60 @@ +--- +Title: Configuration and troubleshooting +alwaysopen: false +categories: +- docs +- operate +- iris +description: Review self-managed LangCache configuration, troubleshooting guidance, and reference links. +linkTitle: Configuration and troubleshooting +weight: 100 +hideListLinks: true +--- + +## Configuration reference + +Use these files to configure a self-managed deployment: + +| File | Purpose | +| --- | --- | +| `langcache-values.yaml` | Helm values for the Data Plane image, replicas, services, and Secret names. | +| `dataplane.config.yaml` | Data Plane caches, Redis URLs, auth mode, and embedding settings. | +| `controlplane-onprem.config.yaml` | Control Plane metadata Redis, database registry, admin-token auth, and embedding contract. | +| `license` | LangCache license file provided by Redis, required by the on-prem-hardened Control Plane and Data Plane binaries. | + +### External secret managers + +If you use an external secret manager, expose the license, config, and +admin-token material to the chart (or your Control Plane manifest) as +Kubernetes Secrets and set the chart's `existingSecret` values, or the +manifest's `secretName` references, to those Secret names. + +## Troubleshooting + +{{< table-scrollable >}} +| Symptom | Likely cause | Fix | +| --- | --- | --- | +| Docker pull fails for the configured image tag | Image tag is wrong, or the image has not been mirrored into a registry your cluster can reach | Use the image reference provided by your Redis representative and mirror it into your registry if needed. | +| Pod is stuck in `ImagePullBackOff` or `ErrImagePull` | Cluster cannot pull the configured image, image tag is wrong, registry requires credentials, or `imagePullSecrets` is missing/wrong | Verify `image.repository`, `image.tag`, registry reachability, and `imagePullSecrets`. | +| `helm install --atomic --wait` times out and rolls back | Cluster is small or image pull/startup takes longer than Helm's default timeout | Install without `--atomic --wait`, or set a longer `--timeout` and ensure enough cluster capacity. | +| Data Plane health fails | Pod not ready, config invalid, or Redis unavailable | Check pod logs and call `/health`, `/health/liveness`, and `/health/readiness`. | +| Data Plane fails to start with an on-prem-hardened image against static config | The on-prem-hardened Data Plane binary (`cmd/onprem`) only supports Control Plane managed caches with agent-key auth; it rejects static `metadata.caches` and other auth methods | Use the static-caches Data Plane image for static caches, or switch to Control Plane managed caches. | +| Cache search or set requests fail with an index error | The RediSearch vector index for the cache was never provisioned, or Cache Redis does not support RediSearch with vector search | Run `provision-cache-index` against the cache's config, or verify Cache Redis modules. | +| Control Plane `CreateCache` returns `424` | Cache Redis for the resolved `databaseId` is unreachable or does not satisfy LangCache's Redis module requirements | Check `databases..urls` connectivity and Redis modules. | +| Control Plane `CreateCache` returns `400` for embedding fields | Request tried to select a different embedding provider/model/dimensions than the deployment's single configured contract, or supplied per-cache embedding credentials | On-prem cache creation uses the deployment-wide embedding contract; it does not accept per-cache overrides or credentials. | +| Agent receives `401` on a Control Plane managed cache | Missing, malformed, revoked, expired, or invalid agent key, or the Data Plane cannot reach the Identity Service | Check the `Authorization` header, key status through the Identity Service, and Data Plane connectivity to `auth.agent_keys.introspection.base_url`. | +| Agent receives `403` on a Control Plane managed cache | Key exists but lacks the required `lc-cache:` grant or action | Update grants through the Identity Service's `/v1/api-keys/{keyId}` endpoint. | +| Cache created by the Control Plane is not visible to the Data Plane | CP and DP point at different Metadata Redis URLs, or the Data Plane is still running the static-caches binary | Make CP `metadata.urls` match DP `metadata.urls`, and confirm the Data Plane is running the on-prem-hardened (`cmd/onprem`) binary. | +| Legacy static-cache token is rejected | Token was generated with a different passphrase or resource ID than the running config | Regenerate the token with `generate-auth-token` against the exact `dataplane.config.yaml` in use. | +| NetworkPolicy blocks expected traffic | Placeholder namespace, release name, or caller selectors were not customized correctly | Check the Helm release label `app.kubernetes.io/instance`, caller namespace, and caller pod labels. | +{{< /table-scrollable >}} + +## References + +| Need | Reference | +| --- | --- | +| Helm chart values | `langcache/helm/values.yaml` in the LangCache source repository | +| LangCache API reference (Data Plane) | [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) | +| Control Plane API reference | [Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}) | +| LangCache overview | [LangCache overview]({{< relref "/develop/ai/context-engine/langcache" >}}) | +| Container images and chart access | Contact your Redis representative or [contact sales](https://redis.io/contact/) | From 60fb84a36acf4f30f7d5049c0d2aa4458b00e1df Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Fri, 4 Sep 2026 14:47:58 +0300 Subject: [PATCH 02/10] MOD-17747: Fix issues found by content review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _index.md: split the single Data Plane port entry into static-caches (8080) vs. Control Plane managed caches (9000) — they're different binaries with different defaults, and the single row was misleading. - data-plane-configuration.md: add the required embedding.endpoint.base_url to the Control Plane managed caches example; pkg/inference.Config.Validate requires it for non-noop providers, so the example would fail startup without it. - operations.md: correct the FIPS posture claim. The on-prem-hardened binaries are FIPS-*capable* (GOFIPS140), but ship with runtime FIPS mode off by default (GODEBUG=fips140=off); the strict rediss:// checks are opt-in, not automatic just from using the hardened image. - deploy-control-plane.md: add the missing Secret-mount steps (license, Identity Service introspection token) for the Data Plane, since the config example referenced mount paths the chart doesn't wire up on its own; uses the chart's existing generic volumes/volumeMounts passthrough. - authentication.md: strengthen the Identity Service caveat to note it needs its own control credential, a per-Data-Plane introspection credential, and product wiring — not just one extra container. Found via a Codex content/meaning review of the rendered staging pages, cross-checked against the actual Go source in the iris monorepo. Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/_index.md | 7 ++- .../langcache/self-managed/authentication.md | 6 ++- .../self-managed/data-plane-configuration.md | 6 ++- .../self-managed/deploy-control-plane.md | 43 +++++++++++++++++-- .../iris/langcache/self-managed/operations.md | 21 ++++++--- 5 files changed, 70 insertions(+), 13 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md index e3e27855ab..40c5cf9779 100644 --- a/content/operate/iris/langcache/self-managed/_index.md +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -36,12 +36,17 @@ A standard self-managed LangCache deployment contains: | Component | Purpose | Default service | | --- | --- | --- | -| LangCache Data Plane | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:8080` | +| LangCache Data Plane (static caches) | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:8080` | +| LangCache Data Plane (Control Plane managed caches) | The same runtime API, served by the on-prem-hardened binary that only supports Control Plane managed caches and agent-key auth. | `langcache:9000` | | LangCache Control Plane | Optional admin API for creating and managing caches. | `langcache-controlplane:9100` | | Identity Service | Shared suite service that issues and validates LangCache agent keys for Control Plane managed caches. | `iris-identity-service:9200` | | Cache Redis | Holds cache entries and RediSearch vector indexes. | Customer-provided | | Metadata Redis | Holds Control Plane cache records and, when agent-key auth is used, key/grant records. | Required for Control Plane managed caches | +Static caches and Control Plane managed caches use different Data Plane +binaries and default ports; see +[Plan a deployment]({{< relref "/operate/iris/langcache/self-managed/plan-deployment" >}}). + ### How the components work together The Data Plane handles runtime cache requests. The optional Control Plane diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md index 7d844231da..2aa4095782 100644 --- a/content/operate/iris/langcache/self-managed/authentication.md +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -179,7 +179,11 @@ curl -sS -X POST "$IDENTITY_SERVICE_URL/v1/api-keys" \ ``` {{< note >}} -The Identity Service is a shared, cross-product component. A full +The Identity Service is a shared, cross-product component, and deploying it +is more than running one extra container: it needs its own control-plane +credential (for the `/v1/api-keys` calls shown above), a separate runtime +introspection credential for each Data Plane that calls it, and its LangCache +product entry wired so grants resolve against real caches. A full self-managed deployment and administration guide for it is out of scope for this LangCache-specific documentation; see your Redis representative or the self-managed Redis Agent Memory Helm chart for a working reference diff --git a/content/operate/iris/langcache/self-managed/data-plane-configuration.md b/content/operate/iris/langcache/self-managed/data-plane-configuration.md index 2871a8472c..0417a9d8c8 100644 --- a/content/operate/iris/langcache/self-managed/data-plane-configuration.md +++ b/content/operate/iris/langcache/self-managed/data-plane-configuration.md @@ -124,6 +124,8 @@ auth: embedding: provider: openai + endpoint: + base_url: https://api.openai.com models: default_embedding_model: text-embedding-3-large dimensions: 3072 @@ -140,7 +142,9 @@ The `databases` map must use the same logical `` keys (here, both processes resolve `databaseId` to the same Cache Redis target. The `embedding` block must match the Control Plane's configured provider, model, and dimensions exactly; Control Plane managed caches cannot select a -different embedding model or supply per-cache credentials. +different embedding model or supply per-cache credentials. `embedding.endpoint.base_url` +is required for the OpenAI-compatible provider; the Data Plane fails startup +without it. For the Identity Service introspection settings, see [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). diff --git a/content/operate/iris/langcache/self-managed/deploy-control-plane.md b/content/operate/iris/langcache/self-managed/deploy-control-plane.md index 629a195f95..836b8b8229 100644 --- a/content/operate/iris/langcache/self-managed/deploy-control-plane.md +++ b/content/operate/iris/langcache/self-managed/deploy-control-plane.md @@ -201,6 +201,22 @@ CONFIG_CHECKSUM="$(shasum -a 256 ./dataplane.config.yaml | awk '{print $1}')" {{< /multitabs >}} +The Control Plane managed cache example in +[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}) +reads the license from `/etc/langcache/license` and the Identity Service +introspection credential from `/etc/langcache/introspection/token`. Neither +path is wired up by the chart's own values today, so mount them yourself +using the chart's generic `volumes`/`volumeMounts` passthrough. + +Create the introspection-token Secret. This is the shared credential the +Data Plane presents to the Identity Service when introspecting agent keys; +provision it as part of your Identity Service deployment: + +```bash +kubectl -n create secret generic langcache-introspection-token \ + --from-literal=token='' +``` + Create `langcache-values.yaml`: ```yaml @@ -211,12 +227,33 @@ image: config: existingSecret: langcache-config existingSecretChecksum: "" + +volumes: + - name: license + secret: + secretName: langcache-license + - name: introspection-token + secret: + secretName: langcache-introspection-token + +volumeMounts: + - name: license + mountPath: /etc/langcache/license + subPath: license + readOnly: true + - name: introspection-token + mountPath: /etc/langcache/introspection/token + subPath: token + readOnly: true ``` +The `subPath` mounts add the license and token files inside the directory +that the chart's own config volume already mounts, without replacing it. + The chart values shown throughout this guide reflect the current `langcache` -chart, which does not yet expose license or Control Plane fields. Once your -chart provides `controlplane.enabled` (or similar) support, prefer that over -the manual Deployment above. +chart, which does not yet expose dedicated license or Control Plane fields. +Once your chart provides `controlplane.enabled` (or similar) support, prefer +that over the manual Deployment and volume passthroughs above. ## Install the Data Plane chart diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index 10823a9d8b..e3fd941203 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -110,21 +110,28 @@ same way. ## FIPS-oriented posture The on-prem-hardened Control Plane and Data Plane binaries (used for Control -Plane managed caches) are built with a FIPS-oriented Go toolchain profile and -reject configuration that: +Plane managed caches) are built with a FIPS-capable Go toolchain (`GOFIPS140`), +but the shipped images run with that runtime FIPS mode turned **off** by +default (`GODEBUG=fips140=off`). The stricter posture checks only activate +when you turn Go's FIPS 140 runtime mode on for the container; they are not +automatic just because you're running the on-prem-hardened image. + +When Go's FIPS mode is enabled, the on-prem-hardened binaries reject +configuration that: - uses non-`rediss://` URLs for `metadata.urls`, `databases..urls`, or the Control Plane's `metadata.urls`; or - otherwise fails the shared FIPS Redis-URL posture check used across the Redis AI Services products. -This is not a formal FIPS 140 compliance or validation claim. Treat it as a -deployment posture and guardrail that must still be reviewed against the -customer's compliance boundary. +This is not a formal FIPS 140 compliance or validation claim. Treat it as an +opt-in deployment posture and guardrail that must still be reviewed against +the customer's compliance boundary, and confirm with your Redis +representative how to turn the runtime FIPS mode on for your deployment. The static-caches Data Plane image (used by the published `langcache` chart -today) does not build with this FIPS profile; it is the same image used for -LangCache on Redis Cloud. +today) does not build with the FIPS-capable toolchain at all; it is the same +image used for LangCache on Redis Cloud. The LangCache API listener itself speaks HTTP inside the cluster. Edge TLS termination is owned by the hosting environment, such as ingress, service From 4eb3fec94540cb6b2bca90f7be3fd4a884228bb5 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Fri, 4 Sep 2026 14:57:12 +0300 Subject: [PATCH 03/10] MOD-17747: Fix chart-value and naming bugs found by content review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The langcache chart takes dataplane.config.yaml inline as the `config` value, rendered into a ConfigMap — it has no existingSecret/ existingSecretChecksum option for it (that's an RS-Agent-Memory-chart convention I'd copied without checking against this chart's actual values.yaml/configmap.yaml). Corrected across deploy-static.md, deploy-control-plane.md, prerequisites.md, reference.md, and operations.md: - Config is now shown inline under `config:` in the Helm values examples, with an explicit callout that this renders to a ConfigMap (not a Secret) so the values file itself should be treated as sensitive. - License and Identity Service introspection-token files (which the chart doesn't support at all) are now mounted via the chart's generic volumes/volumeMounts passthrough, using dedicated directories (/etc/license, /etc/introspection) instead of subPath mounts into /etc/langcache — subPath mounts don't pick up Secret updates without a pod restart, whole-directory mounts do. - Removed the SHA-256-checksum-based rollout pattern for config/license (it assumed a chart field, existingSecretChecksum, that doesn't exist); replaced with explicit `kubectl rollout restart` guidance for license and introspection-token rotation in operations.md. - Added `nameOverride`/`fullnameOverride: langcache` to the values examples so the chart's actual default resource names (derived from nameOverride=langcache-app) don't silently mismatch the `svc/langcache`, `deploy/langcache`, and `app.kubernetes.io/name=langcache` used throughout the verification commands. - deploy-control-plane.md: added `service.port: 9000` since the managed-cache Data Plane binary's default port doesn't match the chart's default service.port (8080); fixed the intro note, which claimed the page deploys the Identity Service when it doesn't. - authentication.md: `full` grant wording corrected to not imply it grants Control Plane admin API access. - api-examples.md: noted the 8080/9000 port split for static vs. Control-Plane-managed Data Plane calls. Found via a second Codex content/meaning review pass, cross-checked against the actual Go source, Helm chart, and Kubernetes subPath semantics. Co-Authored-By: Claude Sonnet 5 --- .../langcache/self-managed/api-examples.md | 1 + .../langcache/self-managed/authentication.md | 2 +- .../self-managed/data-plane-configuration.md | 36 +++-- .../self-managed/deploy-control-plane.md | 131 ++++++++++-------- .../langcache/self-managed/deploy-static.md | 62 +++++++-- .../iris/langcache/self-managed/operations.md | 51 +++---- .../langcache/self-managed/prerequisites.md | 24 ++-- .../iris/langcache/self-managed/reference.md | 19 ++- 8 files changed, 201 insertions(+), 125 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md index e6158e3484..58ff507736 100644 --- a/content/operate/iris/langcache/self-managed/api-examples.md +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -114,6 +114,7 @@ curl -sS "$CP_URL/v1/embedding-providers" \ Set variables: ```bash +# Port 8080 for static caches; port 9000 for Control Plane managed caches. DP_URL="http://localhost:8080" CACHE_ID="" LC_TOKEN="" diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md index 2aa4095782..d009e3fa7b 100644 --- a/content/operate/iris/langcache/self-managed/authentication.md +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -156,7 +156,7 @@ Grant actions: | --- | --- | | `read` | Read and search cache entries. | | `write` | Mutate cache entries. `write` implies `read`. | -| `full` | Full cache administration through the grant. `full` implies `write`. | +| `full` | Full cache access through the grant. `full` implies `write`. This is a resource permission, not a substitute for the Control Plane admin token; it doesn't grant access to Control Plane administration APIs. | Mint and manage agent keys directly against the Identity Service (not the LangCache Control Plane): diff --git a/content/operate/iris/langcache/self-managed/data-plane-configuration.md b/content/operate/iris/langcache/self-managed/data-plane-configuration.md index 0417a9d8c8..7151ac9ea8 100644 --- a/content/operate/iris/langcache/self-managed/data-plane-configuration.md +++ b/content/operate/iris/langcache/self-managed/data-plane-configuration.md @@ -11,9 +11,12 @@ weight: 30 hideListLinks: true --- -The Data Plane reads `dataplane.config.yaml` from a Kubernetes Secret. Use one -cache mode: static caches or Control Plane managed caches. The two modes use -different Data Plane binaries and config shapes. +The Data Plane reads `dataplane.config.yaml`. The published `langcache` chart +provides this content inline under the `config` Helm value, which the chart +renders into a ConfigMap (not a Secret) — see +[Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}). +Use one cache mode: static caches or Control Plane managed caches. The two +modes use different Data Plane binaries and config shapes. ## Shared settings @@ -120,7 +123,7 @@ auth: base_url: https://iris-identity-service:9200 product: langcache credential: - token_file: /etc/langcache/introspection/token + token_file: /etc/introspection/token embedding: provider: openai @@ -134,7 +137,7 @@ embedding: api_key: "" license: - license_path: /etc/langcache/license + license_path: /etc/license/license ``` The `databases` map must use the same logical `` keys (here, @@ -149,11 +152,18 @@ without it. For the Identity Service introspection settings, see [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). -## Secret key - -Create the Data Plane config Secret with the key `dataplane.config.yaml`: - -```bash -kubectl -n create secret generic langcache-config \ - --from-file=dataplane.config.yaml=./dataplane.config.yaml -``` +## Config storage + +The published `langcache` chart takes `dataplane.config.yaml` as the inline +`config` Helm value and renders it into a Kubernetes ConfigMap, not a Secret. +Because this config commonly contains embedding provider credentials and +Redis URLs with embedded credentials, treat the values file itself (and any +CI/CD pipeline that renders it) as sensitive, the same as you would a +Secret. If your security policy requires Secret-backed storage for this +content instead, mount a Secret through the chart's generic +`volumes`/`volumeMounts` values and override `args` to point at the mounted +path instead of the default `/etc/langcache/dataplane.config.yaml`. + +The chart automatically restarts Data Plane pods when the rendered +ConfigMap content changes on `helm upgrade`; no separate checksum value is +needed for `config` itself. diff --git a/content/operate/iris/langcache/self-managed/deploy-control-plane.md b/content/operate/iris/langcache/self-managed/deploy-control-plane.md index 836b8b8229..92d53ce0ff 100644 --- a/content/operate/iris/langcache/self-managed/deploy-control-plane.md +++ b/content/operate/iris/langcache/self-managed/deploy-control-plane.md @@ -17,16 +17,22 @@ Metadata Redis, and the Control Plane provisions the RediSearch index in Cache Redis when it creates a cache. {{< note >}} -The published `langcache` Helm chart currently templates only the Data Plane. -This page deploys the Control Plane, and (for agent-key auth) the Identity -Service, as plain Kubernetes manifests using the images provided by your -Redis representative. Chart support for these components is expected in a -future release; check with your Redis representative for the current state. +The published `langcache` Helm chart currently templates only the Data +Plane. This page deploys the Control Plane as a plain Kubernetes manifest +using the image provided by your Redis representative. Chart support for +the Control Plane is expected in a future release; check with your Redis +representative for the current state. + +This page does not deploy the Identity Service, which agent-key Data Plane +authentication also depends on; see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) +for what that component requires and why deploying it is out of scope here. {{< /note >}} Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) -and create `dataplane.config.yaml` from the -[Control Plane managed caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}). +and the +[Control Plane managed caches config example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}), +which you'll paste into the Data Plane's Helm values below. ## Create the namespace @@ -36,20 +42,14 @@ kubectl create namespace ## Create shared Secrets -Create the license Secret: +Create the license Secret. Both the Control Plane manifest below and the +Data Plane values further down mount this same Secret: ```bash kubectl -n create secret generic langcache-license \ --from-file=license=./license ``` -Create the Data Plane config Secret: - -```bash -kubectl -n create secret generic langcache-config \ - --from-file=dataplane.config.yaml=./dataplane.config.yaml -``` - ## Create the Control Plane config Create `controlplane-onprem.config.yaml`: @@ -63,7 +63,7 @@ auth: token_file: /etc/controlplane-onprem/admin/token license: - license_path: /etc/langcache/license + license_path: /etc/license/license metadata: urls: @@ -138,7 +138,7 @@ spec: mountPath: /etc/controlplane-onprem/admin readOnly: true - name: license - mountPath: /etc/langcache + mountPath: /etc/license readOnly: true readinessProbe: httpGet: @@ -179,34 +179,12 @@ kubectl apply -f langcache-controlplane.yaml ## Create Helm values for the Data Plane -Create SHA-256 checksums for externally managed Secrets. These values are -used by Helm values to roll pods after Secret changes; they are not used to -validate Secret integrity. - -{{< multitabs id="langcache-control-plane-secret-checksums" -tab1="Linux" -tab2="macOS" >}} - -```bash -LICENSE_CHECKSUM="$(sha256sum ./license | awk '{print $1}')" -CONFIG_CHECKSUM="$(sha256sum ./dataplane.config.yaml | awk '{print $1}')" -``` - --tab-sep- - -```bash -LICENSE_CHECKSUM="$(shasum -a 256 ./license | awk '{print $1}')" -CONFIG_CHECKSUM="$(shasum -a 256 ./dataplane.config.yaml | awk '{print $1}')" -``` - -{{< /multitabs >}} - -The Control Plane managed cache example in -[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}) -reads the license from `/etc/langcache/license` and the Identity Service -introspection credential from `/etc/langcache/introspection/token`. Neither -path is wired up by the chart's own values today, so mount them yourself -using the chart's generic `volumes`/`volumeMounts` passthrough. +The published `langcache` chart takes `dataplane.config.yaml` inline as the +`config` value — there is no `existingSecret` option for it. It also has no +built-in fields for the license file or the Identity Service introspection +credential, so mount those two as Secrets yourself using the chart's generic +`volumes`/`volumeMounts` passthrough, at paths that don't overlap with the +chart's own config mount at `/etc/langcache`. Create the introspection-token Secret. This is the shared credential the Data Plane presents to the Identity Service when introspecting agent keys; @@ -217,16 +195,57 @@ kubectl -n create secret generic langcache-introspection-token --from-literal=token='' ``` -Create `langcache-values.yaml`: +Create `langcache-values.yaml`, using the +[Control Plane managed caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}) +for `config`: ```yaml +nameOverride: langcache +fullnameOverride: langcache + image: repository: /langcache-dataplane tag: "" +# The on-prem-hardened Data Plane binary listens on 9000 by default; +# override the chart's default service port (8080) to match. +service: + port: 9000 + config: - existingSecret: langcache-config - existingSecretChecksum: "" + server: + port: 9000 + profile: prod + metadata: + urls: + - redis://redis-meta:6379 + cache_ttl: 1m + databases: + cache-primary: + name: cache-primary + urls: + - redis://cache-primary:6379 + auth: + agent_keys: + enabled: true + product: langcache + introspection: + base_url: https://iris-identity-service:9200 + product: langcache + credential: + token_file: /etc/introspection/token + embedding: + provider: openai + endpoint: + base_url: https://api.openai.com + models: + default_embedding_model: text-embedding-3-large + dimensions: 3072 + credentials: + type: static + api_key: "" + license: + license_path: /etc/license/license volumes: - name: license @@ -238,17 +257,21 @@ volumes: volumeMounts: - name: license - mountPath: /etc/langcache/license - subPath: license + mountPath: /etc/license readOnly: true - name: introspection-token - mountPath: /etc/langcache/introspection/token - subPath: token + mountPath: /etc/introspection readOnly: true ``` -The `subPath` mounts add the license and token files inside the directory -that the chart's own config volume already mounts, without replacing it. +As with static caches, this `config` block ends up in a ConfigMap, so treat +`langcache-values.yaml` as sensitive. The `volumes`/`volumeMounts` entries +above are whole-directory mounts rather than `subPath` mounts, so Kubernetes +refreshes the mounted license and introspection-credential files +automatically when the backing Secret changes — no pod restart required to +pick up new file content (the running process still decides how often it +re-reads them; see [Operations]({{< relref "/operate/iris/langcache/self-managed/operations" >}}) +for license/token rotation). The chart values shown throughout this guide reflect the current `langcache` chart, which does not yet expose dedicated license or Control Plane fields. diff --git a/content/operate/iris/langcache/self-managed/deploy-static.md b/content/operate/iris/langcache/self-managed/deploy-static.md index 14c563fa14..8937b359c6 100644 --- a/content/operate/iris/langcache/self-managed/deploy-static.md +++ b/content/operate/iris/langcache/self-managed/deploy-static.md @@ -17,8 +17,9 @@ deployment does not include the Control Plane and does not use Metadata Redis. This is the mode the published `langcache` Helm chart deploys today. Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) -and create `dataplane.config.yaml` from the -[static caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}}). +and the +[static caches config example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}}), +which you'll paste into the Helm values below. ## Create the namespace @@ -26,34 +27,65 @@ and create `dataplane.config.yaml` from the kubectl create namespace ``` -## Create the config Secret - -```bash -kubectl -n create secret generic langcache-config \ - --from-file=dataplane.config.yaml=./dataplane.config.yaml -``` - ## Create Helm values -Create `langcache-values.yaml`: +The published `langcache` chart takes `dataplane.config.yaml` inline as the +`config` value; there is no `existingSecret` option for it. Paste the +content of your `dataplane.config.yaml` (from the +[static caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}})) +under `config` in `langcache-values.yaml`: ```yaml +nameOverride: langcache +fullnameOverride: langcache + image: repository: /langcache tag: "" config: - existingSecret: langcache-config + server: + port: 8080 + profile: prod + metadata: + loader: static + cache_ttl: 1m + caches: + - id: my-cache + urls: + - redis://cache-redis:6379 + index: idx:my-cache + model: + type: openai + name: text-embedding-3-large + dimensions: 3072 + attributes: [] + default_ttl: 60000 + default_search_threshold: 0.9 + search_strategies: + default_strategies: + - semantic + embeddings: + openai: + default: + base_url: https://api.openai.com initProvisioner: enabled: true config: /etc/langcache/dataplane.config.yaml ``` -`config.existingSecret` points the chart at the config Secret you created. -`initProvisioner.enabled: true` runs `provision-cache-index --ignore` as an -init container so cache indexes exist before the Data Plane starts, without -recreating indexes that already exist. +Because the chart renders `config` into a ConfigMap rather than a Secret, +treat `langcache-values.yaml` itself as sensitive — it contains any +embedding provider credentials and Redis URL credentials you configure. See +[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}) +for a Secret-backed alternative. + +`nameOverride`/`fullnameOverride` make the rendered resource names match the +`langcache` names used in the verification commands below; the chart's own +default names are longer. `initProvisioner.enabled: true` runs +`provision-cache-index --ignore` as an init container so cache indexes exist +before the Data Plane starts, without recreating indexes that already exist. ## Install the chart diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index e3fd941203..ce4e8598a9 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -19,8 +19,9 @@ hideListLinks: true - Back up Metadata Redis for Control Plane managed caches. Losing metadata removes Control Plane cache records. - Back up any external secret manager material used to recreate Kubernetes - Secrets, including the license, Data Plane config, Control Plane config, - and admin-token Secrets. + Secrets, including the license, Control Plane config, and admin-token + Secrets. Back up your Helm values file too — the Data Plane's config is + provided inline through Helm values, not a Secret. - For Metadata Redis, use persistent storage and an eviction policy that does not evict cache records under memory pressure. @@ -37,45 +38,39 @@ kubectl -n create secret generic langcache-controlplane-admin-t -o yaml | kubectl apply -f - ``` -Rotate the LangCache license by updating the license Secret and changing -`config.existingSecretChecksum` (or the equivalent value for your chart -version) so Helm rolls the Data Plane pods. +Rotate the LangCache license by updating the license Secret, then restart +the pods that mount it so they pick up the new file: ```bash kubectl -n create secret generic langcache-license \ --from-file=license=./license \ --dry-run=client \ -o yaml | kubectl apply -f - -``` - -Calculate the new SHA-256 checksum. This value is used by Helm values to roll -pods after the license Secret changes; it is not used to validate Secret -integrity. - -{{< multitabs id="langcache-license-secret-checksum" -tab1="Linux" -tab2="macOS" >}} - -```bash -LICENSE_CHECKSUM="$(sha256sum ./license | awk '{print $1}')" -``` --tab-sep- - -```bash -LICENSE_CHECKSUM="$(shasum -a 256 ./license | awk '{print $1}')" +kubectl -n rollout restart deploy/langcache +kubectl -n rollout restart deploy/langcache-controlplane +kubectl -n rollout status deploy/langcache +kubectl -n rollout status deploy/langcache-controlplane ``` -{{< /multitabs >}} +The license and introspection-token Secrets in this guide are mounted as +whole-directory volumes (not `subPath`), so Kubernetes refreshes the mounted +files automatically within about a minute of the Secret change. Restart the +pods anyway: LangCache shares its license-handling code with self-managed +Redis Agent Memory, which reads and validates the license file at process +startup and does not guarantee it re-reads a replaced file without a +restart. -Apply the updated values and verify the workload rolled: +Rotate the Identity Service introspection-token Secret the same way, then +restart the Data Plane: ```bash -helm upgrade langcache ./langcache \ - --namespace \ - -f langcache-values.yaml +kubectl -n create secret generic langcache-introspection-token \ + --from-literal=token='' \ + --dry-run=client \ + -o yaml | kubectl apply -f - -kubectl -n rollout status deploy/langcache +kubectl -n rollout restart deploy/langcache ``` Rotate agent keys minted for Control Plane managed caches through the diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md index adf9bb676d..1d74b8a7bf 100644 --- a/content/operate/iris/langcache/self-managed/prerequisites.md +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -112,18 +112,26 @@ removes Control Plane cache records. ## Credentials and Secrets -The Data Plane chart consumes configuration and license material from -Kubernetes Secrets: +The published `langcache` chart takes the Data Plane's `dataplane.config.yaml` +inline as a Helm value; the chart renders it into a ConfigMap, not a Secret. +Because that config can contain embedding provider API keys and Redis URLs +with credentials, treat the values file itself as sensitive. If your +security policy requires Secret-backed storage for it instead, mount a +Secret through the chart's generic `volumes`/`volumeMounts` values; see +[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}). + +The license file and, for Control Plane managed caches, the Identity Service +introspection credential are not wired into the chart's values at all today; +mount them yourself as Secrets the same way. The Control Plane (deployed as +a plain manifest until it's chart-packaged) uses real Kubernetes Secrets +throughout: | Secret | Required when | Default key | | --- | --- | --- | -| LangCache license Secret | Always for the on-prem-hardened images | `license` | -| LangCache Data Plane config Secret | Always | `dataplane.config.yaml` | +| LangCache license Secret | Control Plane managed caches | `license` | | Control Plane config Secret | Control Plane used | `controlplane-onprem.config.yaml` | | Control Plane admin-token Secret | Control Plane used | `token` | - -The config file is commonly mounted as a Secret because it can contain -embedding provider API keys and Redis URLs may include credentials. +| Identity Service introspection-token Secret | Agent-key Data Plane auth used | `token` | ## System requirements @@ -147,7 +155,7 @@ name. | Area | Values | Use when | | --- | --- | --- | | Image | `image.repository`, `image.tag`, `imagePullSecrets` | Selecting a release or private registry image. | -| Config | `config`, or `existingSecret`/`existingSecretChecksum` for an externally managed config Secret | Providing `dataplane.config.yaml` content. | +| Config | `config` (inline `dataplane.config.yaml` content) | Configuring caches, embeddings, and auth. Renders into a ConfigMap; treat the values file as sensitive. | | Capacity | `resources`, `autoscaling.*` | Tuning request capacity or memory footprint. | | Scheduling | `nodeSelector`, `affinity`, `tolerations` | Controlling pod placement. | | Networking | `service.type`, `ingress.*` | Exposing LangCache outside the cluster. | diff --git a/content/operate/iris/langcache/self-managed/reference.md b/content/operate/iris/langcache/self-managed/reference.md index 7dd0e58aaf..9920a11c78 100644 --- a/content/operate/iris/langcache/self-managed/reference.md +++ b/content/operate/iris/langcache/self-managed/reference.md @@ -17,17 +17,24 @@ Use these files to configure a self-managed deployment: | File | Purpose | | --- | --- | -| `langcache-values.yaml` | Helm values for the Data Plane image, replicas, services, and Secret names. | -| `dataplane.config.yaml` | Data Plane caches, Redis URLs, auth mode, and embedding settings. | +| `langcache-values.yaml` | Helm values for the Data Plane image, replicas, services, and inline `dataplane.config.yaml` content. Treat this file as sensitive. | +| `dataplane.config.yaml` | Data Plane caches, Redis URLs, auth mode, and embedding settings; provided inline under the chart's `config` value. | | `controlplane-onprem.config.yaml` | Control Plane metadata Redis, database registry, admin-token auth, and embedding contract. | | `license` | LangCache license file provided by Redis, required by the on-prem-hardened Control Plane and Data Plane binaries. | ### External secret managers -If you use an external secret manager, expose the license, config, and -admin-token material to the chart (or your Control Plane manifest) as -Kubernetes Secrets and set the chart's `existingSecret` values, or the -manifest's `secretName` references, to those Secret names. +The license, Control Plane config, Control Plane admin-token, and Identity +Service introspection-token material in this guide are all real Kubernetes +Secrets. If you use an external secret manager, expose that material as +Kubernetes Secrets and reference those Secret names in the Control Plane +manifest's `secretName` fields or the Data Plane chart's generic +`volumes`/`volumeMounts` values. + +The Data Plane's `dataplane.config.yaml` content itself is a Helm value +(`config`), not a Secret, in the current chart; see +[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}) +for a Secret-backed alternative if your security policy requires one. ## Troubleshooting From 29ed4685081cff4658e028f81eaf17b043fdd53b Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:15:28 +0300 Subject: [PATCH 04/10] MOD-17747: Rewrite self-managed LangCache docs for the current on-prem chart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Static caches / "Data Plane only" self-managed LangCache is no longer a thing: since MOD-17459 ("Evolve langcache/helm into the canonical LangCache on-prem chart") and MOD-17460 (removing the on-prem Data Plane's own database registry), the langcache chart always installs the Data Plane, Control Plane, and a bundled-or-external Identity Service together. There is no deployment-mode choice anymore and no supported no-Control-Plane path — the previous docs described an earlier, now-superseded shape of the product (a DP-only chart, a hand-rolled CP manifest, no public images). Rewritten against langcache/helm/{values.yaml,README.md,Chart.yaml}, controlplane-onprem/dataplane on-prem config structs, and development/langcache/onprem/*.config.yaml at origin/main (HEAD's checkout of this reference repo was 15 commits behind and missing all of this): - Removed plan-deployment.md and deploy-static.md — no modes to choose. - Renamed deploy-control-plane.md -> deploy.md: one `helm install` now stands up DP+CP+IdS together; no more manual Control Plane Deployment manifest, the chart templates it. - Renamed data-plane-configuration.md -> configuration.md: config is now a values.yaml (non-secret structure) + per-component overlay Secret (Redis URLs, database registry, embedding credential) split, chart-native end to end, replacing the old hand-mounted subPath workarounds. - authentication.md: agent-key auth via Identity Service (bundled or external) is the only Data Plane auth mode; dropped the legacy static-cache-token material entirely, since static caches aren't part of this product's self-managed shape anymore. - operations.md: rotation now uses the chart's real `*.existingSecretChecksum` mechanism; added the chart's own FIPS posture, support bundle, and preflight features, all newly chart-native. - _index.md/reference.md: updated component list, ports, and images (redislabs/iris-langcache-data, iris-langcache-control, iris-identity-service — now published to public Docker Hub, closing the "no public registry" gap noted in the previous revision). Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/_index.md | 101 ++---- .../langcache/self-managed/api-examples.md | 77 ++++- .../langcache/self-managed/authentication.md | 252 +++++++------- .../langcache/self-managed/configuration.md | 156 +++++++++ .../self-managed/data-plane-configuration.md | 169 --------- .../self-managed/deploy-control-plane.md | 326 ------------------ .../langcache/self-managed/deploy-static.md | 149 -------- .../iris/langcache/self-managed/deploy.md | 198 +++++++++++ .../iris/langcache/self-managed/operations.md | 240 ++++++++----- .../langcache/self-managed/plan-deployment.md | 47 --- .../langcache/self-managed/prerequisites.md | 210 ++++++----- .../iris/langcache/self-managed/reference.md | 46 ++- 12 files changed, 851 insertions(+), 1120 deletions(-) create mode 100644 content/operate/iris/langcache/self-managed/configuration.md delete mode 100644 content/operate/iris/langcache/self-managed/data-plane-configuration.md delete mode 100644 content/operate/iris/langcache/self-managed/deploy-control-plane.md delete mode 100644 content/operate/iris/langcache/self-managed/deploy-static.md create mode 100644 content/operate/iris/langcache/self-managed/deploy.md delete mode 100644 content/operate/iris/langcache/self-managed/plan-deployment.md diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md index 40c5cf9779..f1bca1f321 100644 --- a/content/operate/iris/langcache/self-managed/_index.md +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -26,46 +26,41 @@ documents the self-managed admin endpoints for caches. {{< note >}} Self-managed LangCache is available as a private preview. You need a license -key and access to the container images and Helm chart. Contact your Redis -representative or [contact sales](https://redis.io/contact/). +key to deploy it. Contact your Redis representative or +[contact sales](https://redis.io/contact/). {{< /note >}} ## What you are deploying -A standard self-managed LangCache deployment contains: +One `helm install` of the `langcache` chart always creates the Data Plane and +the Control Plane, plus either a bundled or an external Identity Service. +There is no lighter-weight "Data Plane only" install for self-managed +LangCache — every cache is created and managed through the Control Plane, and +every Data Plane request is authenticated by the Identity Service. | Component | Purpose | Default service | | --- | --- | --- | -| LangCache Data Plane (static caches) | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:8080` | -| LangCache Data Plane (Control Plane managed caches) | The same runtime API, served by the on-prem-hardened binary that only supports Control Plane managed caches and agent-key auth. | `langcache:9000` | -| LangCache Control Plane | Optional admin API for creating and managing caches. | `langcache-controlplane:9100` | -| Identity Service | Shared suite service that issues and validates LangCache agent keys for Control Plane managed caches. | `iris-identity-service:9200` | -| Cache Redis | Holds cache entries and RediSearch vector indexes. | Customer-provided | -| Metadata Redis | Holds Control Plane cache records and, when agent-key auth is used, key/grant records. | Required for Control Plane managed caches | - -Static caches and Control Plane managed caches use different Data Plane -binaries and default ports; see -[Plan a deployment]({{< relref "/operate/iris/langcache/self-managed/plan-deployment" >}}). +| LangCache Data Plane | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:9000` | +| LangCache Control Plane | Admin API for creating and managing caches. | `langcache-controlplane:9100` | +| Identity Service | Issues and validates the agent keys the Data Plane requires. Bundled by the chart (default) or an external instance your suite already runs. | `langcache-identity-service:9200` (bundled mode) | +| Cache Redis | Holds cache entries and RediSearch vector indexes. Registered by ID in the Control Plane's database registry — the Data Plane has no database registry of its own. | Customer-provided | +| Metadata Redis | Holds Control Plane cache records. Can be the same Redis instance as Cache Redis, in a separate keyspace. | Customer-provided | ### How the components work together -The Data Plane handles runtime cache requests. The optional Control Plane -handles cache administration. - -| Flow | Caller | Service | Backing Redis | -| --- | --- | --- | --- | -| Cache administration | Platform admin | LangCache Control Plane | Metadata Redis, Cache Redis (to provision the index) | -| Agent-key issuance and grants | Platform admin | Identity Service | Metadata Redis | -| Runtime cache requests | Agent, app, or gateway | LangCache Data Plane | Cache Redis | - -1. Platform admins use the Control Plane to create and manage caches. -1. The Control Plane writes cache records to Metadata Redis and synchronously - provisions the RediSearch vector index in Cache Redis. -1. When agent-key auth is used, platform admins mint keys and grants through - the Identity Service. -1. Agents and applications call the Data Plane with a cache ID. -1. The Data Plane resolves cache metadata (static config or, for Control Plane - managed caches, Metadata Redis) and reads or writes entries in Cache Redis. +1. Platform admins use the Control Plane to create and manage caches, + selecting a Cache Redis target by `databaseId` from the Control Plane's + own database registry. +1. The Control Plane writes cache records to Metadata Redis, including the + resolved Redis URLs for that cache, and synchronously provisions the + RediSearch vector index in Cache Redis. +1. Platform admins mint agent keys through the Identity Service, granting + `lc-cache:` permissions. +1. Agents and applications call the Data Plane with a cache ID and an agent + key. +1. The Data Plane introspects the key against the Identity Service, reads + the cache's metadata (including its Redis URLs) from Metadata Redis, and + reads or writes entries in Cache Redis. ### API surfaces @@ -78,47 +73,7 @@ boundary for cached entries. | Conversational search | `/v1/caches/{cacheId}/conversations/search` | Search using conversation history context. | | Cache health | `/v1/caches/{cacheId}/health` | Cache-scoped health status. | | Control Plane | `/v1/caches`, `/v1/embedding-providers` | Self-managed administration for caches. | +| Identity Service | `/v1/api-keys` | Mint, list, update, revoke, and rotate agent keys and their cache grants. | -## Deployment modes - -Start with [Plan a deployment]({{< relref "/operate/iris/langcache/self-managed/plan-deployment" >}}) -to choose between static caches and Control Plane managed caches. - -| If you need to | Go to | -| --- | --- | -| Review software, Redis, network, Secret, image, and sizing requirements | [Prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) | -| Prepare `dataplane.config.yaml` for either deployment mode | [Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}) | -| Deploy a first-install or single-cache setup without the Control Plane | [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) | -| Deploy runtime cache administration | [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) | - -Do not combine static `metadata.caches` with Control Plane managed cache -metadata in the same Data Plane process. Static caches do not use Metadata -Redis. Control Plane managed caches use `metadata.loader: live` and require -Metadata Redis. - -{{< warning >}} -Do not expose an auth-disabled Data Plane to untrusted callers. Static caches -default to no Data Plane authentication; any caller that can reach the API can -read or write cached entries for configured caches. Use that mode only when -Kubernetes NetworkPolicy, private service exposure, ingress/gateway policy, -service mesh, or equivalent controls restrict access to trusted components. -{{< /warning >}} - -## Availability and packaging - -Self-managed LangCache is newer than self-managed Redis Agent Memory (RAM) and -its packaging is still catching up: - -- The published `langcache` Helm chart currently deploys only the Data Plane. - It does not yet have a `controlplane.enabled` toggle like the RAM chart. - [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) - shows how to run the Control Plane as a plain Kubernetes Deployment using the - Control Plane container image until chart support ships. -- Control Plane managed caches with agent-key Data Plane authentication depend - on the shared Identity Service, the same suite component RAM's chart - installs as `redis-agent-memory-identity-service`. LangCache's chart does - not template it yet either; see - [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). -- There is currently no public Docker Hub or Helm repository for LangCache - self-managed artifacts. Get the chart and images from your Redis - representative. +Start with [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}), +then follow [Deploy self-managed LangCache]({{< relref "/operate/iris/langcache/self-managed/deploy" >}}). diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md index 58ff507736..f0e6e0929f 100644 --- a/content/operate/iris/langcache/self-managed/api-examples.md +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -5,17 +5,15 @@ categories: - docs - operate - iris -description: Use curl examples with the LangCache self-managed Control Plane and Data Plane APIs. +description: Use curl examples with the LangCache self-managed Control Plane, Identity Service, and Data Plane APIs. linkTitle: Self-managed API examples -weight: 70 +weight: 50 hideListLinks: true --- -These examples show self-managed Control Plane and Data Plane requests. - -They assume either an auth-disabled private Data Plane, the legacy per-cache -token described in [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}), -or agent-key auth for a Control Plane managed cache. +These examples show self-managed Control Plane, Identity Service, and Data +Plane requests. They assume agent-key authentication as described in +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). For the complete shared Data Plane schema, see the [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}). @@ -109,25 +107,66 @@ curl -sS "$CP_URL/v1/embedding-providers" \ -H "Authorization: Bearer $LC_ADMIN_TOKEN" ``` +## Identity Service API examples + +Set variables: + +```bash +IDS_URL="http://localhost:9200" +IDS_CONTROL_TOKEN="" +``` + +Mint an agent key scoped to one cache: + +```bash +curl -sS -X POST "$IDS_URL/v1/api-keys" \ + -H "Authorization: Bearer $IDS_CONTROL_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-agent-key", + "grants": [ + { + "product": "langcache", + "resourceType": "lc-cache", + "resourceId": "", + "actions": ["read", "write"] + } + ] + }' +``` + +Response: + +```json +{ + "keyId": "0123456789abcdef0123456789abcdef", + "token": "", + "createdAt": 1780000000 +} +``` + +Rotate it later: + +```bash +curl -sS -X POST "$IDS_URL/v1/api-keys//rotate" \ + -H "Authorization: Bearer $IDS_CONTROL_TOKEN" +``` + ## Data Plane API examples Set variables: ```bash -# Port 8080 for static caches; port 9000 for Control Plane managed caches. -DP_URL="http://localhost:8080" +DP_URL="http://localhost:9000" CACHE_ID="" -LC_TOKEN="" +LC_AGENT_KEY="" ``` -For auth-disabled deployments, omit the `Authorization` header and rely on -the deployment's hosting controls. - ### Set a cache entry ```bash curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries" \ - -H "Authorization: Bearer $LC_TOKEN" \ + -H "Authorization: Bearer $LC_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "What is the capital of France?", @@ -139,7 +178,7 @@ curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries" \ ```bash curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries/search" \ - -H "Authorization: Bearer $LC_TOKEN" \ + -H "Authorization: Bearer $LC_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "What'"'"'s the capital city of France?" @@ -150,14 +189,14 @@ curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/entries/search" \ ```bash curl -sS -X DELETE "$DP_URL/v1/caches/$CACHE_ID/entries/" \ - -H "Authorization: Bearer $LC_TOKEN" + -H "Authorization: Bearer $LC_AGENT_KEY" ``` ### Delete entries matching attributes ```bash curl -sS -X DELETE "$DP_URL/v1/caches/$CACHE_ID/entries" \ - -H "Authorization: Bearer $LC_TOKEN" \ + -H "Authorization: Bearer $LC_AGENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "attributes": { @@ -170,14 +209,14 @@ curl -sS -X DELETE "$DP_URL/v1/caches/$CACHE_ID/entries" \ ```bash curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/flush" \ - -H "Authorization: Bearer $LC_TOKEN" + -H "Authorization: Bearer $LC_AGENT_KEY" ``` ### Check cache health ```bash curl -sS "$DP_URL/v1/caches/$CACHE_ID/health" \ - -H "Authorization: Bearer $LC_TOKEN" + -H "Authorization: Bearer $LC_AGENT_KEY" ``` For the full request and response schema for these operations, including diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md index d009e3fa7b..d20ff76d6d 100644 --- a/content/operate/iris/langcache/self-managed/authentication.md +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -5,15 +5,23 @@ categories: - docs - operate - iris -description: Configure LangCache self-managed Control Plane authentication and Data Plane auth modes. +description: Configure LangCache self-managed Control Plane authentication and Data Plane agent-key authentication through the Identity Service. linkTitle: Authentication and authorization -weight: 60 +weight: 40 hideListLinks: true --- -Self-managed LangCache uses separate authentication models for the Control -Plane and the Data Plane, and the Data Plane auth model differs between -static and Control Plane managed caches. +Self-managed LangCache uses three separate credentials: + +- an **admin token** for the Control Plane's cache-management API; +- an **internal token** the Identity Service uses to validate that a + cache-grant reference is real, by calling back into the Control Plane; +- **agent keys**, issued by the Identity Service, that applications use to + call the Data Plane. + +The Data Plane always authenticates by introspecting agent keys against an +Identity Service. There is no auth-disabled or static-token mode for +self-managed LangCache. ## Control Plane admin token @@ -23,147 +31,119 @@ Control Plane management endpoints require: Authorization: Bearer ``` -Production deployments should read the token from a mounted Secret file: - -```yaml -profile: prod +By default, `controlplane.adminToken.autoGenerate: true` mints this token +into a chart-managed Secret on first install (stable across upgrades). +Retrieve it: -auth: - type: admin-token - admin_token: - token_file: /etc/controlplane-onprem/admin/token +```bash +kubectl -n get secret langcache-controlplane-admin-token \ + -o jsonpath="{.data.token}" | base64 -d ``` -The Control Plane reads the token file on each request, so rotating the -Secret does not require a Control Plane redeploy. - -## Data Plane auth modes - -Choose the Data Plane auth mode based on the deployment mode and how callers -reach the Data Plane. - -| Mode | Deployment mode | Config | Use when | -| --- | --- | --- | --- | -| Auth-disabled | Static caches | `auth.enabled: false` (default) | The Data Plane is reachable only by trusted internal components. | -| Legacy per-cache token | Static caches | `auth.enabled: true`, `auth.passphrase: ` | You need per-cache API-key-style tokens without deploying the Control Plane or Identity Service. | -| Agent-key authentication | Control Plane managed caches | `auth.agent_keys.enabled: true` | LangCache should validate agent keys and enforce per-cache grants through the shared Identity Service. | +To bring your own token instead: -### Auth-disabled Data Plane (static caches) +```bash +kubectl -n create secret generic langcache-controlplane-admin-token \ + --from-literal=token='' +``` ```yaml -auth: - enabled: false +controlplane: + adminToken: + existingSecret: langcache-controlplane-admin-token + autoGenerate: false ``` -{{< warning >}} -Do not expose an auth-disabled Data Plane to untrusted callers. Any caller -that can reach the API can read or write cached entries for every configured -cache. -{{< /warning >}} +## Control Plane internal token -### Legacy per-cache token (static caches) +The internal token authenticates calls to the Control Plane's internal +grant-validation endpoint (`/internal/v1/grants/validate`). The Identity +Service calls this endpoint to confirm that a grant naming a LangCache cache +resource is valid before it lets an agent key carry that grant. -Static caches also support the same symmetric, per-cache token scheme used by -LangCache on Redis Cloud. Enable it and set a passphrase: - -```yaml -auth: - enabled: true - passphrase: "" -``` - -Generate a token for a cache with the `generate-auth-token` binary shipped in -the Data Plane image: +Like the admin token, it defaults to `controlplane.internalToken.autoGenerate: true` +and is retrievable the same way: ```bash -generate-auth-token \ - --config=/etc/langcache/dataplane.config.yaml \ - --username= \ - --password= \ - --resourceID= +kubectl -n get secret langcache-controlplane-internal-token \ + -o jsonpath="{.data.token}" | base64 -d ``` -The command prints a token. Send it as: - -```http -Authorization: Bearer -``` +In bundled Identity Service mode, the chart wires this token to the +Identity Service's `product_validation.langcache.credential` automatically. +In external mode, you must give this token to the Identity Service's owner +(see [External Identity Service](#external-identity-service)). -Treat the token as an opaque credential. There is no Control Plane endpoint -to mint, list, or revoke these tokens; manage the passphrase and any -generated tokens as part of your Secret material. +The admin token and internal token must always be different values; the +Control Plane rejects config where they match. -### Agent-key authentication (Control Plane managed caches) +## Identity Service modes -Agent-key auth requires Control Plane managed caches and is served by the -on-prem-hardened Data Plane binary. That binary rejects static caches and -every other auth method, so `auth.agent_keys.enabled` is effectively the only -supported setting when you deploy this mode. +Choose exactly one mode at install time — there is no default that applies +without choosing. -Unlike Redis Agent Memory's simpler shared-secret Data Plane auth, LangCache -agent keys are issued and validated by the **Identity Service**, a suite -component shared with RAM (RAM's chart installs it as -`redis-agent-memory-identity-service`; the published image is -`redislabs/iris-identity-service`). The LangCache `langcache` Helm chart does -not template the Identity Service yet, so deploy it the same way you deploy -the [Control Plane]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}): -as a plain Kubernetes Deployment using the published image, pointed at the -same Metadata Redis. +### Bundled -Data Plane config for agent-key auth: +`identityService.mode: bundled` (the default) renders the Identity Service +Deployment and Service, auto-generates its control token and the Data +Plane's own runtime introspection credential, and wires everything together +automatically: ```yaml -auth: - agent_keys: - enabled: true - product: langcache - introspection: - base_url: https://iris-identity-service:9200 - product: langcache - credential: - token_file: /etc/langcache/introspection/token +identityService: + mode: bundled + bundled: + image: + repository: redislabs/iris-identity-service + tag: "" + metadata: + existingSecret: ids-metadata ``` -- `introspection.base_url` is the Identity Service's base URL. It must be - `https://` unless you explicitly allow insecure transport for a lab - environment. -- `introspection.product` must be `langcache`; a different value fails - Data Plane startup. -- `introspection.credential` is the shared credential the Data Plane presents - to the Identity Service when introspecting a key. +Retrieve the auto-generated Identity Service Control admin token (used for +`/v1/api-keys` calls, not the Data Plane's own runtime credential): -Clients send agent keys as Bearer credentials: - -```http -Authorization: Bearer +```bash +kubectl -n get secret langcache-identity-service-control-token \ + -o jsonpath="{.data.token}" | base64 -d ``` -Treat agent keys as opaque credentials. Do not parse their contents. +### External Identity Service -## Cache authorization and grants +`identityService.mode: external` renders no Identity Service workload at +all — use this when your suite already runs one, for example alongside +self-managed Redis Agent Memory: -For agent-key requests, LangCache checks both identity and resource -authorization through the Identity Service: - -1. The key exists and its secret validates. -2. The key has a grant for the requested cache resource, keyed as - `lc-cache:`. -3. The grant includes the permission required by the operation. +```yaml +identityService: + mode: external + external: + baseURL: https://suite-identity-service.example.com + credential: + existingSecret: langcache-dp-ids-credential + secretKey: token +``` -Grant actions: +`langcache-dp-ids-credential` is minted out of band by the suite-level +Identity Service owner, scoped to `api-key-introspect` on product +`langcache`. You must also ask that owner to configure the external +Identity Service's own `product_validation.langcache` against this +release's Control Plane internal Service +(`langcache-controlplane:9100`) and this release's `controlplane.internalToken` +Secret — this chart has no way to reach into an Identity Service it doesn't +own. -| Action | Meaning | -| --- | --- | -| `read` | Read and search cache entries. | -| `write` | Mutate cache entries. `write` implies `read`. | -| `full` | Full cache access through the grant. `full` implies `write`. This is a resource permission, not a substitute for the Control Plane admin token; it doesn't grant access to Control Plane administration APIs. | +## Minting and managing agent keys -Mint and manage agent keys directly against the Identity Service (not the -LangCache Control Plane): +Mint, list, update, revoke, and rotate agent keys directly against the +Identity Service (not the LangCache Control Plane): ```bash -curl -sS -X POST "$IDENTITY_SERVICE_URL/v1/api-keys" \ - -H "Authorization: Bearer $IDENTITY_SERVICE_CONTROL_TOKEN" \ +IDS_URL="http://localhost:9200" +IDS_CONTROL_TOKEN="" + +curl -sS -X POST "$IDS_URL/v1/api-keys" \ + -H "Authorization: Bearer $IDS_CONTROL_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "my-agent-key", @@ -178,18 +158,34 @@ curl -sS -X POST "$IDENTITY_SERVICE_URL/v1/api-keys" \ }' ``` -{{< note >}} -The Identity Service is a shared, cross-product component, and deploying it -is more than running one extra container: it needs its own control-plane -credential (for the `/v1/api-keys` calls shown above), a separate runtime -introspection credential for each Data Plane that calls it, and its LangCache -product entry wired so grants resolve against real caches. A full -self-managed deployment and administration guide for it is out of scope for -this LangCache-specific documentation; see your Redis representative or the -self-managed Redis Agent Memory Helm chart for a working reference -deployment of `iris-identity-service` until dedicated Identity Service docs -are published. -{{< /note >}} +The response contains the new credential. Store it immediately; credentials +are returned only when a key is minted or rotated. + +Grant actions: + +| Action | Meaning | +| --- | --- | +| `read` | Read and search cache entries. | +| `write` | Mutate cache entries. `write` implies `read`. | +| `full` | Full cache access through the grant. `full` implies `write`. This is a resource permission, not a substitute for the Control Plane admin token; it doesn't grant access to Control Plane administration APIs. | + +Clients send agent keys as Bearer credentials to the Data Plane: + +```http +Authorization: Bearer +``` + +Treat agent keys as opaque credentials. Do not parse their contents. + +## Cache authorization + +For agent-key requests, the Data Plane checks both identity and resource +authorization through the Identity Service: + +1. The key exists and its secret validates. +2. The key has a grant for the requested cache resource, keyed as + `lc-cache:`. +3. The grant includes the permission required by the operation. ## Gateway and identity provider integration @@ -201,7 +197,7 @@ Gateway rules: - The gateway owns external authentication and perimeter policy. - LangCache owns cache-level authorization through the Identity Service. -- LangCache agent keys or legacy tokens are stored and forwarded by trusted - infrastructure or trusted applications. +- LangCache agent keys are stored and forwarded by trusted infrastructure or + trusted applications. - Callers must not be able to bypass the gateway and reach the Data Plane - directly unless they also present a valid LangCache credential. + directly unless they also present a valid LangCache agent key. diff --git a/content/operate/iris/langcache/self-managed/configuration.md b/content/operate/iris/langcache/self-managed/configuration.md new file mode 100644 index 0000000000..0b277f5be1 --- /dev/null +++ b/content/operate/iris/langcache/self-managed/configuration.md @@ -0,0 +1,156 @@ +--- +Title: Configuration +alwaysopen: false +categories: +- docs +- operate +- iris +description: Configure the LangCache Data Plane, Control Plane, and Identity Service through Helm values and config overlay Secrets. +linkTitle: Configuration +weight: 20 +hideListLinks: true +--- + +The `langcache` chart splits configuration into two layers for the Data +Plane, the Control Plane, and (in bundled mode) the Identity Service: + +- **Non-secret structure**, set as Helm values (`dataplane.configData`, + `controlplane.configData`, `identityService.bundled.configData`) and + rendered into a ConfigMap by default. +- **Redis URLs, the database registry, and the embedding credential**, + which never go in `values.yaml` or a rendered ConfigMap. Each component + reads its own pre-created overlay Secret, deep-merged over its rendered + base config at container startup (later files win — the chart passes each + overlay as an additional `--config` flag). + +You always create the overlay Secrets yourself; the chart only tells each +component where to mount and read them. + +## Data Plane overlay + +Create `dp-overlay.yaml`. Provide Metadata Redis and, when +`dataplane.embedding.credentials.type: static`, the embedding credential. +The Data Plane has no database registry of its own — it resolves each +cache's Cache Redis target from the `databaseUrls` the Control Plane already +persisted in Metadata Redis at cache-creation time. + +```yaml +metadata: + urls: + - rediss://default:@metadata-redis:6380 + +embedding: + credentials: + api_key: "" +``` + +```bash +kubectl -n create secret generic dp-overlay \ + --from-file=overlay.yaml=./dp-overlay.yaml +``` + +Point the chart at it, alongside the public (non-secret) embedding facts: + +```yaml +dataplane: + secrets: + secretName: dp-overlay + embedding: + provider: openai + endpoint: + baseURL: https://api.openai.com/v1 + credentials: + type: static + models: + defaultEmbeddingModel: text-embedding-3-small + dimensions: 1536 +``` + +## Control Plane overlay + +Create `cp-overlay.yaml`. Provide the same Metadata Redis as the Data Plane, +plus the `databases` registry — one entry per Cache Redis target, keyed by a +logical ID you choose. The Control Plane never receives an embedding +credential; it only needs the public provider/model/dimensions contract +(set as `controlplane.configData`, matching `dataplane.embedding`). + +```yaml +metadata: + urls: + - rediss://default:@metadata-redis:6380 + +databases: + cache-primary: + name: cache-primary + urls: + - rediss://default:@cache-primary:6380 +``` + +```bash +kubectl -n create secret generic cp-overlay \ + --from-file=overlay.yaml=./cp-overlay.yaml +``` + +```yaml +controlplane: + secrets: + secretName: cp-overlay + configData: + profile: prod + embedders: + openai: + models: + - model: text-embedding-3-small + dimensions: 1536 +``` + +The `databases` map must use the same logical IDs your operators will pass +as `databaseId` when creating caches through the Control Plane API. The +`embedders` block must describe exactly one provider with exactly one model +— the embedding contract that cache creation and the Data Plane's +`dataplane.embedding` values must agree on exactly. It must not set +`authorized: true`; on-prem cache creation cannot accept per-cache embedding +credentials. + +## Identity Service metadata (bundled mode only) + +When `identityService.mode: bundled` (the default), the bundled Identity +Service needs its own Metadata Redis connection — it can be the same Redis +instance as the Control Plane's Metadata Redis, in a separate namespace. + +```yaml +metadata: + urls: + - rediss://default:@metadata-redis:6380 +``` + +```bash +kubectl -n create secret generic ids-metadata \ + --from-file=metadata.yaml=./ids-metadata.yaml +``` + +```yaml +identityService: + mode: bundled + bundled: + metadata: + existingSecret: ids-metadata +``` + +If you use `identityService.mode: external` instead, there is no Identity +Service overlay to create here; see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). + +## Multiple overlay Secrets + +`dataplane.secrets.additionalSecrets` and +`controlplane.secrets.additionalSecrets` accept a list of extra pre-created +Secret names, layered in order after the primary overlay (later wins). Use +this to split, for example, Redis connection details from the embedding +credential across separately rotated Secrets. + +## Treat overlay content as sensitive + +Store `dp-overlay.yaml`, `cp-overlay.yaml`, and `ids-metadata.yaml` outside +your values files and outside git, the same as any other credential +material. diff --git a/content/operate/iris/langcache/self-managed/data-plane-configuration.md b/content/operate/iris/langcache/self-managed/data-plane-configuration.md deleted file mode 100644 index 7151ac9ea8..0000000000 --- a/content/operate/iris/langcache/self-managed/data-plane-configuration.md +++ /dev/null @@ -1,169 +0,0 @@ ---- -Title: Data Plane configuration -alwaysopen: false -categories: -- docs -- operate -- iris -description: Configure the LangCache Data Plane for static caches or Control Plane managed caches. -linkTitle: Data Plane configuration -weight: 30 -hideListLinks: true ---- - -The Data Plane reads `dataplane.config.yaml`. The published `langcache` chart -provides this content inline under the `config` Helm value, which the chart -renders into a ConfigMap (not a Secret) — see -[Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}). -Use one cache mode: static caches or Control Plane managed caches. The two -modes use different Data Plane binaries and config shapes. - -## Shared settings - -| Setting | Purpose | -| --- | --- | -| `server.port` | Data Plane bind port. | -| `client_side_cache` | In-memory response caching for repeated lookups. | -| `client_pool` | Redis client pool sizing. | -| `profile` | `prod`, `dev`, or `test`. | - -## Static caches example - -Use this config when caches are declared directly under `metadata.caches`. -This is the mode the published `langcache` Helm chart deploys today. - -```yaml -server: - port: 8080 - -profile: prod - -metadata: - loader: static - cache_ttl: 1m - caches: - # metadata.caches is a list; each entry is one cache. - - id: my-cache - urls: - - redis://cache-redis:6379 - index: idx:my-cache - model: - type: openai - name: text-embedding-3-large - dimensions: 3072 - # key: "" # optional per-cache override - attributes: [] - default_ttl: 60000 - default_search_threshold: 0.9 - search_strategies: - default_strategies: - - semantic - -embeddings: - openai: - default: - base_url: https://api.openai.com - -client_side_cache: - enabled: true - default_ttl: 1m - max_items: 30000 - -client_pool: - enable: true - max_size: 10000 - client_acquisition_timeout_ms: 2000 -``` - -Static caches carry Redis URLs and embedding settings directly in config. -Data Plane auth for this mode is disabled by default; see -[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) -to enable the legacy per-cache token auth. - -Provision the cache's RediSearch index before or during first start. The -`provision-cache-index` binary shipped in the Data Plane image reads the same -config and creates or repairs the index for every entry in `metadata.caches`: - -```bash -provision-cache-index --config=/etc/langcache/dataplane.config.yaml -``` - -The chart can run this automatically as an init container with -`initProvisioner.enabled: true`. - -## Control Plane managed caches example - -Use this config when the Data Plane serves caches created by the Control -Plane. This mode uses the on-prem-hardened Data Plane binary, requires -Metadata Redis, and only supports agent-key authentication through the shared -Identity Service. - -```yaml -server: - port: 9000 - -profile: prod - -metadata: - urls: - - redis://redis-meta:6379 - cache_ttl: 1m - -databases: - cache-primary: - name: cache-primary - urls: - - redis://cache-primary:6379 - -auth: - agent_keys: - enabled: true - product: langcache - introspection: - base_url: https://iris-identity-service:9200 - product: langcache - credential: - token_file: /etc/introspection/token - -embedding: - provider: openai - endpoint: - base_url: https://api.openai.com - models: - default_embedding_model: text-embedding-3-large - dimensions: 3072 - credentials: - type: static - api_key: "" - -license: - license_path: /etc/license/license -``` - -The `databases` map must use the same logical `` keys (here, -`cache-primary`) as the Control Plane's `controlplane-onprem.config.yaml`, so -both processes resolve `databaseId` to the same Cache Redis target. The -`embedding` block must match the Control Plane's configured provider, model, -and dimensions exactly; Control Plane managed caches cannot select a -different embedding model or supply per-cache credentials. `embedding.endpoint.base_url` -is required for the OpenAI-compatible provider; the Data Plane fails startup -without it. - -For the Identity Service introspection settings, see -[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). - -## Config storage - -The published `langcache` chart takes `dataplane.config.yaml` as the inline -`config` Helm value and renders it into a Kubernetes ConfigMap, not a Secret. -Because this config commonly contains embedding provider credentials and -Redis URLs with embedded credentials, treat the values file itself (and any -CI/CD pipeline that renders it) as sensitive, the same as you would a -Secret. If your security policy requires Secret-backed storage for this -content instead, mount a Secret through the chart's generic -`volumes`/`volumeMounts` values and override `args` to point at the mounted -path instead of the default `/etc/langcache/dataplane.config.yaml`. - -The chart automatically restarts Data Plane pods when the rendered -ConfigMap content changes on `helm upgrade`; no separate checksum value is -needed for `config` itself. diff --git a/content/operate/iris/langcache/self-managed/deploy-control-plane.md b/content/operate/iris/langcache/self-managed/deploy-control-plane.md deleted file mode 100644 index 92d53ce0ff..0000000000 --- a/content/operate/iris/langcache/self-managed/deploy-control-plane.md +++ /dev/null @@ -1,326 +0,0 @@ ---- -Title: Deploy with Control Plane managed caches -alwaysopen: false -categories: -- docs -- operate -- iris -description: Deploy LangCache with caches managed by the self-managed Control Plane. -linkTitle: Deploy with Control Plane managed caches -weight: 50 -hideListLinks: true ---- - -Use Control Plane managed caches when operators need to create or manage -caches at runtime. In this mode, the Data Plane reads cache records from -Metadata Redis, and the Control Plane provisions the RediSearch index in -Cache Redis when it creates a cache. - -{{< note >}} -The published `langcache` Helm chart currently templates only the Data -Plane. This page deploys the Control Plane as a plain Kubernetes manifest -using the image provided by your Redis representative. Chart support for -the Control Plane is expected in a future release; check with your Redis -representative for the current state. - -This page does not deploy the Identity Service, which agent-key Data Plane -authentication also depends on; see -[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) -for what that component requires and why deploying it is out of scope here. -{{< /note >}} - -Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) -and the -[Control Plane managed caches config example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}), -which you'll paste into the Data Plane's Helm values below. - -## Create the namespace - -```bash -kubectl create namespace -``` - -## Create shared Secrets - -Create the license Secret. Both the Control Plane manifest below and the -Data Plane values further down mount this same Secret: - -```bash -kubectl -n create secret generic langcache-license \ - --from-file=license=./license -``` - -## Create the Control Plane config - -Create `controlplane-onprem.config.yaml`: - -```yaml -profile: prod - -auth: - type: admin-token - admin_token: - token_file: /etc/controlplane-onprem/admin/token - -license: - license_path: /etc/license/license - -metadata: - urls: - - redis://redis-meta:6379 - -databases: - cache-primary: - name: cache-primary - urls: - - redis://cache-primary:6379 - -embedders: - openai: - models: - - model: text-embedding-3-large - dimensions: 3072 -``` - -The Control Plane's `embedders` block must describe exactly one provider with -exactly one model; it is the embedding contract that cache creation and the -Data Plane's `embedding` config must agree on. It must not set -`authorized: true` — on-prem cache creation cannot accept per-cache embedding -credentials. - -Create the Control Plane config Secret: - -```bash -kubectl -n create secret generic langcache-controlplane-config \ - --from-file=controlplane-onprem.config.yaml=./controlplane-onprem.config.yaml -``` - -Bring your own admin token: - -```bash -kubectl -n create secret generic langcache-controlplane-admin-token \ - --from-literal=token='' -``` - -## Deploy the Control Plane - -Until the Control Plane is packaged in the Helm chart, deploy it directly. -Adjust the image reference to the one provided by your Redis representative: - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: langcache-controlplane - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: langcache-controlplane - template: - metadata: - labels: - app: langcache-controlplane - spec: - containers: - - name: controlplane - image: /langcache-controlplane-onprem: - args: ["--config=/etc/controlplane-onprem/config/controlplane-onprem.config.yaml"] - ports: - - name: http - containerPort: 9100 - volumeMounts: - - name: config - mountPath: /etc/controlplane-onprem/config - readOnly: true - - name: admin-token - mountPath: /etc/controlplane-onprem/admin - readOnly: true - - name: license - mountPath: /etc/license - readOnly: true - readinessProbe: - httpGet: - path: /health/readiness - port: http - livenessProbe: - httpGet: - path: /health/liveness - port: http - volumes: - - name: config - secret: - secretName: langcache-controlplane-config - - name: admin-token - secret: - secretName: langcache-controlplane-admin-token - - name: license - secret: - secretName: langcache-license ---- -apiVersion: v1 -kind: Service -metadata: - name: langcache-controlplane - namespace: -spec: - selector: - app: langcache-controlplane - ports: - - name: http - port: 9100 - targetPort: http -``` - -```bash -kubectl apply -f langcache-controlplane.yaml -``` - -## Create Helm values for the Data Plane - -The published `langcache` chart takes `dataplane.config.yaml` inline as the -`config` value — there is no `existingSecret` option for it. It also has no -built-in fields for the license file or the Identity Service introspection -credential, so mount those two as Secrets yourself using the chart's generic -`volumes`/`volumeMounts` passthrough, at paths that don't overlap with the -chart's own config mount at `/etc/langcache`. - -Create the introspection-token Secret. This is the shared credential the -Data Plane presents to the Identity Service when introspecting agent keys; -provision it as part of your Identity Service deployment: - -```bash -kubectl -n create secret generic langcache-introspection-token \ - --from-literal=token='' -``` - -Create `langcache-values.yaml`, using the -[Control Plane managed caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#control-plane-managed-caches-example" >}}) -for `config`: - -```yaml -nameOverride: langcache -fullnameOverride: langcache - -image: - repository: /langcache-dataplane - tag: "" - -# The on-prem-hardened Data Plane binary listens on 9000 by default; -# override the chart's default service port (8080) to match. -service: - port: 9000 - -config: - server: - port: 9000 - profile: prod - metadata: - urls: - - redis://redis-meta:6379 - cache_ttl: 1m - databases: - cache-primary: - name: cache-primary - urls: - - redis://cache-primary:6379 - auth: - agent_keys: - enabled: true - product: langcache - introspection: - base_url: https://iris-identity-service:9200 - product: langcache - credential: - token_file: /etc/introspection/token - embedding: - provider: openai - endpoint: - base_url: https://api.openai.com - models: - default_embedding_model: text-embedding-3-large - dimensions: 3072 - credentials: - type: static - api_key: "" - license: - license_path: /etc/license/license - -volumes: - - name: license - secret: - secretName: langcache-license - - name: introspection-token - secret: - secretName: langcache-introspection-token - -volumeMounts: - - name: license - mountPath: /etc/license - readOnly: true - - name: introspection-token - mountPath: /etc/introspection - readOnly: true -``` - -As with static caches, this `config` block ends up in a ConfigMap, so treat -`langcache-values.yaml` as sensitive. The `volumes`/`volumeMounts` entries -above are whole-directory mounts rather than `subPath` mounts, so Kubernetes -refreshes the mounted license and introspection-credential files -automatically when the backing Secret changes — no pod restart required to -pick up new file content (the running process still decides how often it -re-reads them; see [Operations]({{< relref "/operate/iris/langcache/self-managed/operations" >}}) -for license/token rotation). - -The chart values shown throughout this guide reflect the current `langcache` -chart, which does not yet expose dedicated license or Control Plane fields. -Once your chart provides `controlplane.enabled` (or similar) support, prefer -that over the manual Deployment and volume passthroughs above. - -## Install the Data Plane chart - -```bash -helm install langcache ./langcache \ - --namespace \ - --create-namespace \ - -f langcache-values.yaml -``` - -## Verify the deployment - -Check pods: - -```bash -kubectl -n get pods -``` - -Port-forward the Data Plane: - -```bash -kubectl -n port-forward svc/langcache 9000:9000 -``` - -```bash -curl http://localhost:9000/health -``` - -Port-forward the Control Plane: - -```bash -kubectl -n port-forward svc/langcache-controlplane 9100:9100 -``` - -Verify the admin API: - -```bash -curl -H "Authorization: Bearer " \ - http://localhost:9100/v1/caches -``` - -For the full self-managed admin API schema, see the -[Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}). - -After you deploy Control Plane managed caches, configure Data Plane -agent-key authentication and the Identity Service in -[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). diff --git a/content/operate/iris/langcache/self-managed/deploy-static.md b/content/operate/iris/langcache/self-managed/deploy-static.md deleted file mode 100644 index 8937b359c6..0000000000 --- a/content/operate/iris/langcache/self-managed/deploy-static.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -Title: Deploy with static caches -alwaysopen: false -categories: -- docs -- operate -- iris -description: Deploy LangCache with static caches and no Control Plane. -linkTitle: Deploy with static caches -weight: 40 -hideListLinks: true ---- - -Use static caches for a first install or a private single-cache deployment. -In this mode, caches are declared directly in Data Plane configuration. The -deployment does not include the Control Plane and does not use Metadata -Redis. This is the mode the published `langcache` Helm chart deploys today. - -Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) -and the -[static caches config example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}}), -which you'll paste into the Helm values below. - -## Create the namespace - -```bash -kubectl create namespace -``` - -## Create Helm values - -The published `langcache` chart takes `dataplane.config.yaml` inline as the -`config` value; there is no `existingSecret` option for it. Paste the -content of your `dataplane.config.yaml` (from the -[static caches example]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#static-caches-example" >}})) -under `config` in `langcache-values.yaml`: - -```yaml -nameOverride: langcache -fullnameOverride: langcache - -image: - repository: /langcache - tag: "" - -config: - server: - port: 8080 - profile: prod - metadata: - loader: static - cache_ttl: 1m - caches: - - id: my-cache - urls: - - redis://cache-redis:6379 - index: idx:my-cache - model: - type: openai - name: text-embedding-3-large - dimensions: 3072 - attributes: [] - default_ttl: 60000 - default_search_threshold: 0.9 - search_strategies: - default_strategies: - - semantic - embeddings: - openai: - default: - base_url: https://api.openai.com - -initProvisioner: - enabled: true - config: /etc/langcache/dataplane.config.yaml -``` - -Because the chart renders `config` into a ConfigMap rather than a Secret, -treat `langcache-values.yaml` itself as sensitive — it contains any -embedding provider credentials and Redis URL credentials you configure. See -[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}) -for a Secret-backed alternative. - -`nameOverride`/`fullnameOverride` make the rendered resource names match the -`langcache` names used in the verification commands below; the chart's own -default names are longer. `initProvisioner.enabled: true` runs -`provision-cache-index --ignore` as an init container so cache indexes exist -before the Data Plane starts, without recreating indexes that already exist. - -## Install the chart - -Install from the chart package provided by your Redis representative: - -```bash -helm install langcache ./langcache \ - --namespace \ - --create-namespace \ - -f langcache-values.yaml -``` - -On small clusters, install without `--atomic --wait`, then watch pod status: - -```bash -kubectl -n get pods -w -``` - -If you want Helm to wait, set an explicit timeout that matches the -environment: - -```bash -helm install langcache ./langcache \ - --namespace \ - --create-namespace \ - -f langcache-values.yaml \ - --wait \ - --timeout 15m -``` - -## Verify the deployment - -Check pods: - -```bash -kubectl -n get pods -l app.kubernetes.io/name=langcache -``` - -Port-forward the Data Plane: - -```bash -kubectl -n port-forward svc/langcache 8080:8080 -``` - -Check health endpoints: - -```bash -curl http://localhost:8080/health -curl http://localhost:8080/health/liveness -curl http://localhost:8080/health/readiness -``` - -Check the configured cache: - -```bash -curl http://localhost:8080/v1/caches/my-cache/health -``` - -Do not expose an auth-disabled Data Plane to untrusted callers. Use -Kubernetes NetworkPolicy, private service exposure, ingress, gateway, service -mesh, or equivalent controls to restrict access. diff --git a/content/operate/iris/langcache/self-managed/deploy.md b/content/operate/iris/langcache/self-managed/deploy.md new file mode 100644 index 0000000000..d4c9169b6f --- /dev/null +++ b/content/operate/iris/langcache/self-managed/deploy.md @@ -0,0 +1,198 @@ +--- +Title: Deploy self-managed LangCache +alwaysopen: false +categories: +- docs +- operate +- iris +description: Deploy self-managed LangCache with the langcache Helm chart. +linkTitle: Deploy +weight: 30 +hideListLinks: true +--- + +One `helm install` of the `langcache` chart deploys the Data Plane, the +Control Plane, and (by default) a bundled Identity Service. There is no +separate lighter-weight install path; every self-managed LangCache +deployment uses all three components. + +Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) +and prepare the config overlays described in +[Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}). + +## Choose an Identity Service mode + +Decide before you install: + +| Mode | Use when | Values | +| --- | --- | --- | +| Bundled (default) | This is your first LangCache install, or your suite doesn't already run an Identity Service. | `identityService.mode: bundled` | +| External | Your suite already runs an Identity Service (for example, alongside self-managed Redis Agent Memory) and you want LangCache to share it. | `identityService.mode: external` | + +This guide uses bundled mode. For external mode, see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication#external-identity-service" >}}) +for the values and the coordination required with the Identity Service's +owner. + +## Create the namespace + +```bash +kubectl create namespace +``` + +## Create the required Secrets + +Create the license Secret, shared by the Data Plane and Control Plane: + +```bash +kubectl -n create secret generic langcache-license \ + --from-file=license=./langcache.key +``` + +Create the config overlay Secrets described in +[Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}): + +```bash +kubectl -n create secret generic dp-overlay \ + --from-file=overlay.yaml=./dp-overlay.yaml +kubectl -n create secret generic cp-overlay \ + --from-file=overlay.yaml=./cp-overlay.yaml +kubectl -n create secret generic ids-metadata \ + --from-file=metadata.yaml=./ids-metadata.yaml +``` + +## Create Helm values + +Create `langcache-values.yaml`: + +```yaml +dataplane: + image: + repository: redislabs/iris-langcache-data + tag: "" + license: + existingSecret: langcache-license + secrets: + secretName: dp-overlay + embedding: + provider: openai + endpoint: + baseURL: https://api.openai.com/v1 + credentials: + type: static + models: + defaultEmbeddingModel: text-embedding-3-small + dimensions: 1536 + +controlplane: + image: + repository: redislabs/iris-langcache-control + tag: "" + secrets: + secretName: cp-overlay + configData: + profile: prod + embedders: + openai: + models: + - model: text-embedding-3-small + dimensions: 1536 + +identityService: + mode: bundled + bundled: + image: + repository: redislabs/iris-identity-service + tag: "" + metadata: + existingSecret: ids-metadata +``` + +This is a minimal complete install. `controlplane.adminToken`, +`controlplane.internalToken`, and `identityService.bundled.controlToken` +all default to `autoGenerate: true`, so the chart mints those tokens for +you on first install; see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) +to retrieve them, or set `existingSecret` to bring your own. + +## Install the chart + +Install from the chart package or repository your Redis representative +provides. From the chart's own root directory (`langcache/helm/` in the +source layout): + +```bash +helm install langcache . \ + --namespace \ + --create-namespace \ + -f langcache-values.yaml \ + --atomic --wait +``` + +On small clusters, install without `--atomic --wait`, then watch pod +status: + +```bash +kubectl -n get pods -w +``` + +## Verify the deployment + +```bash +kubectl -n rollout status deployment/langcache +kubectl -n rollout status deployment/langcache-controlplane +kubectl -n rollout status deployment/langcache-identity-service +``` + +Port-forward the Data Plane: + +```bash +kubectl -n port-forward svc/langcache 9000:9000 +``` + +```bash +curl http://localhost:9000/health +``` + +Port-forward the Control Plane: + +```bash +kubectl -n port-forward svc/langcache-controlplane 9100:9100 +``` + +Retrieve the auto-generated admin token, then create your first cache: + +```bash +kubectl -n get secret langcache-controlplane-admin-token \ + -o jsonpath="{.data.token}" | base64 -d +``` + +```bash +curl -sS -X POST http://localhost:9100/v1/caches \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-cache", + "databaseId": "cache-primary", + "defaultSearchThreshold": 0.9, + "defaultTtlMillis": -1, + "attributes": [] + }' +``` + +For the full self-managed admin API schema, see the +[Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}). + +Next, mint an agent key through the Identity Service and start calling the +Data Plane; see +[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) +and [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}). + +## Update + +```bash +helm upgrade langcache . \ + --namespace \ + -f langcache-values.yaml \ + --atomic --wait +``` diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index ce4e8598a9..98be100718 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -5,7 +5,7 @@ categories: - docs - operate - iris -description: Operate self-managed LangCache with backups, secret rotation, updates, and FIPS posture. +description: Operate self-managed LangCache with backups, secret rotation, updates, FIPS posture, and support bundles. linkTitle: Operations weight: 90 hideListLinks: true @@ -13,137 +13,195 @@ hideListLinks: true ## Backups -- Back up Cache Redis according to the customer's cache-retention policy. - LangCache can rebuild the RediSearch index from existing entries, but losing - the underlying hashes loses cached responses. -- Back up Metadata Redis for Control Plane managed caches. Losing metadata - removes Control Plane cache records. -- Back up any external secret manager material used to recreate Kubernetes - Secrets, including the license, Control Plane config, and admin-token - Secrets. Back up your Helm values file too — the Data Plane's config is - provided inline through Helm values, not a Secret. -- For Metadata Redis, use persistent storage and an eviction policy that does - not evict cache records under memory pressure. +- Back up Cache Redis according to your cache-retention policy. LangCache + can rebuild the RediSearch index from existing entries, but losing the + underlying hashes loses cached responses. +- Back up Metadata Redis. Losing metadata removes Control Plane cache + records — including the `databaseUrls` the Data Plane depends on to reach + Cache Redis. +- Back up the Identity Service's own metadata Redis (bundled mode). Losing + it removes agent-key and grant records. +- Back up any external secret manager material used to recreate the config + overlay, license, and token Secrets. ## Secret rotation -Rotate the Control Plane admin token by updating -`langcache-controlplane-admin-token`. The Control Plane reads the token on -use, so changing the token value does not require a Control Plane redeploy. +The chart cannot see the contents of Secrets you bring yourself +(`existingSecret` values), so it can't roll pods automatically when you +update one. Every rotatable Secret has a matching `existingSecretChecksum` +value: update the Secret, then bump the checksum and run `helm upgrade` to +force a rollout. + +Rotate the config overlay Secrets (Redis URLs, database registry, embedding +credential): + +```bash +kubectl -n create secret generic dp-overlay \ + --from-file=overlay.yaml=./dp-overlay.yaml \ + --dry-run=client -o yaml | kubectl apply -f - +kubectl -n create secret generic cp-overlay \ + --from-file=overlay.yaml=./cp-overlay.yaml \ + --dry-run=client -o yaml | kubectl apply -f - +``` + +```yaml +dataplane: + secrets: + secretName: dp-overlay + existingSecretChecksum: "" +controlplane: + secrets: + secretName: cp-overlay + existingSecretChecksum: "" +``` + +Rotate the license the same way, using `dataplane.license.existingSecretChecksum`. + +{{< multitabs id="langcache-secret-checksum" +tab1="Linux" +tab2="macOS" >}} ```bash -kubectl -n create secret generic langcache-controlplane-admin-token \ - --from-literal=token='' \ - --dry-run=client \ - -o yaml | kubectl apply -f - +sha256sum ./dp-overlay.yaml | awk '{print $1}' ``` -Rotate the LangCache license by updating the license Secret, then restart -the pods that mount it so they pick up the new file: +-tab-sep- ```bash -kubectl -n create secret generic langcache-license \ - --from-file=license=./license \ - --dry-run=client \ - -o yaml | kubectl apply -f - - -kubectl -n rollout restart deploy/langcache -kubectl -n rollout restart deploy/langcache-controlplane -kubectl -n rollout status deploy/langcache -kubectl -n rollout status deploy/langcache-controlplane +shasum -a 256 ./dp-overlay.yaml | awk '{print $1}' ``` -The license and introspection-token Secrets in this guide are mounted as -whole-directory volumes (not `subPath`), so Kubernetes refreshes the mounted -files automatically within about a minute of the Secret change. Restart the -pods anyway: LangCache shares its license-handling code with self-managed -Redis Agent Memory, which reads and validates the license file at process -startup and does not guarantee it re-reads a replaced file without a -restart. +{{< /multitabs >}} -Rotate the Identity Service introspection-token Secret the same way, then -restart the Data Plane: +Apply the updated values and verify the workloads rolled: ```bash -kubectl -n create secret generic langcache-introspection-token \ - --from-literal=token='' \ - --dry-run=client \ - -o yaml | kubectl apply -f - +helm upgrade langcache . \ + --namespace \ + -f langcache-values.yaml -kubectl -n rollout restart deploy/langcache +kubectl -n rollout status deployment/langcache +kubectl -n rollout status deployment/langcache-controlplane ``` -Rotate agent keys minted for Control Plane managed caches through the -Identity Service, as described in -[Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). +Rotating an auto-generated token (admin token, internal token, Identity +Service control token, or the Data Plane's Identity Service runtime +credential) is different: those Secrets are Helm-managed, not +`existingSecret`, so there is no checksum to bump. Set `autoGenerate: false` +temporarily and supply a new `existingSecret`, or delete the underlying +Secret and let the next `helm upgrade` regenerate it — confirm which +behavior your chart version implements before relying on it in production. -Rotate the legacy static-cache token by regenerating it with -`generate-auth-token` and redistributing it to callers; there is no server -side revocation for this token type, so also consider rotating -`auth.passphrase` if a token may have leaked. +Rotate agent keys minted for LangCache caches through the Identity Service; +see [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples#identity-service-api-examples" >}}). ## Updates For every update: 1. Update chart version and image tags. -2. Recalculate Secret checksums for changed files. +2. Recalculate `existingSecretChecksum` values for any changed overlay or + license Secrets. 3. Run `helm upgrade`. 4. Verify pod rollout and health endpoints. ```bash -helm upgrade langcache ./langcache \ +helm upgrade langcache . \ --namespace \ - -f langcache-values.yaml + -f langcache-values.yaml \ + --atomic --wait +``` + +On small clusters, avoid `--atomic` unless the timeout and capacity are +known to be sufficient. + +## Helm tests + +The chart can render `helm test` resources when `tests.enabled: true`. This +renders the shared security-profile check and the minimal RBAC it needs: + +```bash +helm upgrade --install langcache . \ + --namespace \ + -f langcache-values.yaml \ + --set tests.enabled=true + +helm test langcache --logs ``` -On small clusters, avoid `--atomic` unless the timeout and capacity are known -to be sufficient. If you deployed the Control Plane as a plain manifest, -update its image tag and re-apply the manifest, then verify its rollout the -same way. +`tests.smoke.enabled: true` independently gates an additional smoke test +that proves authenticated set/search/delete of one uniquely generated cache +entry. It expects a `READY` cache and a valid agent key to already +exist — create the cache through the Control Plane and mint the key +through the Identity Service first, then store the key's plaintext token +in a Secret and reference it: + +```yaml +tests: + enabled: true + smoke: + enabled: true + cacheID: + apiKey: + existingSecret: langcache-smoke-key +``` ## FIPS-oriented posture -The on-prem-hardened Control Plane and Data Plane binaries (used for Control -Plane managed caches) are built with a FIPS-capable Go toolchain (`GOFIPS140`), -but the shipped images run with that runtime FIPS mode turned **off** by -default (`GODEBUG=fips140=off`). The stricter posture checks only activate -when you turn Go's FIPS 140 runtime mode on for the container; they are not -automatic just because you're running the on-prem-hardened image. +`security.profile: fips` sets `GODEBUG=fips140=on` on every container this +release renders (Data Plane, Control Plane, and, in bundled mode, the +Identity Service): + +```yaml +security: + profile: fips +``` -When Go's FIPS mode is enabled, the on-prem-hardened binaries reject -configuration that: +Under this posture, the chart: -- uses non-`rediss://` URLs for `metadata.urls`, `databases..urls`, or - the Control Plane's `metadata.urls`; or -- otherwise fails the shared FIPS Redis-URL posture check used across the - Redis AI Services products. +- refuses to render with `identityService.mode: bundled` — the bundled + Identity Service's in-cluster Service has no TLS termination of its own, + so its address is always `http://`, which the profile forbids. Use + `identityService.mode: external` with a TLS-fronted Identity Service + instead. +- refuses `identityService.external.baseURL` unless it is `https://`. + `identityService.external.allowInsecureTransport: true` is a real opt-out + outside `fips`, but is not honored under `fips`. This is not a formal FIPS 140 compliance or validation claim. Treat it as an opt-in deployment posture and guardrail that must still be reviewed against -the customer's compliance boundary, and confirm with your Redis -representative how to turn the runtime FIPS mode on for your deployment. +your compliance boundary. + +## Support bundles and preflight -The static-caches Data Plane image (used by the published `langcache` chart -today) does not build with the FIPS-capable toolchain at all; it is the same -image used for LangCache on Redis Cloud. +`supportPackage.enabled: true` (the default) ships a namespace-scoped +[Troubleshoot](https://troubleshoot.sh) spec as a ConfigMap. Collect a +bundle with: -The LangCache API listener itself speaks HTTP inside the cluster. Edge TLS -termination is owned by the hosting environment, such as ingress, service -mesh, or external load balancer. Outbound TLS to Redis and the embedding -provider is configured through LangCache config and is covered by the -posture checks for Control Plane managed caches. +```bash +kubectl support-bundle --namespace --load-cluster-specs \ + -l troubleshoot.sh/kind=support-bundle +``` + +The bundle excludes Secret contents, license data, Redis URLs, +admin/internal/runtime credentials, API-key material, prompts, responses, +vectors, and cache records — see the redactor spec shipped in the same +namespace (`langcache-support-redactors`) for the exact rules. + +`preflight.enabled: true` (the default) ships a cluster preflight check as +both a ConfigMap and a standalone file (`support/langcache-preflight.yaml` +in the chart source) for `kubectl preflight` before you install: + +```bash +kubectl preflight support/langcache-preflight.yaml +``` ## Network policy -For auth-disabled Data Plane deployments, restrict access to trusted callers. -For agent-key deployments behind a gateway, prevent direct bypass paths -unless the direct caller also has a valid LangCache credential. - -There is no bundled NetworkPolicy reference manifest for LangCache yet -(unlike the self-managed Redis Agent Memory chart's -`networkpolicy.reference.yaml`). Write a NetworkPolicy for your cluster's CNI -that default-denies ingress to the LangCache Data Plane and Control Plane -pods, then allows TCP traffic on the Data Plane port (`8080` for static -caches, `9000` for Control Plane managed caches) and the Control Plane port -(`9100`) from approved callers only. +For every Identity Service mode, prevent callers from bypassing your +intended access path (gateway, ingress, or trusted-internal-only) and +reaching the Data Plane, Control Plane, or bundled Identity Service Service +directly. Write a NetworkPolicy for your cluster's CNI that default-denies +ingress to the `langcache`, `langcache-controlplane`, and (bundled mode) +`langcache-identity-service` Services, then allow TCP traffic on their +respective ports (`9000`, `9100`, `9200`) from approved callers only. diff --git a/content/operate/iris/langcache/self-managed/plan-deployment.md b/content/operate/iris/langcache/self-managed/plan-deployment.md deleted file mode 100644 index 8b7a03eb4a..0000000000 --- a/content/operate/iris/langcache/self-managed/plan-deployment.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -Title: Plan a self-managed LangCache deployment -alwaysopen: false -categories: -- docs -- operate -- iris -description: Choose a self-managed LangCache deployment mode before installing the Helm chart. -linkTitle: Plan a deployment -weight: 10 -hideListLinks: true ---- - -Choose the deployment mode before you create Redis databases, configuration -Secrets, or Helm values. - -## Deployment modes - -{{< table-scrollable >}} -| Mode | What it deploys | Redis databases | Data Plane auth | Start here | -| --- | --- | --- | --- | --- | -| Static caches | Data Plane only. Caches are declared directly in `dataplane.config.yaml`. | Cache Redis. | Disabled by default. Protect access with Kubernetes, ingress, gateway, or service-mesh controls, or enable the legacy per-cache token auth described in [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}). | [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) | -| Control Plane managed caches | Data Plane, Control Plane, and (for agent-key auth) the shared Identity Service. Caches are created and managed at runtime. | Cache Redis and Metadata Redis. | Agent-key authentication through the Identity Service. | [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}) | -{{< /table-scrollable >}} - -## Mode rules - -Do not combine static `metadata.caches` with Control Plane managed cache -metadata in the same Data Plane process. Static caches do not use Metadata -Redis. Control Plane managed caches use `metadata.loader: live` and require -Metadata Redis. - -Static caches use one embedding contract per cache, configured directly in -`dataplane.config.yaml`. Control Plane managed caches use one embedding -contract for the whole deployment: the Control Plane and Data Plane must be -configured with the same provider, model, and dimensions, and cache creation -cannot override it or supply per-cache embedding credentials. - -The walkthroughs in this section use `langcache` as the Helm release name for -the Data Plane. If you choose a different release name, update -release-derived service and deployment names in the verification commands. - -## Before you deploy - -1. Review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}). -1. Prepare the appropriate [Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration" >}}). -1. Follow either [Deploy with static caches]({{< relref "/operate/iris/langcache/self-managed/deploy-static" >}}) or [Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}). diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md index 1d74b8a7bf..125d8b58a3 100644 --- a/content/operate/iris/langcache/self-managed/prerequisites.md +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -7,15 +7,14 @@ categories: - iris description: Review software, Redis, network, Secret, image, and sizing prerequisites for self-managed LangCache. linkTitle: Prerequisites -weight: 20 +weight: 10 hideListLinks: true --- -LangCache self-managed is distributed as container images plus a Helm chart. -The published `langcache` chart deploys the LangCache Data Plane. The Control -Plane and, for Control Plane managed caches, the shared Identity Service are -distributed as container images that you deploy alongside the chart; see -[Deploy with Control Plane managed caches]({{< relref "/operate/iris/langcache/self-managed/deploy-control-plane" >}}). +LangCache self-managed is distributed as container images on Docker Hub plus +the `langcache` Helm chart. One `helm install` of the chart deploys the +LangCache Data Plane, the LangCache Control Plane, and (by default) a +bundled Identity Service. You provide the Redis databases, embedding provider credentials, Kubernetes exposure, and license material used by the deployment. @@ -29,68 +28,42 @@ Kubernetes cluster. | Item | Where it comes from | | ---- | ------------------- | -| Container images | LangCache Data Plane image, and, when the Control Plane is used, the LangCache Control Plane image. Provided by your Redis representative. | -| Helm chart | `langcache` chart, provided by your Redis representative. | -| Identity Service image | `redislabs/iris-identity-service` on Docker Hub, needed only for Control Plane managed caches with agent-key Data Plane authentication. | -| Redis databases | You provide Cache Redis and, for Control Plane managed caches, Metadata Redis. | +| Container images | `redislabs/iris-langcache-data`, `redislabs/iris-langcache-control`, and (bundled Identity Service) `redislabs/iris-identity-service` on Docker Hub | +| Helm chart | `langcache` chart, synced to the Redis Enterprise Helm chart repository. Contact your Redis representative for the exact repository coordinates and chart version, or for a chart package. | +| Redis databases | You provide Metadata Redis and one or more Cache Redis databases | | License key | Contact your Redis representative or [contact sales](https://redis.io/contact/). | -| Provider credentials | You provide embedding provider credentials (currently an OpenAI-compatible provider). | - -{{< note >}} -LangCache self-managed does not yet have a public Docker Hub or Helm -repository the way self-managed Redis Agent Memory does. Get the chart -package and image references from your Redis representative and mirror them -into your own registry if needed. -{{< /note >}} +| Provider credentials | You provide embedding provider credentials (currently an OpenAI-compatible provider) | ## Required software | Software | Minimum version | Purpose | | -------- | --------------- | ------- | -| Kubernetes | 1.19+ | Orchestration | -| kubectl | 1.19+ | Kubernetes CLI | -| Helm | 3.x | Package manager for the Data Plane chart | +| Kubernetes | 1.23+ | Orchestration; the chart renders an `autoscaling/v2` HorizontalPodAutoscaler | +| kubectl | 1.23+ | Kubernetes CLI | +| Helm | 3.x | Package manager | ## Redis databases -The Helm chart does not deploy Redis databases. Provision the Redis databases -outside the LangCache chart and pass their URLs in `dataplane.config.yaml` -and, when the Control Plane is used, `controlplane-onprem.config.yaml`. +The Helm chart does not deploy Redis databases. Provision them outside the +chart and register them through the Control Plane's and Data Plane's config +overlays (see [Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}})). Cache Redis must support RediSearch with vector search, because LangCache -creates a RediSearch vector index per cache. Metadata Redis does not need that -capability. - -### Static caches - -Use static caches for a first install or a private single-cache deployment. -Caches are declared directly in `dataplane.config.yaml`. The Control Plane -and Metadata Redis are not used. +creates a RediSearch vector index per cache. Metadata Redis does not need +that capability. {{< table-scrollable >}} -| Redis database | Required when | Configure in `dataplane.config.yaml` | Purpose | +| Redis database | Required | Registered in | Purpose | | --- | --- | --- | --- | -| Cache Redis | Always | `metadata.caches[].urls` | Cache entry hashes and RediSearch vector indexes. | -{{< /table-scrollable >}} - -### Control Plane managed caches - -Use Control Plane managed caches when operators need to create or manage -caches at runtime. The Data Plane and Control Plane must resolve the same -`databaseId` to the same Cache Redis target and point at the same Metadata -Redis. - -{{< table-scrollable >}} -| Redis database | Required when | Configure in `dataplane.config.yaml` | Configure in `controlplane-onprem.config.yaml` | Purpose | -| --- | --- | --- | --- | --- | -| Cache Redis | Always | `databases..urls` | `databases..urls` | Cache entries for Control Plane managed caches. Both processes must define the same ``. | -| Metadata Redis | Always | `metadata.urls` | `metadata.urls` | Cache records and, for agent-key auth, key/grant records managed by the Identity Service. | +| Metadata Redis | Always | Both the Data Plane's and Control Plane's config overlays (same URLs, same keyspace) | Cache records written by the Control Plane, read by the Data Plane. | +| Cache Redis (one or more) | Always | The Control Plane's config overlay only, as a `databases` registry entry keyed by a logical `databaseId` | Cache entry hashes and RediSearch vector indexes. The Data Plane has no database registry of its own — it resolves each cache's Redis URLs from the metadata the Control Plane already persisted at cache-creation time. | +| Identity Service metadata Redis (bundled mode only) | When `identityService.mode: bundled` | The bundled Identity Service's own config overlay | Agent-key and grant records. Can be the same Redis instance as Metadata Redis, in a separate namespace. | {{< /table-scrollable >}} -For a lab deployment, Cache Redis and Metadata Redis can point to the same -Redis endpoint if it has the required modules and capacity. For production, -separate them so cache data and control metadata can be scaled, backed up, -and operated independently. +For a lab deployment, these Redis roles can point at the same Redis endpoint +if it has the required modules and capacity. For production, separate them +so cache data and control metadata can be scaled, backed up, and operated +independently. ### Metadata Redis durability @@ -101,67 +74,120 @@ removes Control Plane cache records. ## Network access -- **Connected install:** the cluster must be able to pull the LangCache - images and, for Control Plane managed caches, the `iris-identity-service` - image. -- **Air-gapped install:** mirror the images into an internal registry. +- **Connected install:** the cluster must be able to pull the LangCache and + Identity Service images from Docker Hub (or your mirrored registry) and + reach the Helm chart repository. +- **Air-gapped install:** mirror the images into an internal registry and + use a locally available chart package. - **Runtime access:** LangCache pods must reach the Redis databases and the - embedding provider endpoint used by the deployment. + embedding provider endpoint used by the deployment. The Data Plane must + also reach the Identity Service (bundled or external); the Control Plane + must reach Metadata Redis and every registered Cache Redis database. - **Data Plane exposure:** use NetworkPolicy, ingress, gateway, service mesh, private load balancer, or equivalent controls to restrict API access. ## Credentials and Secrets -The published `langcache` chart takes the Data Plane's `dataplane.config.yaml` -inline as a Helm value; the chart renders it into a ConfigMap, not a Secret. -Because that config can contain embedding provider API keys and Redis URLs -with credentials, treat the values file itself as sensitive. If your -security policy requires Secret-backed storage for it instead, mount a -Secret through the chart's generic `volumes`/`volumeMounts` values; see -[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}). - -The license file and, for Control Plane managed caches, the Identity Service -introspection credential are not wired into the chart's values at all today; -mount them yourself as Secrets the same way. The Control Plane (deployed as -a plain manifest until it's chart-packaged) uses real Kubernetes Secrets -throughout: +The chart never puts Redis URLs, the database registry, or the embedding +credential in `values.yaml` or a rendered ConfigMap. Each of the Data Plane, +Control Plane, and (bundled) Identity Service reads its own pre-created +overlay Secret, deep-merged over its rendered base config at runtime. See +[Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}) +for the overlay content each component expects. | Secret | Required when | Default key | | --- | --- | --- | -| LangCache license Secret | Control Plane managed caches | `license` | -| Control Plane config Secret | Control Plane used | `controlplane-onprem.config.yaml` | -| Control Plane admin-token Secret | Control Plane used | `token` | -| Identity Service introspection-token Secret | Agent-key Data Plane auth used | `token` | +| LangCache license Secret | Always | `license` | +| Data Plane config overlay Secret | Always | `overlay.yaml` | +| Control Plane config overlay Secret | Always | `overlay.yaml` | +| Identity Service metadata Secret | `identityService.mode: bundled` | `metadata.yaml` | +| Control Plane admin token | Auto-generated by default, or bring your own | `token` | +| Control Plane internal (grant-validation) token | Auto-generated by default, or bring your own | `token` | +| Identity Service control token (bundled mode) | Auto-generated by default, or bring your own | `token` | +| Data Plane's Identity Service runtime credential (external mode) | `identityService.mode: external` | `token`, minted by the suite-level Identity Service owner | + +## Release artifacts and image tags + +LangCache self-managed image tags use the release SemVer value, for example: + +```yaml +dataplane: + image: + repository: redislabs/iris-langcache-data + tag: "" +controlplane: + image: + repository: redislabs/iris-langcache-control + tag: "" +identityService: + bundled: + image: + repository: redislabs/iris-identity-service + tag: "" +``` + +Use the image tags listed for the release on Docker Hub or provided by +Redis. Do not use floating image tags in production. + +## Air-gapped and private registry installs + +Mirror the published images into your internal registry: + +```bash +for image in iris-langcache-data iris-langcache-control iris-identity-service; do + docker pull redislabs/$image: + docker tag redislabs/$image: \ + registry.example.com/redislabs/$image: + docker push registry.example.com/redislabs/$image: +done +``` + +If the registry requires authentication, create an image pull Secret and +reference it from `imagePullSecrets` in your values file: + +```bash +kubectl -n create secret docker-registry langcache-registry \ + --docker-server=registry.example.com \ + --docker-username= \ + --docker-password= +``` + +```yaml +imagePullSecrets: + - name: langcache-registry +``` ## System requirements -Default chart values for the published `langcache` chart: +Default chart values: | Component | Default | Purpose | | --------- | ------- | ------- | -| LangCache Data Plane | 1 replica, autoscaling disabled | Data Plane API traffic | +| LangCache Data Plane | 2 replicas with autoscaling enabled (2–10) | Data Plane API traffic | +| LangCache Control Plane | 1 replica, no autoscaling | Admin API for caches | +| Identity Service (bundled mode) | 1 replica | Agent-key issuance and introspection | -For production, review `replicaCount` and `autoscaling` and size explicitly -for the expected request volume; the chart's defaults are intended for a -first install, not a production HA recommendation. +During a rolling update, Kubernetes may temporarily run old and new pods at +the same time. A small test cluster can run out of CPU during install or +upgrade; size for the maximum rolling-update overlap, or reduce replicas +explicitly for a lab install. ## Helm values to review -The walkthroughs use `langcache` as the Helm release name. The generated -service and deployment names in the verification steps assume that release -name. +The walkthroughs in this guide assume the chart's default +`fullnameOverride: langcache`, which fixes the rendered resource names to +`langcache` (Data Plane), `langcache-controlplane`, and +`langcache-identity-service` (bundled mode). If you change it, update the +release-derived names in the verification commands throughout this guide. {{< table-scrollable >}} | Area | Values | Use when | | --- | --- | --- | -| Image | `image.repository`, `image.tag`, `imagePullSecrets` | Selecting a release or private registry image. | -| Config | `config` (inline `dataplane.config.yaml` content) | Configuring caches, embeddings, and auth. Renders into a ConfigMap; treat the values file as sensitive. | -| Capacity | `resources`, `autoscaling.*` | Tuning request capacity or memory footprint. | -| Scheduling | `nodeSelector`, `affinity`, `tolerations` | Controlling pod placement. | -| Networking | `service.type`, `ingress.*` | Exposing LangCache outside the cluster. | -| Naming | `fullnameOverride` | Running more than one LangCache release in a namespace. | -| Service account | `serviceAccount.*` | Matching customer namespace security policy. | -| Cache-index provisioning | `initProvisioner.enabled`, `initProvisioner.config` | Running the `provision-cache-index` init container against static caches before the Data Plane starts. | +| Images | `dataplane.image.*`, `controlplane.image.*`, `identityService.bundled.image.*`, `imagePullSecrets` | Selecting a release or private registry image. | +| Data Plane capacity | `dataplane.resources`, `dataplane.autoscaling.*` | Tuning request capacity or memory footprint. | +| Networking | `dataplane.service.*`, `dataplane.ingress.*` | Exposing LangCache outside the cluster. | +| Security posture | `security.profile` | Opting into the FIPS-oriented posture. | +| Identity Service mode | `identityService.mode` (`bundled` or `external`) | Choosing whether this release runs its own Identity Service or joins one the suite already runs. | +| Config overlays | `dataplane.secrets.*`, `controlplane.secrets.*`, `identityService.bundled.metadata.*` | Pointing the chart at your pre-created overlay Secrets. | +| Rotation | `*.existingSecretChecksum` fields throughout | Rolling pods after an externally managed Secret changes. | {{< /table-scrollable >}} - -Do not use floating image tags in production. diff --git a/content/operate/iris/langcache/self-managed/reference.md b/content/operate/iris/langcache/self-managed/reference.md index 9920a11c78..2459b0d901 100644 --- a/content/operate/iris/langcache/self-managed/reference.md +++ b/content/operate/iris/langcache/self-managed/reference.md @@ -17,42 +17,36 @@ Use these files to configure a self-managed deployment: | File | Purpose | | --- | --- | -| `langcache-values.yaml` | Helm values for the Data Plane image, replicas, services, and inline `dataplane.config.yaml` content. Treat this file as sensitive. | -| `dataplane.config.yaml` | Data Plane caches, Redis URLs, auth mode, and embedding settings; provided inline under the chart's `config` value. | -| `controlplane-onprem.config.yaml` | Control Plane metadata Redis, database registry, admin-token auth, and embedding contract. | -| `license` | LangCache license file provided by Redis, required by the on-prem-hardened Control Plane and Data Plane binaries. | +| `langcache-values.yaml` | Helm values for images, replicas, services, security posture, Identity Service mode, and non-secret config structure. | +| `dp-overlay.yaml` | Data Plane's Metadata Redis URLs and (if static) embedding credential, deep-merged over the rendered config at startup. | +| `cp-overlay.yaml` | Control Plane's Metadata Redis URLs and Cache Redis database registry, deep-merged over the rendered config at startup. | +| `ids-metadata.yaml` | Bundled Identity Service's own Metadata Redis URLs. | +| `langcache.key` | LangCache license file provided by Redis. | ### External secret managers -The license, Control Plane config, Control Plane admin-token, and Identity -Service introspection-token material in this guide are all real Kubernetes -Secrets. If you use an external secret manager, expose that material as -Kubernetes Secrets and reference those Secret names in the Control Plane -manifest's `secretName` fields or the Data Plane chart's generic -`volumes`/`volumeMounts` values. - -The Data Plane's `dataplane.config.yaml` content itself is a Helm value -(`config`), not a Secret, in the current chart; see -[Data Plane configuration]({{< relref "/operate/iris/langcache/self-managed/data-plane-configuration#config-storage" >}}) -for a Secret-backed alternative if your security policy requires one. +If you use an external secret manager, expose the license, overlay, and +token material to the chart as Kubernetes Secrets and set the chart's +`existingSecret` values to those Secret names. ## Troubleshooting {{< table-scrollable >}} | Symptom | Likely cause | Fix | | --- | --- | --- | -| Docker pull fails for the configured image tag | Image tag is wrong, or the image has not been mirrored into a registry your cluster can reach | Use the image reference provided by your Redis representative and mirror it into your registry if needed. | -| Pod is stuck in `ImagePullBackOff` or `ErrImagePull` | Cluster cannot pull the configured image, image tag is wrong, registry requires credentials, or `imagePullSecrets` is missing/wrong | Verify `image.repository`, `image.tag`, registry reachability, and `imagePullSecrets`. | +| Docker pull fails for the configured image tag | Image tag is wrong or not published yet | Use the image tag listed for the release on Docker Hub or provided by Redis. | +| Pod is stuck in `ImagePullBackOff` or `ErrImagePull` | Cluster cannot pull the configured image, image tag is wrong, registry requires credentials, or `imagePullSecrets` is missing/wrong | Verify `dataplane.image.*`/`controlplane.image.*`/`identityService.bundled.image.*`, registry reachability, and `imagePullSecrets`. | | `helm install --atomic --wait` times out and rolls back | Cluster is small or image pull/startup takes longer than Helm's default timeout | Install without `--atomic --wait`, or set a longer `--timeout` and ensure enough cluster capacity. | -| Data Plane health fails | Pod not ready, config invalid, or Redis unavailable | Check pod logs and call `/health`, `/health/liveness`, and `/health/readiness`. | -| Data Plane fails to start with an on-prem-hardened image against static config | The on-prem-hardened Data Plane binary (`cmd/onprem`) only supports Control Plane managed caches with agent-key auth; it rejects static `metadata.caches` and other auth methods | Use the static-caches Data Plane image for static caches, or switch to Control Plane managed caches. | -| Cache search or set requests fail with an index error | The RediSearch vector index for the cache was never provisioned, or Cache Redis does not support RediSearch with vector search | Run `provision-cache-index` against the cache's config, or verify Cache Redis modules. | -| Control Plane `CreateCache` returns `424` | Cache Redis for the resolved `databaseId` is unreachable or does not satisfy LangCache's Redis module requirements | Check `databases..urls` connectivity and Redis modules. | +| Chart fails to render with `identityService.mode: bundled` and `security.profile: fips` | The FIPS posture forbids the bundled Identity Service's unencrypted in-cluster address | Use `identityService.mode: external` with a TLS-fronted Identity Service. | +| Data Plane health fails | Pod not ready, overlay Secret missing/invalid, or Redis unavailable | Check pod logs and call `/health`, `/health/liveness`, and `/health/readiness`. | +| Cache search or set requests fail with an index error | The RediSearch vector index for the cache was never provisioned, or Cache Redis does not support RediSearch with vector search | Check Control Plane cache status (`GET /v1/caches/{cacheId}`) and Cache Redis modules. | +| Control Plane `CreateCache` returns `424` | Cache Redis for the resolved `databaseId` is unreachable or does not satisfy LangCache's Redis module requirements | Check the `databases..urls` connectivity and Redis modules in `cp-overlay.yaml`. | | Control Plane `CreateCache` returns `400` for embedding fields | Request tried to select a different embedding provider/model/dimensions than the deployment's single configured contract, or supplied per-cache embedding credentials | On-prem cache creation uses the deployment-wide embedding contract; it does not accept per-cache overrides or credentials. | -| Agent receives `401` on a Control Plane managed cache | Missing, malformed, revoked, expired, or invalid agent key, or the Data Plane cannot reach the Identity Service | Check the `Authorization` header, key status through the Identity Service, and Data Plane connectivity to `auth.agent_keys.introspection.base_url`. | -| Agent receives `403` on a Control Plane managed cache | Key exists but lacks the required `lc-cache:` grant or action | Update grants through the Identity Service's `/v1/api-keys/{keyId}` endpoint. | -| Cache created by the Control Plane is not visible to the Data Plane | CP and DP point at different Metadata Redis URLs, or the Data Plane is still running the static-caches binary | Make CP `metadata.urls` match DP `metadata.urls`, and confirm the Data Plane is running the on-prem-hardened (`cmd/onprem`) binary. | -| Legacy static-cache token is rejected | Token was generated with a different passphrase or resource ID than the running config | Regenerate the token with `generate-auth-token` against the exact `dataplane.config.yaml` in use. | +| Agent receives `401` | Missing, malformed, revoked, expired, or invalid agent key, or the Data Plane cannot reach the Identity Service | Check the `Authorization` header, key status through the Identity Service, and Data Plane connectivity to the Identity Service (bundled Service or `identityService.external.baseURL`). | +| Agent receives `403` | Key exists but lacks the required `lc-cache:` grant or action | Update grants through the Identity Service's `/v1/api-keys/{keyId}` endpoint. | +| Cache created by the Control Plane is not visible to the Data Plane | Data Plane and Control Plane overlays point at different Metadata Redis URLs | Make `dp-overlay.yaml` and `cp-overlay.yaml` use the same `metadata.urls`. | +| `helm upgrade` doesn't roll a pod after rotating an overlay Secret | The matching `existingSecretChecksum` value wasn't bumped | Recalculate the SHA-256 checksum of the overlay file and set the corresponding `*.existingSecretChecksum` value. | +| External Identity Service rejects LangCache's introspection calls | The suite-level Identity Service's `product_validation.langcache` isn't configured against this release's Control Plane internal Service and `internalToken` | Ask the Identity Service owner to configure that product entry; see [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication#external-identity-service" >}}). | | NetworkPolicy blocks expected traffic | Placeholder namespace, release name, or caller selectors were not customized correctly | Check the Helm release label `app.kubernetes.io/instance`, caller namespace, and caller pod labels. | {{< /table-scrollable >}} @@ -60,7 +54,7 @@ for a Secret-backed alternative if your security policy requires one. | Need | Reference | | --- | --- | -| Helm chart values | `langcache/helm/values.yaml` in the LangCache source repository | +| Helm chart values and README | `langcache/helm/` in the LangCache source repository | | LangCache API reference (Data Plane) | [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) | | Control Plane API reference | [Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}) | | LangCache overview | [LangCache overview]({{< relref "/develop/ai/context-engine/langcache" >}}) | From 8762844b6dc1253cff6f40d9877e5c55fda04f68 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:39:16 +0300 Subject: [PATCH 05/10] MOD-17747: Confirm and use the now-published langcache Helm chart repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified against the real release: RedisLabs/redis-enterprise-helm now carries ai/charts/langcache (chart v0.0.1, synced from langcache/helm at origin/main — content is byte-identical except default image tags now pinned to 0.0.1 instead of empty), and https://helm.redis.io/ai/index.yaml actually serves a "langcache" entry as of today. This confirms, rather than just infers by analogy with RAM, the chart's public distribution channel. - prerequisites.md/reference.md: state the chart is published to https://helm.redis.io/ai (same repo as self-managed Redis Agent Memory) instead of "contact your Redis representative for exact coordinates." Split the reference.md "contact your rep" row so it only covers the license key now, not chart/image access (both of which are public). - deploy.md/operations.md: install/upgrade/helm-test commands now use `helm repo add redis-ai https://helm.redis.io/ai` + `helm install/upgrade langcache redis-ai/langcache --version `, matching the real, now-public flow, with a note for anyone still installing from a local chart checkout or package instead. No other content changed — the chart's actual config schema, ports, overlay mechanism, and image names documented in the previous revision all matched the published release exactly. Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/deploy.md | 22 ++++++++++++++----- .../iris/langcache/self-managed/operations.md | 9 +++++--- .../langcache/self-managed/prerequisites.md | 6 ++--- .../iris/langcache/self-managed/reference.md | 6 +++-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/deploy.md b/content/operate/iris/langcache/self-managed/deploy.md index d4c9169b6f..5f9a2b4529 100644 --- a/content/operate/iris/langcache/self-managed/deploy.md +++ b/content/operate/iris/langcache/self-managed/deploy.md @@ -117,18 +117,29 @@ to retrieve them, or set `existingSecret` to bring your own. ## Install the chart -Install from the chart package or repository your Redis representative -provides. From the chart's own root directory (`langcache/helm/` in the -source layout): +Add the Helm repository when installing from the public repository: ```bash -helm install langcache . \ +helm repo add redis-ai https://helm.redis.io/ai +helm repo update redis-ai +helm search repo redis-ai/langcache --versions +``` + +Install with `langcache` as the Helm release name: + +```bash +helm install langcache redis-ai/langcache \ + --version \ --namespace \ --create-namespace \ -f langcache-values.yaml \ --atomic --wait ``` +If you installed from a chart package or a local checkout instead, replace +`redis-ai/langcache --version ` with the chart path (for +example `.` from the chart's own root directory). + On small clusters, install without `--atomic --wait`, then watch pod status: @@ -191,7 +202,8 @@ and [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples ## Update ```bash -helm upgrade langcache . \ +helm upgrade langcache redis-ai/langcache \ + --version \ --namespace \ -f langcache-values.yaml \ --atomic --wait diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index 98be100718..32c22b66c6 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -76,7 +76,8 @@ shasum -a 256 ./dp-overlay.yaml | awk '{print $1}' Apply the updated values and verify the workloads rolled: ```bash -helm upgrade langcache . \ +helm upgrade langcache redis-ai/langcache \ + --version \ --namespace \ -f langcache-values.yaml @@ -106,7 +107,8 @@ For every update: 4. Verify pod rollout and health endpoints. ```bash -helm upgrade langcache . \ +helm upgrade langcache redis-ai/langcache \ + --version \ --namespace \ -f langcache-values.yaml \ --atomic --wait @@ -121,7 +123,8 @@ The chart can render `helm test` resources when `tests.enabled: true`. This renders the shared security-profile check and the minimal RBAC it needs: ```bash -helm upgrade --install langcache . \ +helm upgrade --install langcache redis-ai/langcache \ + --version \ --namespace \ -f langcache-values.yaml \ --set tests.enabled=true diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md index 125d8b58a3..962d400a60 100644 --- a/content/operate/iris/langcache/self-managed/prerequisites.md +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -29,7 +29,7 @@ Kubernetes cluster. | Item | Where it comes from | | ---- | ------------------- | | Container images | `redislabs/iris-langcache-data`, `redislabs/iris-langcache-control`, and (bundled Identity Service) `redislabs/iris-identity-service` on Docker Hub | -| Helm chart | `langcache` chart, synced to the Redis Enterprise Helm chart repository. Contact your Redis representative for the exact repository coordinates and chart version, or for a chart package. | +| Helm chart | `langcache` chart, published to `https://helm.redis.io/ai` (the same repository as the self-managed Redis Agent Memory chart), or a chart package provided by Redis. | | Redis databases | You provide Metadata Redis and one or more Cache Redis databases | | License key | Contact your Redis representative or [contact sales](https://redis.io/contact/). | | Provider credentials | You provide embedding provider credentials (currently an OpenAI-compatible provider) | @@ -76,9 +76,9 @@ removes Control Plane cache records. - **Connected install:** the cluster must be able to pull the LangCache and Identity Service images from Docker Hub (or your mirrored registry) and - reach the Helm chart repository. + reach `https://helm.redis.io/ai`. - **Air-gapped install:** mirror the images into an internal registry and - use a locally available chart package. + use a locally downloaded chart package. - **Runtime access:** LangCache pods must reach the Redis databases and the embedding provider endpoint used by the deployment. The Data Plane must also reach the Identity Service (bundled or external); the Control Plane diff --git a/content/operate/iris/langcache/self-managed/reference.md b/content/operate/iris/langcache/self-managed/reference.md index 2459b0d901..576702a3e0 100644 --- a/content/operate/iris/langcache/self-managed/reference.md +++ b/content/operate/iris/langcache/self-managed/reference.md @@ -54,8 +54,10 @@ token material to the chart as Kubernetes Secrets and set the chart's | Need | Reference | | --- | --- | -| Helm chart values and README | `langcache/helm/` in the LangCache source repository | +| Helm chart repository | `https://helm.redis.io/ai`, chart `langcache` | +| Helm chart values and README | `langcache/helm/` in the LangCache source repository, or the synced copy in `RedisLabs/redis-enterprise-helm` at `ai/charts/langcache` | +| Container images | Docker Hub: [redislabs/iris-langcache-data](https://hub.docker.com/r/redislabs/iris-langcache-data/tags), [redislabs/iris-langcache-control](https://hub.docker.com/r/redislabs/iris-langcache-control/tags), [redislabs/iris-identity-service](https://hub.docker.com/r/redislabs/iris-identity-service/tags) | | LangCache API reference (Data Plane) | [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) | | Control Plane API reference | [Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}) | | LangCache overview | [LangCache overview]({{< relref "/develop/ai/context-engine/langcache" >}}) | -| Container images and chart access | Contact your Redis representative or [contact sales](https://redis.io/contact/) | +| License key | Contact your Redis representative or [contact sales](https://redis.io/contact/) | From 1cdc3aae244fac3bd33adb9d3f27c072429366e0 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:06:32 +0300 Subject: [PATCH 06/10] MOD-17747: Address review feedback from mich-elle-luna Applied all 22 inline review suggestions from PR #3925: - _index.md: wording fixes ("faster", "either returns a", "no lighter-weight install of only the Data Plane", period instead of em-dash). - authentication.md: reworded the admin/internal-token-mismatch sentence and the bundled-mode intro; renamed "### Bundled" to "### Bundled Identity Service" (matching "### External Identity Service") with an explicit "choose either ... or ..." lead-in; added the missing article to the external credential sentence; added a "Next steps" section. - configuration.md: split the overlay-mechanism sentence for clarity, reworded the `authorized: true` rule and the bundled Identity Service metadata intro; added a "Next steps" section. - deploy.md: dropped "(by default)"/"(default)" qualifiers now that bundled vs. external is chosen explicitly one section down; added a "Next steps" section. - operations.md: added a "See also" section. - prerequisites.md: dropped the same "(by default)"/"(bundled)" qualifiers; added a "Next steps" section. Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/_index.md | 8 ++++---- .../langcache/self-managed/authentication.md | 19 +++++++++++++------ .../langcache/self-managed/configuration.md | 15 ++++++++++----- .../iris/langcache/self-managed/deploy.md | 10 ++++++++-- .../iris/langcache/self-managed/operations.md | 6 ++++++ .../langcache/self-managed/prerequisites.md | 10 ++++++++-- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md index f1bca1f321..40cda0b969 100644 --- a/content/operate/iris/langcache/self-managed/_index.md +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -11,8 +11,8 @@ weight: 40 hideListLinks: true --- -LangCache is a semantic caching service that stores LLM responses for fast, -cheaper retrieval. Applications send prompts to LangCache, which returns a +LangCache is a semantic caching service that stores LLM responses for faster, +cheaper retrieval. Applications send prompts to LangCache, which either returns a cached response for a semantically similar prior prompt or calls out to your embedding provider and stores a new entry when there is no match. @@ -34,8 +34,8 @@ key to deploy it. Contact your Redis representative or One `helm install` of the `langcache` chart always creates the Data Plane and the Control Plane, plus either a bundled or an external Identity Service. -There is no lighter-weight "Data Plane only" install for self-managed -LangCache — every cache is created and managed through the Control Plane, and +There is no lighter-weight install of only the Data Plane for self-managed +LangCache. Every cache is created and managed through the Control Plane, and every Data Plane request is authenticated by the Identity Service. | Component | Purpose | Default service | diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md index d20ff76d6d..b5c545b388 100644 --- a/content/operate/iris/langcache/self-managed/authentication.md +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -75,16 +75,15 @@ In external mode, you must give this token to the Identity Service's owner (see [External Identity Service](#external-identity-service)). The admin token and internal token must always be different values; the -Control Plane rejects config where they match. +Control Plane rejects a configuration where admin token and internal token match. ## Identity Service modes -Choose exactly one mode at install time — there is no default that applies -without choosing. +You must choose either Bundled Identity Service or External Identity Service at install time. -### Bundled +### Bundled Identity Service -`identityService.mode: bundled` (the default) renders the Identity Service +`identityService.mode: bundled` renders the Identity Service Deployment and Service, auto-generates its control token and the Data Plane's own runtime introspection credential, and wires everything together automatically: @@ -124,7 +123,7 @@ identityService: secretKey: token ``` -`langcache-dp-ids-credential` is minted out of band by the suite-level +The `langcache-dp-ids-credential` is minted out of band by the suite-level Identity Service owner, scoped to `api-key-introspect` on product `langcache`. You must also ask that owner to configure the external Identity Service's own `product_validation.langcache` against this @@ -201,3 +200,11 @@ Gateway rules: trusted applications. - Callers must not be able to bypass the gateway and reach the Data Plane directly unless they also present a valid LangCache agent key. + +## Next steps + +With an admin token, internal token, and agent key in hand, see +[API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}) +to create a cache and start calling the Data Plane, or +[Operations]({{< relref "/operate/iris/langcache/self-managed/operations" >}}) +to rotate these credentials going forward. diff --git a/content/operate/iris/langcache/self-managed/configuration.md b/content/operate/iris/langcache/self-managed/configuration.md index 0b277f5be1..c9922d5a8b 100644 --- a/content/operate/iris/langcache/self-managed/configuration.md +++ b/content/operate/iris/langcache/self-managed/configuration.md @@ -20,8 +20,8 @@ Plane, the Control Plane, and (in bundled mode) the Identity Service: - **Redis URLs, the database registry, and the embedding credential**, which never go in `values.yaml` or a rendered ConfigMap. Each component reads its own pre-created overlay Secret, deep-merged over its rendered - base config at container startup (later files win — the chart passes each - overlay as an additional `--config` flag). + base config at container startup. The chart passes each overlay as an + additional `--config` flag, so later files win. You always create the overlay Secrets yourself; the chart only tells each component where to mount and read them. @@ -109,13 +109,13 @@ as `databaseId` when creating caches through the Control Plane API. The `embedders` block must describe exactly one provider with exactly one model — the embedding contract that cache creation and the Data Plane's `dataplane.embedding` values must agree on exactly. It must not set -`authorized: true`; on-prem cache creation cannot accept per-cache embedding +`authorized: true` because on-prem cache creation cannot accept per-cache embedding credentials. ## Identity Service metadata (bundled mode only) -When `identityService.mode: bundled` (the default), the bundled Identity -Service needs its own Metadata Redis connection — it can be the same Redis +When `identityService.mode: bundled` is set, the bundled Identity +Service needs its own Metadata Redis connection. This connection can be the same Redis instance as the Control Plane's Metadata Redis, in a separate namespace. ```yaml @@ -154,3 +154,8 @@ credential across separately rotated Secrets. Store `dp-overlay.yaml`, `cp-overlay.yaml`, and `ids-metadata.yaml` outside your values files and outside git, the same as any other credential material. + +## Next steps + +With your overlay Secrets and values ready, continue to +[Deploy self-managed LangCache]({{< relref "/operate/iris/langcache/self-managed/deploy" >}}). diff --git a/content/operate/iris/langcache/self-managed/deploy.md b/content/operate/iris/langcache/self-managed/deploy.md index 5f9a2b4529..09f931026b 100644 --- a/content/operate/iris/langcache/self-managed/deploy.md +++ b/content/operate/iris/langcache/self-managed/deploy.md @@ -12,7 +12,7 @@ hideListLinks: true --- One `helm install` of the `langcache` chart deploys the Data Plane, the -Control Plane, and (by default) a bundled Identity Service. There is no +Control Plane, and a bundled Identity Service. There is no separate lighter-weight install path; every self-managed LangCache deployment uses all three components. @@ -26,7 +26,7 @@ Decide before you install: | Mode | Use when | Values | | --- | --- | --- | -| Bundled (default) | This is your first LangCache install, or your suite doesn't already run an Identity Service. | `identityService.mode: bundled` | +| Bundled | This is your first LangCache install, or your suite doesn't already run an Identity Service. | `identityService.mode: bundled` | | External | Your suite already runs an Identity Service (for example, alongside self-managed Redis Agent Memory) and you want LangCache to share it. | `identityService.mode: external` | This guide uses bundled mode. For external mode, see @@ -208,3 +208,9 @@ helm upgrade langcache redis-ai/langcache \ -f langcache-values.yaml \ --atomic --wait ``` + +## Next steps + +- [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) to mint agent keys and configure the Identity Service mode you chose. +- [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}) to start calling the Data Plane. +- [Operations]({{< relref "/operate/iris/langcache/self-managed/operations" >}}) for backups, secret rotation, and FIPS posture. diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index 32c22b66c6..402793f1e5 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -208,3 +208,9 @@ directly. Write a NetworkPolicy for your cluster's CNI that default-denies ingress to the `langcache`, `langcache-controlplane`, and (bundled mode) `langcache-identity-service` Services, then allow TCP traffic on their respective ports (`9000`, `9100`, `9200`) from approved callers only. + +## See also + +- [Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}) for the Redis roles being backed up and rotated here. +- [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) for how the tokens and agent keys rotated above are used. +- [Configuration and troubleshooting]({{< relref "/operate/iris/langcache/self-managed/reference" >}}) for symptoms and fixes if a rotation or update doesn't take effect. diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md index 962d400a60..81c6c57edf 100644 --- a/content/operate/iris/langcache/self-managed/prerequisites.md +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -13,7 +13,7 @@ hideListLinks: true LangCache self-managed is distributed as container images on Docker Hub plus the `langcache` Helm chart. One `helm install` of the chart deploys the -LangCache Data Plane, the LangCache Control Plane, and (by default) a +LangCache Data Plane, the LangCache Control Plane, and a bundled Identity Service. You provide the Redis databases, embedding provider credentials, Kubernetes @@ -90,7 +90,7 @@ removes Control Plane cache records. The chart never puts Redis URLs, the database registry, or the embedding credential in `values.yaml` or a rendered ConfigMap. Each of the Data Plane, -Control Plane, and (bundled) Identity Service reads its own pre-created +Control Plane, and bundled Identity Service reads its own pre-created overlay Secret, deep-merged over its rendered base config at runtime. See [Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}) for the overlay content each component expects. @@ -191,3 +191,9 @@ release-derived names in the verification commands throughout this guide. | Config overlays | `dataplane.secrets.*`, `controlplane.secrets.*`, `identityService.bundled.metadata.*` | Pointing the chart at your pre-created overlay Secrets. | | Rotation | `*.existingSecretChecksum` fields throughout | Rolling pods after an externally managed Secret changes. | {{< /table-scrollable >}} + +## Next steps + +Continue to [Configuration]({{< relref "/operate/iris/langcache/self-managed/configuration" >}}) +to prepare the Data Plane, Control Plane, and Identity Service overlay +Secrets, then [Deploy self-managed LangCache]({{< relref "/operate/iris/langcache/self-managed/deploy" >}}). From 224471ff4313f1a6f93c7c61f2b7788039575605 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:32:21 +0300 Subject: [PATCH 07/10] MOD-17747: Tighten token-rotation claim after deep source verification Downloaded the actual published chart tarball (langcache-0.0.1.tgz from the helm.redis.io/ai release) and cross-checked every technical claim in the PR against its templates/_helpers.tpl, values.yaml, and NOTES.txt, plus the identity-service, controlplane-onprem, and dataplane Smithy/Go source at origin/main. Everything else held up exactly as documented (ports, resource names, secret keys, overlay mount paths, FIPS validation messages, the Identity Service's Grant/CreateAPIKey shapes, the internal grant-validation path, and the /health endpoints all matched byte-for-byte or field-for-field). One place was more hedged than it needed to be: operations.md's auto-generated-token rotation guidance said to "confirm which behavior your chart version implements" because I hadn't verified the underlying mechanism. controlplane-secrets.yaml and identity-service-secrets.yaml both show the real mechanism directly: a lookup-or-generate helper that re-reads the existing Secret on every helm upgrade (keeping it stable) plus a helm.sh/resource-policy: keep annotation, so deleting the Secret and re-running helm upgrade does mint a fresh token. Replaced the hedge with that confirmed explanation. Co-Authored-By: Claude Sonnet 5 --- .../operate/iris/langcache/self-managed/operations.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index 402793f1e5..ae4e477b6a 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -88,10 +88,12 @@ kubectl -n rollout status deployment/langcache-controlplane Rotating an auto-generated token (admin token, internal token, Identity Service control token, or the Data Plane's Identity Service runtime credential) is different: those Secrets are Helm-managed, not -`existingSecret`, so there is no checksum to bump. Set `autoGenerate: false` -temporarily and supply a new `existingSecret`, or delete the underlying -Secret and let the next `helm upgrade` regenerate it — confirm which -behavior your chart version implements before relying on it in production. +`existingSecret`, so there is no checksum to bump. The chart looks up the +existing Secret on every `helm upgrade` and keeps its value stable unless +the Secret is gone, so either set `autoGenerate: false` and supply a new +`existingSecret`, or delete the underlying Secret (it carries a +`helm.sh/resource-policy: keep` annotation, so `helm uninstall` won't do +this for you) and let the next `helm upgrade` mint a fresh one. Rotate agent keys minted for LangCache caches through the Identity Service; see [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples#identity-service-api-examples" >}}). From ea2afab97a9f6eef8b996bf6ca03d157b46c7044 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:35:47 +0300 Subject: [PATCH 08/10] MOD-17747: Fix findings from deep code review (code-review skill, high) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _index.md: split "Cache entries" table row so flush's real path (/v1/caches/{cacheId}/flush) isn't implied to live under /entries; added a note that the shared LangCache API reference doesn't yet cover conversational search or cache health (confirmed: content/develop/ai/ context-engine/langcache/api-reference/api.yaml only has entries/search, entries, entries/{entryId}, and flush — both endpoints are real on the actual Data Plane per the Smithy source, just missing from that shared spec, which is out of scope to edit here). - api-examples.md: added a real "Search using conversation history" example (verified against ConversationalSearchBody/-Output in the DP Smithy source: prompt, context as chronological turns, actualPrompt in the response) instead of just claiming conversational search was covered by a reference that doesn't include it. - reference.md: replaced a troubleshooting row describing a 400 for "per-cache embedding fields" on CreateCache — CreateCacheRequestContent has no embedding-related field at all, so that scenario can't occur as described. Replaced with the request fields that actually exist and can fail validation. - authentication.md: added the missing Secret name and retrieval command for the Data Plane's own auto-generated Identity Service runtime credential (langcache-identity-service-dp-credential) — previously mentioned as existing but never given a name, unlike the other three auto-generated tokens. Not changed: the generated openapi-control-plane.json's PATCH /v1/caches returning 201 with no body. Verified directly against the Smithy source (@http(method: "PATCH", ..., code: 201), no output) — that's what the real API does, however unusual; "fixing" it to 200 would misrepresent it. Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/_index.md | 8 +++++- .../langcache/self-managed/api-examples.md | 25 +++++++++++++++++-- .../langcache/self-managed/authentication.md | 9 +++++++ .../iris/langcache/self-managed/reference.md | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md index 40cda0b969..7cae98ba32 100644 --- a/content/operate/iris/langcache/self-managed/_index.md +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -69,11 +69,17 @@ boundary for cached entries. | API surface | Endpoint prefix | Purpose | | --- | --- | --- | -| Cache entries | `/v1/caches/{cacheId}/entries` | Set, search, delete, and flush cached entries. | +| Cache entries | `/v1/caches/{cacheId}/entries` | Set, search, and delete cached entries. | +| Cache flush | `/v1/caches/{cacheId}/flush` | Flush all entries in a cache. | | Conversational search | `/v1/caches/{cacheId}/conversations/search` | Search using conversation history context. | | Cache health | `/v1/caches/{cacheId}/health` | Cache-scoped health status. | | Control Plane | `/v1/caches`, `/v1/embedding-providers` | Self-managed administration for caches. | | Identity Service | `/v1/api-keys` | Mint, list, update, revoke, and rotate agent keys and their cache grants. | +The [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) +reference does not yet document conversational search or cache health; for +those two, use [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}) +until the shared schema is updated. + Start with [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}), then follow [Deploy self-managed LangCache]({{< relref "/operate/iris/langcache/self-managed/deploy" >}}). diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md index f0e6e0929f..7e63d765db 100644 --- a/content/operate/iris/langcache/self-managed/api-examples.md +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -212,6 +212,25 @@ curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/flush" \ -H "Authorization: Bearer $LC_AGENT_KEY" ``` +### Search using conversation history + +```bash +curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/conversations/search" \ + -H "Authorization: Bearer $LC_AGENT_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "prompt": "What about the capital of Germany?", + "context": [ + "What is the capital of France?", + "The capital of France is Paris." + ] + }' +``` + +`context` is prior conversation turns in chronological order. When +provided, LangCache reformulates the query before searching, then returns +the reformulated `actualPrompt` alongside the matching entries. + ### Check cache health ```bash @@ -219,6 +238,8 @@ curl -sS "$DP_URL/v1/caches/$CACHE_ID/health" \ -H "Authorization: Bearer $LC_AGENT_KEY" ``` -For the full request and response schema for these operations, including -conversational search, see the +For the full request and response schema for cache entries (set, search, +delete, flush), see the [LangCache API reference]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}). +That shared reference does not yet cover conversational search or cache +health; the examples above reflect the same Data Plane API. diff --git a/content/operate/iris/langcache/self-managed/authentication.md b/content/operate/iris/langcache/self-managed/authentication.md index b5c545b388..c5063f1f78 100644 --- a/content/operate/iris/langcache/self-managed/authentication.md +++ b/content/operate/iris/langcache/self-managed/authentication.md @@ -107,6 +107,15 @@ kubectl -n get secret langcache-identity-service-control-token -o jsonpath="{.data.token}" | base64 -d ``` +The chart also auto-generates a separate credential the Data Plane itself +uses to call the Identity Service's introspection endpoint (scoped to +`api-key-introspect` on product `langcache` only): + +```bash +kubectl -n get secret langcache-identity-service-dp-credential \ + -o jsonpath="{.data.token}" | base64 -d +``` + ### External Identity Service `identityService.mode: external` renders no Identity Service workload at diff --git a/content/operate/iris/langcache/self-managed/reference.md b/content/operate/iris/langcache/self-managed/reference.md index 576702a3e0..4f8f1218aa 100644 --- a/content/operate/iris/langcache/self-managed/reference.md +++ b/content/operate/iris/langcache/self-managed/reference.md @@ -41,7 +41,7 @@ token material to the chart as Kubernetes Secrets and set the chart's | Data Plane health fails | Pod not ready, overlay Secret missing/invalid, or Redis unavailable | Check pod logs and call `/health`, `/health/liveness`, and `/health/readiness`. | | Cache search or set requests fail with an index error | The RediSearch vector index for the cache was never provisioned, or Cache Redis does not support RediSearch with vector search | Check Control Plane cache status (`GET /v1/caches/{cacheId}`) and Cache Redis modules. | | Control Plane `CreateCache` returns `424` | Cache Redis for the resolved `databaseId` is unreachable or does not satisfy LangCache's Redis module requirements | Check the `databases..urls` connectivity and Redis modules in `cp-overlay.yaml`. | -| Control Plane `CreateCache` returns `400` for embedding fields | Request tried to select a different embedding provider/model/dimensions than the deployment's single configured contract, or supplied per-cache embedding credentials | On-prem cache creation uses the deployment-wide embedding contract; it does not accept per-cache overrides or credentials. | +| Control Plane `CreateCache` returns `400` | A required field is missing, or a field fails validation — for example `databaseId` doesn't match `^[A-Za-z0-9-]+$`, `defaultSearchThreshold` is outside 0–1, or `attributes` has more than 5 entries | Check the request body against [Control Plane API reference]({{< relref "/operate/iris/langcache/self-managed/control-plane-api-reference" >}}). `CreateCache` has no embedding-related fields at all; the embedding provider, model, and dimensions always come from the deployment-wide contract, not the request. | | Agent receives `401` | Missing, malformed, revoked, expired, or invalid agent key, or the Data Plane cannot reach the Identity Service | Check the `Authorization` header, key status through the Identity Service, and Data Plane connectivity to the Identity Service (bundled Service or `identityService.external.baseURL`). | | Agent receives `403` | Key exists but lacks the required `lc-cache:` grant or action | Update grants through the Identity Service's `/v1/api-keys/{keyId}` endpoint. | | Cache created by the Control Plane is not visible to the Data Plane | Data Plane and Control Plane overlays point at different Metadata Redis URLs | Make `dp-overlay.yaml` and `cp-overlay.yaml` use the same `metadata.urls`. | From a64b87d476c8c4c57988c0ccb1121d70e284333d Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:06:39 +0300 Subject: [PATCH 09/10] docs: align LangCache self-managed helm guidance --- .../iris/langcache/self-managed/api-examples.md | 4 ++-- .../iris/langcache/self-managed/configuration.md | 16 +++++----------- .../self-managed/control-plane-api-reference.md | 6 ++++++ .../iris/langcache/self-managed/deploy.md | 16 ++++++++-------- .../iris/langcache/self-managed/operations.md | 5 ++--- .../iris/langcache/self-managed/prerequisites.md | 4 ++-- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md index 7e63d765db..ba2ceb3739 100644 --- a/content/operate/iris/langcache/self-managed/api-examples.md +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -61,8 +61,8 @@ Response: `databaseId` must match an entry in the Control Plane's configured `databases` registry. `defaultSearchThreshold` is a float between 0 and 1. -`defaultTtlMillis` is `-1` for no expiration, or a positive number of -milliseconds. +`defaultTtlMillis` accepts `-1` or `0` for no expiration, or a positive +number of milliseconds. Get a cache: diff --git a/content/operate/iris/langcache/self-managed/configuration.md b/content/operate/iris/langcache/self-managed/configuration.md index c9922d5a8b..1e7309911d 100644 --- a/content/operate/iris/langcache/self-managed/configuration.md +++ b/content/operate/iris/langcache/self-managed/configuration.md @@ -72,7 +72,7 @@ Create `cp-overlay.yaml`. Provide the same Metadata Redis as the Data Plane, plus the `databases` registry — one entry per Cache Redis target, keyed by a logical ID you choose. The Control Plane never receives an embedding credential; it only needs the public provider/model/dimensions contract -(set as `controlplane.configData`, matching `dataplane.embedding`). +that the chart renders from `dataplane.embedding.*`. ```yaml metadata: @@ -97,20 +97,14 @@ controlplane: secretName: cp-overlay configData: profile: prod - embedders: - openai: - models: - - model: text-embedding-3-small - dimensions: 1536 ``` The `databases` map must use the same logical IDs your operators will pass as `databaseId` when creating caches through the Control Plane API. The -`embedders` block must describe exactly one provider with exactly one model -— the embedding contract that cache creation and the Data Plane's -`dataplane.embedding` values must agree on exactly. It must not set -`authorized: true` because on-prem cache creation cannot accept per-cache embedding -credentials. +chart derives the Control Plane's `embedders` config from +`dataplane.embedding.provider` and `dataplane.embedding.models.*`. On-prem +cache creation uses that single provider/model/dimensions contract and +does not accept per-cache embedding credentials. ## Identity Service metadata (bundled mode only) diff --git a/content/operate/iris/langcache/self-managed/control-plane-api-reference.md b/content/operate/iris/langcache/self-managed/control-plane-api-reference.md index 6df3d76a54..df398de63e 100644 --- a/content/operate/iris/langcache/self-managed/control-plane-api-reference.md +++ b/content/operate/iris/langcache/self-managed/control-plane-api-reference.md @@ -8,3 +8,9 @@ params: sourcefile: ./openapi-control-plane.json sortOperationsAlphabetically: false --- + +All Control Plane API requests require the admin bearer token: + +```http +Authorization: Bearer +``` diff --git a/content/operate/iris/langcache/self-managed/deploy.md b/content/operate/iris/langcache/self-managed/deploy.md index 09f931026b..da7a38ae57 100644 --- a/content/operate/iris/langcache/self-managed/deploy.md +++ b/content/operate/iris/langcache/self-managed/deploy.md @@ -12,9 +12,10 @@ hideListLinks: true --- One `helm install` of the `langcache` chart deploys the Data Plane, the -Control Plane, and a bundled Identity Service. There is no -separate lighter-weight install path; every self-managed LangCache -deployment uses all three components. +Control Plane, and either a bundled Identity Service or a connection to an +external Identity Service. There is no separate lighter-weight install +path; every self-managed LangCache deployment uses the Data Plane, Control +Plane, and one Identity Service mode. Before you begin, review [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}) and prepare the config overlays described in @@ -92,11 +93,6 @@ controlplane: secretName: cp-overlay configData: profile: prod - embedders: - openai: - models: - - model: text-embedding-3-small - dimensions: 1536 identityService: mode: bundled @@ -115,6 +111,10 @@ you on first install; see [Authentication and authorization]({{< relref "/operate/iris/langcache/self-managed/authentication" >}}) to retrieve them, or set `existingSecret` to bring your own. +The chart renders the Control Plane's embedding contract from +`dataplane.embedding.*`, so set the provider, model, and dimensions only +under `dataplane.embedding`. + ## Install the chart Add the Helm repository when installing from the public repository: diff --git a/content/operate/iris/langcache/self-managed/operations.md b/content/operate/iris/langcache/self-managed/operations.md index ae4e477b6a..7ae082f84e 100644 --- a/content/operate/iris/langcache/self-managed/operations.md +++ b/content/operate/iris/langcache/self-managed/operations.md @@ -153,9 +153,8 @@ tests: ## FIPS-oriented posture -`security.profile: fips` sets `GODEBUG=fips140=on` on every container this -release renders (Data Plane, Control Plane, and, in bundled mode, the -Identity Service): +In a valid `security.profile: fips` deployment, the chart sets +`GODEBUG=fips140=on` on the Data Plane and Control Plane containers: ```yaml security: diff --git a/content/operate/iris/langcache/self-managed/prerequisites.md b/content/operate/iris/langcache/self-managed/prerequisites.md index 81c6c57edf..448d7034b4 100644 --- a/content/operate/iris/langcache/self-managed/prerequisites.md +++ b/content/operate/iris/langcache/self-managed/prerequisites.md @@ -13,8 +13,8 @@ hideListLinks: true LangCache self-managed is distributed as container images on Docker Hub plus the `langcache` Helm chart. One `helm install` of the chart deploys the -LangCache Data Plane, the LangCache Control Plane, and a -bundled Identity Service. +LangCache Data Plane, the LangCache Control Plane, and either a bundled +Identity Service or a connection to an external Identity Service. You provide the Redis databases, embedding provider credentials, Kubernetes exposure, and license material used by the deployment. From 2a7e46009ab9f3e3f4813d665a4a43f0dacbdd20 Mon Sep 17 00:00:00 2001 From: Todor Todorov <98095+tptodorov@users.noreply.github.com> Date: Fri, 11 Sep 2026 13:23:44 +0300 Subject: [PATCH 10/10] MOD-17747: Drop conversational search from self-managed docs Per teoparvanov's review: conversational search isn't fully supported yet, so remove its coverage from the self-managed LangCache docs for now (_index.md's API surfaces table and component summary, and the api-examples.md endpoint example and its cross-reference note). Co-Authored-By: Claude Sonnet 5 --- .../iris/langcache/self-managed/_index.md | 7 +++--- .../langcache/self-managed/api-examples.md | 23 ++----------------- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/content/operate/iris/langcache/self-managed/_index.md b/content/operate/iris/langcache/self-managed/_index.md index 7cae98ba32..4538a3e816 100644 --- a/content/operate/iris/langcache/self-managed/_index.md +++ b/content/operate/iris/langcache/self-managed/_index.md @@ -40,7 +40,7 @@ every Data Plane request is authenticated by the Identity Service. | Component | Purpose | Default service | | --- | --- | --- | -| LangCache Data Plane | Cache-scoped runtime API for set, search, flush, and conversational search. | `langcache:9000` | +| LangCache Data Plane | Cache-scoped runtime API for set, search, and flush. | `langcache:9000` | | LangCache Control Plane | Admin API for creating and managing caches. | `langcache-controlplane:9100` | | Identity Service | Issues and validates the agent keys the Data Plane requires. Bundled by the chart (default) or an external instance your suite already runs. | `langcache-identity-service:9200` (bundled mode) | | Cache Redis | Holds cache entries and RediSearch vector indexes. Registered by ID in the Control Plane's database registry — the Data Plane has no database registry of its own. | Customer-provided | @@ -71,14 +71,13 @@ boundary for cached entries. | --- | --- | --- | | Cache entries | `/v1/caches/{cacheId}/entries` | Set, search, and delete cached entries. | | Cache flush | `/v1/caches/{cacheId}/flush` | Flush all entries in a cache. | -| Conversational search | `/v1/caches/{cacheId}/conversations/search` | Search using conversation history context. | | Cache health | `/v1/caches/{cacheId}/health` | Cache-scoped health status. | | Control Plane | `/v1/caches`, `/v1/embedding-providers` | Self-managed administration for caches. | | Identity Service | `/v1/api-keys` | Mint, list, update, revoke, and rotate agent keys and their cache grants. | The [LangCache API]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}) -reference does not yet document conversational search or cache health; for -those two, use [API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}) +reference does not yet document cache health; for that, use +[API examples]({{< relref "/operate/iris/langcache/self-managed/api-examples" >}}) until the shared schema is updated. Start with [prerequisites]({{< relref "/operate/iris/langcache/self-managed/prerequisites" >}}), diff --git a/content/operate/iris/langcache/self-managed/api-examples.md b/content/operate/iris/langcache/self-managed/api-examples.md index ba2ceb3739..7989444cfa 100644 --- a/content/operate/iris/langcache/self-managed/api-examples.md +++ b/content/operate/iris/langcache/self-managed/api-examples.md @@ -212,25 +212,6 @@ curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/flush" \ -H "Authorization: Bearer $LC_AGENT_KEY" ``` -### Search using conversation history - -```bash -curl -sS -X POST "$DP_URL/v1/caches/$CACHE_ID/conversations/search" \ - -H "Authorization: Bearer $LC_AGENT_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "prompt": "What about the capital of Germany?", - "context": [ - "What is the capital of France?", - "The capital of France is Paris." - ] - }' -``` - -`context` is prior conversation turns in chronological order. When -provided, LangCache reformulates the query before searching, then returns -the reformulated `actualPrompt` alongside the matching entries. - ### Check cache health ```bash @@ -241,5 +222,5 @@ curl -sS "$DP_URL/v1/caches/$CACHE_ID/health" \ For the full request and response schema for cache entries (set, search, delete, flush), see the [LangCache API reference]({{< relref "/develop/ai/context-engine/langcache/api-reference" >}}). -That shared reference does not yet cover conversational search or cache -health; the examples above reflect the same Data Plane API. +That shared reference does not yet cover cache health; the example above +reflects the same Data Plane API.