> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensormesh.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Every values.yaml key for the Tensormesh Platform Helm chart, plus ready-to-use example overlays.

Configure Tensormesh Platform with a **values file** (`-f my-values.yaml`) rather than
`--set` flags. It's reproducible and reviewable, and the chart validates it against a bundled
`values.schema.json` at parse time (typos and wrong types fail fast). To see every key with
its live default:

```bash theme={null}
helm show values oci://artifacts.tensormesh.ai/tensormesh-production/charts/tensormesh-operator --version <version>
```

<Warning>
  **Pin explicit image tags** in your values file, never `latest`. With
  `imagePullPolicy: IfNotPresent`, a node that cached an image under a mutable tag keeps the
  stale copy. Pin the chart (`--version <version>`) and the runtime image (`v<version>` or an explicit
  nightly). By default the operator image tag follows the chart `appVersion`, but you can still
  override it with `operator.image.tag`. See the
  [Compatibility Matrix](/v1.0.0/installation/compatibility) for the validated version tuple.
</Warning>

## Top level

| Key | Type | Default | Description |
| - | - | - | - |
| `crds.enabled` | bool | `true` | Install the three CRD schemas: `LMCacheEngine`, `LMCacheCoordinator`, `CacheBlendEngine`. |
| `nameOverride` | string | `""` | Override the chart name used in resource names. |
| `fullnameOverride` | string | `""` | Fully override the generated `<release>-<chart>` prefix. |

## `operator` — controller-manager

| Key | Type | Default | Description |
| - | - | - | - |
| `operator.enabled` | bool | `true` | Deploy the controller-manager. Disable for CR-only installs. |
| `operator.replicas` | int | `1` | Replicas. Leader-elected; `>1` = HA standby. |
| `operator.image.repository` | string | `lmcache/lmcache-operator` | Operator image repo. |
| `operator.image.tag` | string | `""` | Empty = chart `appVersion`. Pinning the chart version is the explicit pin. |
| `operator.image.pullPolicy` | string | `IfNotPresent` | `Always` / `IfNotPresent` / `Never`. |
| `operator.image.pullSecrets` | list | `[]` | Image pull secret names. |
| `operator.resources` | object | `requests 10m/256Mi, limits 500m/1Gi` | Operator container resources. Override these for unusually large clusters, but the chart now defaults to a more conservative memory floor than the original low-memory settings. |
| `operator.leaderElection.enabled` | bool | `true` | Required when `replicas > 1`. |
| `operator.healthProbe.port` | int | `8081` | Liveness/readiness probe port. |
| `operator.metrics.enabled` | bool | `true` | Expose controller-manager metrics. |
| `operator.metrics.port` | int | `8443` | Metrics port. |
| `operator.metrics.secure` | bool | `true` | HTTPS + authn/authz filter on metrics. |
| `operator.metrics.enableHTTP2` | bool | `false` | Off by default (CVE guidance). |
| `operator.metrics.tls.*` | — | — | Mount a TLS cert (`certPath`, `certName`, `certKey`, `secretName`). Empty = self-signed. |
| `operator.serviceAccount.create` | bool | `true` | Create the operator ServiceAccount. |
| `operator.serviceAccount.name` | string | `""` | Override SA name. |
| `operator.serviceAccount.annotations` | object | `{}` | SA annotations. |
| `operator.rbac.create` | bool | `true` | Create the operator **ClusterRole + ClusterRoleBinding** (cluster-scoped). |
| `operator.serviceMonitor.enabled` | bool | `false` | `ServiceMonitor` for the operator's own metrics (`:8443`). |
| `operator.serviceMonitor.interval` / `.scrapeTimeout` | string | `30s` / `10s` | Scrape timing. |
| `operator.serviceMonitor.labels` / `.tlsConfig` | object | `{}` | Selector labels / TLS override. |
| `operator.networkPolicy.enabled` | bool | `false` | Restrict ingress to the operator pod. |
| `operator.networkPolicy.metricsNamespaceSelector` | object | `{matchLabels: {metrics: enabled}}` | Who may scrape metrics. |
| `operator.nodeSelector` / `.tolerations` / `.affinity` | — | `{}` / `[]` / `{}` | Operator pod scheduling. |
| `operator.podAnnotations` / `.podLabels` / `.priorityClassName` | — | `{}` / `{}` / `""` | Operator pod metadata. |

## `webhook` — pod-mutating webhook

| Key | Type | Default | Description |
| - | - | - | - |
| `webhook.enabled` | bool | `true` | Serve the **CacheBlend** pod-mutating webhook. **Requires cert-manager**: rendering fails fast without it. When `false`, the operator runs with `ENABLE_WEBHOOKS=false` and no cert-manager objects are created. |
| `webhook.port` | int | `9443` | Container port the webhook server listens on. |

The webhook patches opted-in vLLM **pods** at admission, and is a prerequisite for
`cacheBlend.enabled`.

<Note>
  The chart registers **both** pod injectors: CacheBlend (`lmcache.ai/cacheblend-inject`)
  and LMCache **connection** injection (`lmcache.ai/lmcache-inject`). Both take effect on a
  chart install. The release namespace is excluded from injection, and the engine is resolved
  in the opted-in pod's own namespace. See
  [Modify an Existing Deployment](/v1.0.0/installation/existing-deployment).
</Note>

## `engine` — the LMCacheEngine CR

| Key | Type | Default | Description |
| - | - | - | - |
| `engine.enabled` | bool | `true` | Create an `LMCacheEngine` CR in this release. |
| `engine.name` | string | `""` | CR name. Empty = `<fullname>-default-engine`. |
| `engine.namespace` | string | `""` | CR namespace. Empty = release namespace. |
| `engine.spec` | object | `{l1: {sizeGB: 60}, privileged: false}` | Rendered **verbatim** into the CR's `spec`. Required: `l1.sizeGB`. |
| `engine.spec.l1.sizeGB` | int | `60` | Per-node L1 cache size in GB. |
| `engine.spec.privileged` | bool | `false` | Run engine containers privileged. Set `true` when the node runtime cannot otherwise expose GPUs. Requires operator `v0.5.1`+. `gpuVendor: amd` forces it regardless. |
| `engine.p2p.enabled` | bool | `false` | Peer-to-peer KV transfer between engine pods (sets `--p2p-advertise-url`, which is what turns P2P on). |
| `engine.p2p.port` | int | `8500` | Port advertised to peers; the URL is `<pod IP>:<port>`. |
| `engine.p2p.l1AlignBytesOverwrite` | int | `65536` | L1 buffer alignment. Appended last, so it overrides the operator default (4 KiB). 64 KiB is recommended for P2P. |

`engine.spec` is a passthrough to the `LMCacheEngine` CRD, so its full surface is defined by
the CRD, not the chart. The fields below have **no chart default**: leave one out and the
operator's own default applies. Inspect the live schema with
`kubectl explain lmcacheengine.spec` once the CRD is installed.

| Field | Example | What it does |
| - | - | - |
| `image.{repository,tag,pullPolicy}` | `lmcache/vllm-openai`, `v<version>` | Engine container image. Pin the tag the [Compatibility Matrix](/v1.0.0/installation/compatibility) pairs with your chart. |
| `server.{port,chunkSize,maxWorkers}` | `5555`, `256`, `1` | Cache-server listener and KV chunk size in tokens. Prompts shorter than `chunkSize` store nothing. |
| `eviction.{triggerWatermark,evictionRatio}` | `0.8`, `0.2` | Start evicting at 80% full, drop 20% when triggered. |
| `prometheus.{enabled,port}` | `true`, `9090` | Engine-side metrics endpoint. |
| `l2Backend` | `{resp: {host: redis, port: 6379}}` | External L2 tier behind L1. |
| `l2Backend.serde.aesgcm` | see below | At-rest encryption for L2. See [KVCache Encryption](/v1.0.0/configuration/kvcache-encryption). Requires operator `v0.5.3`+. |
| `nodeSelector` | `{nvidia.com/gpu.present: "true"}` | Where engine pods run. This is the operator's default, and vLLM pods must land on the same nodes to reach the engine. |
| `serviceAccountName` | `lmcache-engine-sa` | Must already exist in the engine namespace. |
| `logLevel` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR`. |
| `extraArgs` | `["--foo", "bar"]` | Appended to the server command; skipped if the flag is already present. |

## `openshift` — privileged SCC for hostIPC

| Key | Type | Default | Description |
| - | - | - | - |
| `openshift.enabled` | bool | `false` | Bind a privileged SCC to engine pods (required on OpenShift). |
| `openshift.sccClusterRole` | string | `system:openshift:scc:privileged` | ClusterRole granting `use` on the SCC. |
| `openshift.serviceAccount.create` | bool | `true` | Create the privileged SA in the engine namespace. |
| `openshift.serviceAccount.name` | string | `""` | Override SA name. Empty = `<fullname>-engine-privileged`. |
| `openshift.serviceAccount.annotations` | object | `{}` | SA annotations. |

## `coordinator` — the LMCacheCoordinator CR

| Key | Type | Default | Description |
| - | - | - | - |
| `coordinator.enabled` | bool | `true` | Create an `LMCacheCoordinator` CR — one fleet-wide Deployment the engines register with. |
| `coordinator.spec` | object | `{}` | Rendered **verbatim** into the CR. Empty means every knob (image, port `9300`, replicas, timeouts, eviction) takes its server-side default. |

Override only to tune a specific knob: `replicas`, `port`, `instanceTimeout`,
`evictionRatio`, `triggerWatermark`, `logLevel`, `resourceOverrides`.

## `cacheBlend` — the CacheBlendEngine CR *(Preview)*

| Key | Type | Default | Description |
| - | - | - | - |
| `cacheBlend.enabled` | bool | `false` | Create a `CacheBlendEngine` CR. Requires `webhook.enabled=true` **and** cert-manager. |
| `cacheBlend.name` | string | `""` | CR name. Empty = `<fullname>-cacheblend`. |
| `cacheBlend.namespace` | string | `""` | CR namespace. Empty = release namespace. |
| `cacheBlend.spec` | object | `{l1: {sizeGB: 60}}` | Rendered **verbatim** into the CR. Required: `l1.sizeGB` (host DRAM, same as the engine's L1). |

`cacheBlend.spec` accepts the same passthrough fields as `engine.spec`, plus CacheBlend-only
ones: `blend.{checkLayer,recompRatio}` (how much KV is recomputed rather than reused),
`injection.{payloadImage,imagePullSecrets,cudagraph}` (what the webhook injects into opt-in
vLLM pods), and `server.chunkSize`, which is **fixed at 256** for CacheBlend — it must equal
vLLM's `--block-size 64` × 4.

`cacheBlend.spec.injection.payloadImage` is the **private** plugin init-container image and
is required for injection to happen at all. Set it together with a pull secret that exists
in the vLLM pod's namespace. See [CacheBlend](/v1.0.0/configuration/cacheblend) and
`examples/values-cacheblend.yaml`.

## `observability` — OTel Collector, metrics, traces

| Key | Type | Default | Description |
| - | - | - | - |
| `observability.enabled` | bool | `false` | Create an `OpenTelemetryCollector` CR and auto-wire the engine. Requires the OpenTelemetry Operator CRD. |
| `observability.otelCollector.resources` | object | `{}` | Collector pod resources. |
| `observability.otelCollector.debug` | bool | `false` | Debug exporter — logs every metric/trace to stdout. Dev only. |
| `observability.otelCollector.envFrom` | list | `[]` | `envFrom` entries (e.g. a `secretRef`) to mount auth tokens; reference with `${env:VAR}`. |
| `observability.prometheus.serviceMonitor.enabled` | bool | `true` | `ServiceMonitor` for the Collector's prometheus exporter (`:8889`). |
| `observability.prometheus.serviceMonitor.interval` | string | `30s` | Scrape interval. |
| `observability.prometheus.serviceMonitor.additionalLabels` | object | `{}` | Selector labels (e.g. `release: kube-prometheus-stack`). |
| `observability.prometheus.remoteWrite.enabled` | bool | `false` | Push metrics to a Prometheus remote-write endpoint (Grafana Cloud, Mimir, …). |
| `observability.prometheus.remoteWrite.endpoint` | string | `""` | Remote-write URL. |
| `observability.prometheus.remoteWrite.headers` | object | `{}` | Headers (use `${env:VAR}` for secrets). |
| `observability.prometheus.remoteWrite.externalLabels` | object | `{}` | Labels added to all remote-written metrics. |
| `observability.traces.externalEndpoint.enabled` | bool | `false` | Push traces to an external OTLP endpoint. |
| `observability.traces.externalEndpoint.endpoint` | string | `""` | OTLP gRPC endpoint (e.g. `tempo.monitoring:4317`). |
| `observability.traces.externalEndpoint.tls.insecure` | bool | `true` | Set `false` for TLS endpoints (e.g. Grafana Cloud :443). |
| `observability.traces.externalEndpoint.headers` | object | `{}` | Headers (use `${env:VAR}`). |
| `observability.traces.tempoCR.enabled` | bool | `false` | Create a `TempoMonolithic` CR. Requires the Tempo Operator. |

## `preDelete` and `tests`

| Key | Type | Default | Description |
| - | - | - | - |
| `preDelete.image` | string | `bitnami/kubectl:latest` | Image for the pre-delete hook Job (removes the CR before the operator). |
| `preDelete.timeoutSeconds` | int | `120` | Hook Job `activeDeadlineSeconds`. |
| `tests.enabled` | bool | `true` | Render `helm test` smoke pods. |
| `tests.image` | string | `bitnami/kubectl:latest` | kubectl-based test pod image. |
| `tests.curlImage` | string | `curlimages/curl:8.10.1` | curl-based test pod image. |
| `tests.integration.enabled` | bool | `false` | Run the engine serve/store/retrieve e2e. Needs a GPU node. |
| `tests.integration.vllmImage` | string | `lmcache/vllm-openai:latest-nightly` | Image the integration test serves with. |
| `tests.integration.model` | string | `Qwen/Qwen3-0.6B` | Model the integration test loads. Keep it small. |
| `tests.cacheblend.enabled` | bool | `false` | Run the CacheBlend reconcile + webhook-wiring test. |
| `tests.cacheblend.integration.enabled` | bool | `false` | Run the CacheBlend injection + serve e2e. Needs a GPU node. |
| `tests.cacheblend.integration.model` | string | `Qwen/Qwen3-0.6B` | Model the CacheBlend e2e loads. |
| `tests.cacheblend.integration.workloadNamespace` | string | `""` | Empty = `<fullname>-cb-itest`. **Must differ from the release namespace** — the webhook excludes its own. |

## Example overlays

The chart repo ships ready-to-use overlays under `examples/`:

| File | Shape |
| - | - |
| `values-minimal.yaml` | Operator + engine + coordinator, native filesystem L2. Smallest viable install. |
| `values-openshift.yaml` | Adds the privileged SCC binding for `hostIPC`. |
| `values-p2p.yaml` | Adds peer-to-peer KV transfer between engine pods (with `hostNetwork`). |
| `values-cacheblend.yaml` | `CacheBlendEngine` + webhook for non-prefix KV reuse. Requires cert-manager. |
| `values-l2-encrypted.yaml` | At-rest encryption of the L2 tier. See [KVCache Encryption](/v1.0.0/configuration/kvcache-encryption). |
| `values-pd.yaml` | Prefill/decode disaggregation: one engine DaemonSet serving both roles. |
| `values-observability-e2e.yaml` | Engine + full OTel stack (Collector + ServiceMonitor + debug). |

### Minimal (Kubernetes)

```yaml my-values.yaml theme={null}
engine:
  enabled: true
  spec:
    l1:
      sizeGB: 60
    image:
      repository: lmcache/vllm-openai
      tag: v<version>
      pullPolicy: IfNotPresent
```

### OpenShift

```yaml values-openshift.yaml theme={null}
openshift:
  enabled: true
engine:
  enabled: true
  spec:
    l1:
      sizeGB: 60
    image:
      repository: lmcache/vllm-openai
      tag: v<version>
      pullPolicy: IfNotPresent
```

### Observability (metrics + traces to a local Tempo)

```yaml values-observability.yaml theme={null}
openshift:
  enabled: true
engine:
  enabled: true
  spec:
    l1:
      sizeGB: 60
    image:
      repository: lmcache/vllm-openai
      tag: v<version>
      pullPolicy: IfNotPresent
observability:
  enabled: true
  otelCollector:
    debug: true
  prometheus:
    serviceMonitor:
      enabled: true
  traces:
    tempoCR:
      enabled: true
```

Apply any of these with:

```bash theme={null}
helm upgrade --install tensormesh-operator \
  oci://artifacts.tensormesh.ai/tensormesh-production/charts/tensormesh-operator \
  --version <version> -n tensormesh-operator --create-namespace \
  -f my-values.yaml --wait
```

## Next steps

<CardGroup cols={2}>
  <Card title="Architecture" icon="sitemap" href="/v1.0.0/reference/architecture">
    What each value deploys, and which resources are cluster-scoped.
  </Card>

  <Card title="Install with Helm" icon="ship-wheel" href="/v1.0.0/installation/helm">
    The install/upgrade/uninstall flow.
  </Card>
</CardGroup>
