> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo-platform/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo-platform/_mcp/server.

# NeMo Platform Helm Chart

![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)

For deployment guide, see [Self-Managed Deployment](/documentation/self-managed-deployment/setup) in the NeMo Platform documentation.

## Platform Secrets Encryption Key

The platform secrets service reads `NMP_SECRETS_DEFAULT_ENCRYPTION_KEY` from the
API env Secret. The value must be base64-encoded and decode to at least 32 bytes.

Set `secrets.defaultEncryptionKey.value` to provide your own key. When that value
is empty and neither `envFromSecret` nor
`secrets.defaultEncryptionKey.existingSecret.name` is set, the chart runs a
pre-install hook that creates `<fullname>-api-env` with a per-install random key.
The hook is install-only and refuses to patch or rotate an existing Secret.

Set `secrets.defaultEncryptionKey.existingSecret.name` to use an existing Secret
for only the secrets service encryption key. After Kubernetes decodes the Secret
data, the value loaded from `secrets.defaultEncryptionKey.existingSecret.key`
must be a base64-encoded key that decodes to at least 32 bytes.

Set `envFromSecret` to use a fully user-managed API env Secret. In that mode the
chart does not create or generate the API env Secret.

On upgrade, the generated Secret must already exist and contain
`NMP_SECRETS_DEFAULT_ENCRYPTION_KEY`. If it is missing, restore the original
Secret instead of generating a replacement key; existing encrypted platform
secrets will not decrypt with a new key.

## Intake and ClickHouse

Intake is included in the platform API service group. By default, the chart
deploys a single-node embedded ClickHouse 26.3 LTS service, and Intake creates
and migrates its own `intake` database on first use.

The embedded ClickHouse is intended for development, evaluation, and
non-critical single-node installations. It does not provide replication or
automatic backups. For a production deployment that requires high availability,
set `clickhouse.enabled` to `false` and provide a separately managed ClickHouse:

First, create the credentials Secret in the Helm release namespace. The Secret
key must match `externalClickhouse.existingSecretPasswordKey`:

```shell
kubectl create secret generic clickhouse-credentials \
  --namespace <release-namespace> \
  --from-literal=password='<clickhouse-password>'
```

Then configure the external connection:

```yaml
clickhouse:
  enabled: false

externalClickhouse:
  host: clickhouse.example.internal
  port: 8443
  secure: true
  user: nemo
  database: intake
  existingSecret: clickhouse-credentials
  existingSecretPasswordKey: password
```

The external user must be allowed to create the configured database, tables,
materialized views, and indexes because Intake owns its ClickHouse migrations.

### ClickHouse sizing

Use retained span count as an initial operational threshold, not as a disk-size
estimate. Span `input`, `output`, and attribute payloads vary substantially.
Measure `bytes_on_disk` from representative traffic before setting production
storage:

```sql
SELECT
    table,
    sum(rows) AS physical_rows,
    formatReadableSize(sum(bytes_on_disk)) AS disk
FROM system.parts
WHERE active AND database = 'intake'
GROUP BY table
ORDER BY table;
```

The following are starting points for the current Intake schema and interactive
query workload:

| Retained Intake spans                       | Topology                                                                     | ClickHouse resources                                                                  | Storage                                                                    |
| ------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Up to 1 million                             | Embedded single node for non-critical workloads                              | 2 vCPU, 8 GiB RAM                                                                     | Fast SSD, at least 20 GiB and 2× measured active data                      |
| 1–10 million                                | External preferred; embedded only when downtime and data loss are acceptable | 4–8 vCPU, 16–32 GiB RAM                                                               | Provisioned-IOPS SSD, at least 100 GiB and 2× measured active data         |
| More than 10 million, or any HA requirement | Managed ClickHouse or an operator-managed replicated cluster                 | Start at 8 vCPU and 32 GiB RAM per replica, then load-test the actual ingest/read mix | Size from measured compression, retention, replication, and merge headroom |

Intake currently retains spans and its trace index for 90 days. Evaluator
results and annotations do not have a time-based TTL, so include their continuing
growth in capacity planning. ReplacingMergeTree retries also leave physical row
versions until background merges complete.

For large or frequently queried deployments, ClickHouse recommends:

* At least 8 GiB RAM even at low data volumes.
* A general-purpose starting ratio of 4 GiB RAM per CPU core.
* Provisioned-IOPS SSDs for latency-sensitive workloads.
* Roughly 1:30 to 1:50 RAM-to-storage for frequently accessed large datasets.
* Replication for production durability; vertically scale replicas before
  adding shards.

Validate CPU, query peak memory, active parts, merge backlog, disk latency, and
free space under representative batched OTLP ingestion before promoting a tier.
See the upstream
[ClickHouse sizing guide](https://clickhouse.com/docs/guides/oss/best-practices/sizing-and-hardware-recommendations)
and
[OSS operational recommendations](https://clickhouse.com/docs/guides/oss/best-practices/tips).

## Kyverno

The chart does not install Kyverno. Multi-node NCCL device injection renders
ClusterPolicies that Kyverno must apply. Enable exactly one cloud provider
under `multinodeNetworking`.
How-to: [https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/multinode-networking](https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/multinode-networking)

## Volcano

The chart does not install Volcano. Multi-node `volcano_job` workloads need it.
`rbac.volcanoEnabled` defaults to true so the core controller can manage Volcano
CRs. Skip Volcano and set `rbac.volcanoEnabled: false` if you are not running
those jobs.
How-to: [https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/volcano](https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/volcano)

## OpenSandbox

The chart does not install OpenSandbox. Sandboxed GRPO / NeMo Gym talks to an
already installed server as an HTTP client (`OPEN_SANDBOX_DOMAIN`,
`OPEN_SANDBOX_API_KEY`). Gym sample YAML uses `OPENSANDBOX_*`; do not mix names.

`[kubernetes] namespace` in the server TOML **must be the Helm release
namespace**. Control plane may stay in `opensandbox-system`. Copy the API-key
Secret into the job namespace.

Example overlays: [examples/opensandbox](examples/opensandbox).
Shared-kernel (cluster default OCI runtime): [https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/opensandbox](https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/opensandbox)
Kata QEMU: [https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/opensandbox-kata](https://docs.nvidia.com/nemo-platform/latest/documentation/self-managed-deployment/setup/helm/opensandbox-kata)

## NetworkPolicies

The chart can render NetworkPolicy resources for the Platform API, core
controller, and managed job pods. A top-level switch enables all default
policies, and each subpolicy can be disabled independently for cluster-specific
exceptions.

## Values

The following is the complete `values.yaml` for the NeMo Platform Helm Chart.
All configuration options are documented inline with comments.

```yaml wordWrap
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Default values for NeMo Microservices Platform Helm chart

## Helm global configuration settings

# -- Overrides for name and fullname templates
nameOverride: ""
fullnameOverride: ""

# -- Your NVIDIA GPU Cloud (NGC) API key authenticates API calls to NGC services, such as model downloads. The existing secret overrides this key if you provide one to the `existingSecret` key.
ngcAPIKey: YOUR-NGC-API-KEY

# -- Environment variables that will be applied to every deployment pod. Uses a simple key value map structure like MY_ENV_VAR: the-key and works with valueFrom as well.
env: {}

# -- Optional. Name of an existing Kubernetes Secret to load as env vars (envFrom) for the API pod.
# When set, the chart does not create or generate the default api-env Secret; use your own Secret (for example, from Vault or sealed-secrets).
envFromSecret: ""

# -- Secrets service configuration.
secrets:
  defaultEncryptionKey:
    # -- Optional base64-encoded key for encrypting platform secrets. The decoded key must be at least 32 bytes. If empty and envFromSecret is not set, a pre-install hook generates a per-install key.
    value: ""
    # -- Existing Kubernetes Secret containing the key for encrypting platform secrets. If name is set, the chart does not create or generate the default api-env Secret.
    existingSecret:
      # -- Name of an existing Kubernetes Secret containing the encryption key.
      name: ""
      # -- Key in the existing Secret. After Kubernetes decodes the Secret data, the loaded value must be the base64-encoded NMP_SECRETS_DEFAULT_ENCRYPTION_KEY string.
      key: NMP_SECRETS_DEFAULT_ENCRYPTION_KEY
    # -- Generated key configuration used only when value and envFromSecret are empty. The generated key is not rotated or recreated on upgrade.
    generated:
      enabled: true
      image:
        # -- Image repository for the pre-install key generation hook.
        repository: docker.io/library/python
        # -- Image tag for the pre-install key generation hook.
        tag: "3.12-slim"
        # -- Image pull policy for the pre-install key generation hook.
        pullPolicy: IfNotPresent
      serviceAccount:
        # -- Specifies whether a service account should be created for the key generation hook.
        create: true
        # -- Annotations to add to the key generation hook service account.
        annotations: {}
        # -- The name of the service account to use. Required when create is false. If not set and create is true, a name is generated using the fullname template.
        name: ""
      # -- Number of retries before the key generation hook is marked failed.
      backoffLimit: 3
      # -- Maximum seconds for the key generation hook to run.
      activeDeadlineSeconds: 120
      # -- Seconds to keep the key generation hook Job after it finishes, if the hook is not deleted first.
      ttlSecondsAfterFinished: 300
      # -- Optional pod security context for the key generation hook.
      podSecurityContext: {}
      # -- Optional container security context for the key generation hook.
      securityContext: {}
      # -- Optional resource limits/requests for the key generation hook.
      resources: {}
      # -- Node selector for the key generation hook.
      nodeSelector: {}
      # -- Affinity for the key generation hook.
      affinity: {}
      # -- Tolerations for the key generation hook.
      tolerations: []

# -- You can use an existing Kubernetes secret for communicating with the NGC API for downloading models. The chart uses the `ngcAPIKey` value to generate the secret if you set this to an empty string.
existingSecret: ngc-api

# -- Existing Kubernetes image pull secrets to use for pulling container images from private registries or mirrors.
imagePullSecrets: []

# -- Whether OpenSandbox is installed on this cluster. The chart does not install OpenSandbox.
# Defaults to false so sandboxed GRPO fail-closes until you deploy OpenSandbox and set this true.
# See the OpenSandbox section in this README.
sandboxClusterCapable: false

# -- Connection settings for an already-installed OpenSandbox server.
# Used when sandboxClusterCapable is true. Copy the API-key Secret into the Helm
# release namespace (the namespace jobs run in). Override domain for a Kata Service.
opensandbox:
  # -- In-cluster OpenSandbox Service DNS with no scheme.
  domain: "opensandbox-server.opensandbox-system.svc.cluster.local"
  # -- Scheme jobs use to reach the server. In-cluster Services speak http.
  protocol: "http"
  # -- Kubernetes Secret in the job/release namespace holding the API key.
  apiKeySecret: "opensandbox-server-api-key"
  # -- Key inside apiKeySecret.
  apiKeySecretKey: "api-key"

# -- RBAC configuration settings for optional dependencies
rbac:
  # -- Specifies whether to enable the core Controller to have RBAC permissions to Volcano for scheduling distributed jobs.
  volcanoEnabled: true

# -- Multi-node networking configuration for distributed GPU training.
# These settings control Kyverno policies that inject cloud-specific networking and NCCL configurations.
#
# Requirements:
# - Kyverno policy engine must be installed in your cluster (required for multi-node networking)
# - Kyverno is NOT included as a subchart dependency and must be installed separately
#
# To install Kyverno:
#   helm install kyverno kyverno/kyverno --namespace kyverno --create-namespace --version 3.2.0
#
# Documentation: https://kyverno.io/docs/installation/
# Helm chart: https://kyverno.github.io/kyverno/
#
# Note: Only enable ONE cloud provider per cluster deployment.
multinodeNetworking:
  # -- AWS-specific configuration for EFA device injection
  aws:
    # -- Enable AWS-specific Kyverno policy for EFA device injection
    enabled: false
    # -- Number of EFA devices to request per GPU (typically 1 or 4)
    efaDevicesPerGPU: 1

  # -- Azure-specific configuration for InfiniBand/RDMA
  azure:
    # -- Enable Azure-specific Kyverno policy for InfiniBand/RDMA configuration
    enabled: false
    # -- Number of RDMA devices to request per GPU
    rdmaDevicesPerGPU: 1
    # -- RDMA device plugin resource name
    rdmaDeviceName: "hca_shared_devices_a"

  # -- GCP-specific configuration for TCP-X/TCP-XO
  gcp:
    # -- Enable GCP-specific Kyverno policy for TCP-X/TCP-XO configuration
    enabled: false

  # -- OCI-specific configuration for InfiniBand/SR-IOV
  oci:
    # -- Enable OCI-specific Kyverno policy for InfiniBand/SR-IOV configuration
    enabled: false
    # -- Number of RDMA devices (mlnxnics) to request per GPU
    rdmaDevicesPerGPU: 8

# -- NetworkPolicy configuration. Enable the top-level switch to render all default policies, then disable individual policies only for cluster-specific exceptions. For a Calico-backed smoke test, see https://docs.nvidia.com/nemo-platform/documentation/self-managed-deployment/setup/helm/network-policy-smoke-test.
# @default -- This object has the following default values. The top-level switch is disabled by default so chart upgrades do not change cluster connectivity unless explicitly enabled.
networkPolicies:
  # -- Create NetworkPolicy resources for enabled subpolicies.
  enabled: false
  # -- NetworkPolicy configuration for the Platform API pods.
  # @default -- This object has the following default values for API pod ingress isolation.
  api:
    # -- Create NetworkPolicy resources that isolate Platform API pod ingress.
    enabled: true
    # -- Optional NetworkPolicy port for the Platform API. Empty uses api.service.port.
    port: ""
    # -- Allow pods from the same Helm release namespace that carry the chart selector labels to reach the Platform API pods.
    sameReleasePods:
      # -- Enable ingress from same-release pods.
      enabled: true
    # -- Allow managed job pods to reach the Platform API pods.
    managedJobs:
      # -- Enable ingress from managed job pods.
      enabled: true
      # -- Pod selector for managed job pods. The default matches Kubernetes/Volcano pods created by the jobs controller.
      podSelector:
        matchLabels:
          app: nemo-job
          nmp.nvidia.com/managed_by: jobs-controller
    # -- Extra NetworkPolicy ingress rules appended to the API policy, for cluster-specific ingress controllers, gateways, monitoring, or debugging pods.
    extraIngress: []

  # -- NetworkPolicy configuration for the core controller pods.
  # @default -- This object has the following default values for core controller pod ingress isolation.
  controller:
    # -- Create NetworkPolicy resources that isolate core controller pod ingress.
    enabled: true
    # -- Optional NetworkPolicy port for the core controller. Empty uses core.controller.service.port.
    port: ""
    # -- Allow pods from the same Helm release namespace that carry the chart selector labels to reach the core controller pods.
    sameReleasePods:
      # -- Enable ingress from same-release pods.
      enabled: true
    # -- Extra NetworkPolicy ingress rules appended to the core controller policy, for cluster-specific monitoring or debugging pods.
    extraIngress: []

  # -- NetworkPolicy configuration for pods created by the jobs controller.
  # @default -- This object has the following default values for managed job pod egress isolation.
  jobs:
    # -- Create NetworkPolicy resources that isolate managed job pod egress.
    enabled: true
    # -- Pod selector for managed job pods. The default matches Kubernetes/Volcano pods created by the jobs controller.
    podSelector:
      matchLabels:
        app: nemo-job
        nmp.nvidia.com/managed_by: jobs-controller
    # -- Allow managed job pods to reach the in-namespace Platform API pods.
    platformApi:
      # -- Enable the default egress exception to the platform API pods. Disable only when managed job pods should not call the in-namespace API, or when API access is supplied through cluster-specific extraEgress rules.
      enabled: true
      # -- Optional NetworkPolicy port for the platform API. Empty uses api.service.port.
      port: ""
    # -- Allow DNS lookup from managed job pods.
    dns:
      # -- Enable egress to DNS pods.
      enabled: true
      # -- Namespace selector for DNS pods.
      namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      # -- Pod selector for DNS pods.
      podSelector:
        matchLabels:
          k8s-app: kube-dns
      # -- DNS ports to allow.
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
    # -- Allow egress to external CIDR blocks. The default excludes common private, loopback, and link-local ranges so enabling the policy does not allow direct access to typical in-cluster service and pod networks.
    externalEgress:
      # -- Enable egress to external CIDR blocks.
      enabled: true
      # -- External destination CIDR blocks for managed job pods.
      ipBlocks:
        - cidr: 0.0.0.0/0
          except:
            - 10.0.0.0/8
            - 100.64.0.0/10
            - 127.0.0.0/8
            - 169.254.0.0/16
            - 172.16.0.0/12
            - 192.168.0.0/16
      # -- Optional list of ports for external egress. Empty allows all ports to the configured ipBlocks.
      ports: []
    # -- Extra NetworkPolicy egress rules appended to the managed job policy, for cluster-specific dependencies or additional allowed CIDRs.
    extraEgress: []

# -- NCCL chart test (`helm test`): multi-node allreduce check. Templates use helm.sh/hook: test — they are not created on install/upgrade, only when you run helm test.
# Requires nodes labeled with gpuNodeLabelKey/gpuNodeLabelValue (default NFD / GPU operator style).
# See https://helm.sh/docs/topics/chart_tests/
ncclTest:
  # -- Node label used to discover GPU workers (must match your cluster).
  gpuNodeLabelKey: nvidia.com/gpu.present
  gpuNodeLabelValue: "true"
  # -- Resource name for GPU capacity on worker pods (e.g. nvidia.com/gpu or a MIG device).
  gpuResourceKey: nvidia.com/gpu
  # -- GPUs per worker pod / per node (torch.distributed nproc_per_node).
  # IMPORTANT: Set this value before testing
  gpusPerNode: 1
  # -- Max seconds to wait for each worker pod to complete.
  waitTimeoutSeconds: 900
  # -- How many times to run the full multinode NCCL test (orchestrator loop; env NCCL_TEST_ITERATIONS).
  # Increase the test timeout on helm test if increasing this variable
  iterations: 3
  validation:
    # -- Minimum allreduce bandwidth (MB/s) at 1024MB message size; 0 disables the floor check in nccl_test.py.
    minBandwidthMBpsAt1024MB: 8000
  orchestrator:
    image:
      repository: docker.io/library/python
      tag: "3.12-slim"
    resources:
      requests:
        cpu: 100m
        memory: 256Mi
      limits:
        cpu: "1"
        memory: 512Mi
  # -- Post-test hook Job (after orchestrator): deletes the scripts ConfigMap (helm.sh/hook-weight 5).
  configMapCleanupJob:
    image:
      repository: docker.io/library/python
      tag: "3.12-slim"
  worker:
    image:
      repository: nvcr.io/nvidia/nemo-platform/nmp-automodel-training
      tag: ""
    resources:
      requests:
        cpu: "4"
        memory: 8Gi
      limits:
        cpu: "8"
        memory: 16Gi

# -- Local PostgreSQL configuration for the NeMo Platform.
# @default -- This object has the following default values for the PostgreSQL configuration.
postgresql:
  # -- Whether to deploy the embedded PostgreSQL. If enabled, the chart deploys a single-replica PostgreSQL instance using the official Postgres image.
  # It is NOT recommended to use the built-in PostgreSQL for production deployments. It is enabled in the chart by default for ease of getting started with the platform.
  # If you are using an existing PostgreSQL installation, set this to false and use the "externalDatabase" configuration section.
  enabled: true
  image:
    repository: docker.io/library/postgres
    tag: "18"
    pullPolicy: IfNotPresent
  # -- PostgreSQL authentication configuration.
  auth:
    username: nemo
    password: nemo
    database: nemoplatform
    # -- Name of an existing secret containing a "password" key (or use existingSecretPasswordKey). If set, the chart does not create a secret.
    existingSecret: ""


  # -- PostgreSQL service configuration.
  service:
    port: 5432

  # -- PostgreSQL persistence configuration.
  persistence:
    enabled: true
    size: 5Gi
    # -- Storage class for the PostgreSQL PVC. If unset, the cluster default is used.
    storageClass: ""
  # -- Optional resource limits/requests for the PostgreSQL container.
  resources: {}
  # -- Optional pod security context for the PostgreSQL pod (e.g. for OpenShift SCC).
  podSecurityContext: {}
  # -- Optional container security context for the PostgreSQL container.
  securityContext: {}
  # -- Service account for the PostgreSQL pod.
  # @default -- This object has the following default values for the service account configuration.
  serviceAccount:
    # -- Specifies whether a service account should be created for the PostgreSQL pod.
    create: true
    # -- Automatically mount the ServiceAccount's API credentials.
    automount: true
    # -- Annotations to add to the service account.
    annotations: {}
    # -- The name of the service account to use. If not set and create is true, a name is generated from the release fullname.
    name: ""
  # -- Node selector for the PostgreSQL pod.
  nodeSelector: {}
  # -- Affinity for the PostgreSQL pod.
  affinity: {}
  # -- Tolerations for the PostgreSQL pod.
  tolerations: []

# -- External PostgreSQL configuration settings. These values are only used when postgresql.enabled is set to false.
# @default -- This object has the following default values for the external PostgreSQL configuration.
externalDatabase:
  # -- External database host address.
  host: localhost
  # -- External database port number.
  port: 5432
  # -- Database username
  user: nemo
  # -- Database name.
  database: nemoplatform
  # -- Name of an existing secret resource containing the database credentials.
  existingSecret: ""
  # -- Name of an existing secret key containing the database credentials.
  existingSecretPasswordKey: ""
  # -- URI secret configuration for external database.
  # @default -- This object has the following default values for the URI secret configuration.
  uriSecret:
    # -- Name of the URI secret.
    name: ""
    # -- Key in the URI secret containing the database URI.
    key: ""

# -- Embedded ClickHouse configuration for Intake.
# The embedded deployment is a single-node convenience topology. Use an external,
# replicated ClickHouse deployment for production environments that require high availability.
# These values are used only when `clickhouse.enabled` is true.
# @default -- This object has the following default values for the embedded ClickHouse configuration.
clickhouse:
  # -- Whether to deploy the embedded ClickHouse. Set to false to use `externalClickhouse`.
  enabled: true
  image:
    # -- ClickHouse image repository. Intake is tested against the 26.3 LTS release line.
    repository: docker.io/clickhouse/clickhouse-server
    # -- ClickHouse image tag.
    tag: "26.3"
    # -- ClickHouse image pull policy.
    pullPolicy: IfNotPresent
  auth:
    # -- ClickHouse username used by Intake.
    username: nemo
    # -- ClickHouse password used when auth.existingSecret is empty. If unset, the chart generates a random password.
    password: null
    # -- ClickHouse database used by Intake.
    database: intake
    # -- Name of an existing Secret containing the ClickHouse password. If empty, the chart creates one.
    existingSecret: ""
    # -- Key in auth.existingSecret containing the ClickHouse password.
    existingSecretPasswordKey: password
  service:
    # -- ClickHouse HTTP interface port used by Intake.
    httpPort: 8123
    # -- ClickHouse native protocol port exposed inside the cluster for administration.
    nativePort: 9000
    # -- Annotations to add to the ClickHouse Service.
    annotations: {}
  persistence:
    # -- Whether to persist embedded ClickHouse data.
    enabled: true
    # -- PersistentVolumeClaim size. See the Intake and ClickHouse sizing guidance in the chart README.
    size: 20Gi
    # -- Storage class for the ClickHouse PVC. If unset, the cluster default is used.
    storageClass: ""
  # -- Resource requests and limits for the ClickHouse container. The defaults are the supported small-volume starting point.
  resources:
    requests:
      cpu: "2"
      memory: 8Gi
  # -- Startup probe configuration for the ClickHouse container.
  # @default -- This object has the following default values for the startup probe configuration.
  startupProbe:
    httpGet:
      path: /ping
      port: http
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 60
  # -- Liveness probe configuration for the ClickHouse container.
  # @default -- This object has the following default values for the liveness probe configuration.
  livenessProbe:
    httpGet:
      path: /ping
      port: http
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3
  # -- Readiness probe configuration for the ClickHouse container.
  # @default -- This object has the following default values for the readiness probe configuration.
  readinessProbe:
    httpGet:
      path: /ping
      port: http
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 3
  # -- Optional pod security context for the ClickHouse pod.
  podSecurityContext: {}
  # -- Optional container security context for the ClickHouse container.
  securityContext: {}
  # -- Service account for the ClickHouse pod.
  # @default -- This object has the following default values for the service account configuration.
  serviceAccount:
    # -- Specifies whether a service account should be created for the ClickHouse pod.
    create: true
    # -- Automatically mount the ServiceAccount's API credentials.
    automount: false
    # -- Annotations to add to the service account.
    annotations: {}
    # -- The name of the service account to use. If not set and create is true, a name is generated from the release fullname.
    name: ""
  # -- Annotations to add to the ClickHouse StatefulSet.
  annotations: {}
  # -- Annotations to add to the ClickHouse pod.
  podAnnotations: {}
  # -- Additional labels to add to the ClickHouse pod.
  podLabels: {}
  # -- Node selector for the ClickHouse pod.
  nodeSelector: {}
  # -- Affinity for the ClickHouse pod.
  affinity: {}
  # -- Tolerations for the ClickHouse pod.
  tolerations: []

# -- External ClickHouse configuration. These values are used when `clickhouse.enabled` is false.
# @default -- This object has the following default values for the external ClickHouse configuration.
externalClickhouse:
  # -- External ClickHouse host. Required when the embedded ClickHouse is disabled.
  host: ""
  # -- External ClickHouse HTTP interface port.
  port: 8123
  # -- Whether Intake should connect to ClickHouse over HTTPS.
  secure: false
  # -- ClickHouse username used by Intake.
  user: nemo
  # -- ClickHouse database used by Intake.
  database: intake
  # -- Name of an existing Secret containing the ClickHouse password. Required when using external ClickHouse.
  existingSecret: ""
  # -- Key in existingSecret containing the ClickHouse password. Required when using external ClickHouse.
  existingSecretPasswordKey: ""

# -- Platform-wide configuration settings
# Set configuration here to apply custom, structured configuration across all services.
# Applied after the base platform config is evaluated for templates. Enables adding / overriding YAML-based elements in the evaluated platform config.
# It is usually recommended to use this config section instead of `basePlatformConfig` unless you need to use templating features.
# For example, you can set the NIM default StorageClass via models.controller.backends.deployments_plugin.default_storage_class.
# For full configuration reference, see https://docs.nvidia.com/nemo-platform
platformConfig:
  studio:
    feature_flags:
      assistant_studio_enabled: true

# -- Base platform configuration settings
# @default -- This object has the following default values for the base platform configuration.
basePlatformConfig: |
  # -- platform is the service discovery configuration for services across the platform
  platform:
    # -- runtime specifies the type of runtime the platform is running on.
    # Always set to 'kubernetes' for NeMo Platform when deploying with Helm.
    runtime: kubernetes

    # Base URLs for various platform services
    base_url: "{{ printf "http://%s:%s" (include "nmp-api.api-servicename" . ) (toString .Values.api.service.port) }}"

    # Image configuration for launching containers via the platform
    image_registry: nvcr.io/nvidia/nemo-platform
    image_tag: {{ .Chart.AppVersion | quote }}
    image_pull_secrets: {{ default (list) .Values.imagePullSecrets | toJson }}
    sandbox_cluster_capable: {{ .Values.sandboxClusterCapable }}
    sandbox_server_domain: {{ .Values.opensandbox.domain | quote }}
    sandbox_server_protocol: {{ .Values.opensandbox.protocol | quote }}
    sandbox_api_key_secret: {{ .Values.opensandbox.apiKeySecret | quote }}
    sandbox_api_key_secret_key: {{ .Values.opensandbox.apiKeySecretKey | quote }}

  studio:
    # -- platform_base_url is the base URL used to access the platform.
    # This is the URL that NeMo Studio will use in the browser to communicate with the platform backend services.
    # An empty string means the Studio UI will reference its own host for API calls.
    platform_base_url: ""
    # -- static_files_path points at the Studio UI bundle baked into the container image
    # (see docker/Dockerfile.nmp-api). The Python default resolves to the wheel's packaged
    # assets, which the container image doesn't populate, so we override here.
    static_files_path: "/static/studio"

  auth:
    enabled: false
    policy_decision_point_provider: embedded
    policy_decision_point_base_url: "{{ printf "http://%s:%s" (include "nmp-api.api-servicename" . ) (toString .Values.api.service.port) }}"
    policy_data_refresh_interval: 5
    bundle_cache_seconds: 5
    admin_email: "admin@example.com"

  # -- service is the common configuration for service settings on the platform
  service:
    host: "0.0.0.0"
    port: {{ toString .Values.api.service.port }}
    log_format: json

  # -- entities is the configuration specific to entity management on the platform
  entities:
    backend: sqlalchemy

  # -- jobs is the configuration specific to executing jobs on the platform
  jobs:
    # -- executor_defaults is the default configuration applied to all executor profiles
    executor_defaults:
      kubernetes_job:
        service_account_name: {{ include "nmp-core.jobsServiceAccountName" . | quote }}
        launcher_image: {{ include "nmp-core.image" . | quote }}
        storage:
          pvc_name: {{ (include "nmp-core.persistentVolumeClaim" . ) }}
          volume_permissions_image: {{ .Values.core.storage.volumePermissionsImage | quote }}
        pod_security_context: {{ .Values.podSecurityContext | toYaml | nindent 10 }}
      volcano_job:
        service_account_name: {{ include "nmp-core.jobsServiceAccountName" . | quote }}
        launcher_image: {{ include "nmp-core.image" . | quote }}
        storage:
          pvc_name: {{ (include "nmp-core.persistentVolumeClaim" . ) }}
          volume_permissions_image: {{ .Values.core.storage.volumePermissionsImage | quote }}
        pod_security_context: {{ .Values.podSecurityContext | toYaml | nindent 10 }}
        {{- if include "nemo-platform.multinodeNetworkingEnabled" . }}
        # Enable multi-node networking (triggers Kyverno policies for cloud-specific configuration)
        enable_multi_node_networking: true
        {{- end }}

  # -- secrets is the configuration specific to storing secrets on the platform
  secrets:
    encryption:
      current_provider: local_v1
      providers:
        secret_key:
          local_v1:
            from_env: "NMP_SECRETS_DEFAULT_ENCRYPTION_KEY"

  # -- models is the configuration specific to model management on the platform
  models:
    controller:
      backends:
        deployments_plugin:
          enabled: true
          k8s_executor: local-k8s
          default_executor: local-k8s
          # Bypass the image `nemo` ENTRYPOINT; invoke the adapters module directly.
          # Avoids PermissionError when the sidecar writes instance state under $HOME.
          lora_sidecar_command:
            - python
            - -m
            - nmp.core.models.sidecars.adapters.main

  deployments:
    executors:
      - name: local-k8s
        backend: k8s
        config:
          default_namespace: {{ .Release.Namespace | quote }}
    default_executor: local-k8s

  # -- inference_gateway is the configuration specific to inference request routing
  inference_gateway: {}

  # -- files is the configuration specific to file management on the platform
  files:
    default_storage_config:
      type: local
      path: /vol/files

  # -- auditor is the configuration specific to the Auditor service
  auditor: {}

  # -- data_designer is the configuration specific to the Data Designer service
  data_designer:
    model_provider_registry:
      default: "mock"
      providers:
        - name: "mock"
          endpoint: "http://localhost:8000"

  # -- customizer is the configuration specific to the Customizer service
  customizer: {}

  # -- automodel is the configuration specific to Automodel customization jobs
  automodel:
    default_training_execution_profile: default

  # -- unsloth is the configuration specific to Unsloth customization jobs
  unsloth:
    default_training_execution_profile: default

  # -- rl is the configuration specific to NeMo-RL customization jobs (DPO / GRPO)
  rl:
    # -- job_storage_pvc_claim is the claim sandboxed GRPO re-mounts into the Gym host so
    # the sandbox can read the downloaded environment and dataset. Must match the claim the
    # Jobs controller mounts for job storage.
    job_storage_pvc_claim: {{ (include "nmp-core.persistentVolumeClaim" . ) }}

  # -- safe_synthesizer is the configuration specific to the Safe Synthesizer service
  safe_synthesizer:
    container_image: safe-synthesizer-tasks

  # -- evaluator is the configuration specific to the Evaluator service
  evaluator: {}

  # -- guardrails is the configuration specific to the Guardrails service
  guardrails: {}


ingress:
  # -- Specifies whether to enable the ingress.
  enabled: false
  # -- Annotations for the ingress resource.
  annotations: {}
  # -- The ingress class to use if your cluster has more than one class.
  className: ""
  # -- Optional default hostname. When set, one rule is generated with this host and paths from the first entry in ingress.hosts.
  defaultHost: ""
  # -- TLS configurations.
  tls: []
  hosts:
      # -- Hostname used by ingress. If blank, use path-only routing.
    - name: ""
      paths:
        - path: /
          pathType: Exact
          service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'
        - path: /apis
          pathType: Prefix
          service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'
        - path: /studio
          pathType: Prefix
          service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'
        - path: /cluster-info
          pathType: Exact
          service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'
        - path: /status
          pathType: Exact
          service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'

httpRoute:
  # -- Specifies whether to enable a Gateway API HTTP Route for the service.
  enabled: false
  # -- Extra labels for the HTTP Route object.
  labels: {}
  # -- Extra annotations for the HTTP Route object.
  annotations: {}
  # -- A list of Gateways to enable this route on. This is required if httpRoute.enabled is true.
  parentRefs: []
  # -- If this has a specific hostname, add the name or names here in an array.
  hostnames: []
  # -- Path matches to route queries.
  pathRules:
    - matches:
        - path: /
          type: Exact
        - path: /apis
          type: PathPrefix
        - path: /studio
          type: PathPrefix
        - path: /cluster-info
          type: Exact
        - path: /status
          type: Exact
      backends:
        - service: '{{ include "nemo-platform.ingressBackendService" . }}'
          port: '{{ include "nemo-platform.ingressBackendPort" . }}'
  # -- This is a list of filters for the objects, such as CORS settings.
  filters: []

# -- OpenShift Route (route.openshift.io/v1). Use on OpenShift to expose the API via a Route instead of Ingress.
openshiftRoute:
  # -- Specifies whether to create an OpenShift Route for the API service.
  enabled: false
  # -- Hostname for the route. If empty, the OpenShift router may assign a default hostname.
  host: ""
  # -- Service name to route to. Defaults to Envoy when auth+envoy enabled, otherwise API (tpl-evaluated).
  service: '{{ include "nemo-platform.ingressBackendService" . }}'
  # -- Target port on the service. Defaults to Envoy or API port depending on auth (tpl-evaluated).
  targetPort: '{{ include "nemo-platform.ingressBackendPort" . }}'
  # -- Optional TLS configuration (termination, certificate, key, etc.). See OpenShift Route spec.
  tls: {}
  # -- Annotations for the route resource.
  annotations: {}
  # -- Labels for the route resource.
  labels: {}

# # -- OpenTelemetry configuration settings for all services.
# @default -- This object has the following default values for the OpenTelemetry configuration.
telemetry:
  # -- Disable OpenTelemetry instrumentation and exporting for all services.
  OTEL_SDK_DISABLED: false
  # -- The OpenTelemetry grpc collector endpoint to export traces and metrics to.
  OTEL_EXPORTER_OTLP_ENDPOINT: ""
  # -- Whether to use an insecure connection (no TLS) to the OpenTelemetry collector endpoint.
  OTEL_EXPORTER_OTLP_INSECURE: true
  # -- The OpenTelemetry traces exporter to use. Options are "otlp" or "none" to disable export.
  OTEL_TRACES_EXPORTER: "none"
  # -- The OpenTelemetry metrics exporter to use. Options are "otlp", "prometheus" or "none" to disable export.
  OTEL_METRICS_EXPORTER: "none"
  # -- The OpenTelemetry traces exporter endpoint to use. Defaults to `OTEL_EXPORTER_OTLP_ENDPOINT` if not set.
  OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: null
  # -- Whether to use an insecure connection (HTTP) to the OpenTelemetry traces exporter endpoint. Defaults to `OTEL_EXPORTER_OTLP_INSECURE` if not set.
  OTEL_EXPORTER_OTLP_TRACES_INSECURE: true
  # -- The OpenTelemetry metrics exporter endpoint to use. Defaults to `OTEL_EXPORTER_OTLP_ENDPOINT` if not set.
  OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: null
  # -- Whether to use an insecure connection (HTTP) to the OpenTelemetry metrics exporter endpoint. Defaults to `OTEL_EXPORTER_OTLP_INSECURE` if not set.
  OTEL_EXPORTER_OTLP_METRICS_INSECURE: true

# -- Pod security context settings applied to all services by default.
# These can be overridden in individual service configurations.
# @default -- This object has the following default values for the pod security context.
podSecurityContext: {}

# -- Container security context settings applied to all services by default.
# These can be overridden in individual service configurations.
# @default -- This object has the following default values for the container security context.
securityContext: {}

# -- API configuration settings for the api deployment
# @default -- This object has the following default values for the API configuration.
api:
  # -- Specifies whether to enable the api deployment.
  enabled: true

  # -- Container image configuration for the api deployment.
  # @default -- This object has the following default values for the image configuration.
  image:
    # -- The registry where the NeMo Platform image is located.
    repository: nvcr.io/nvidia/nemo-platform/nmp-api
    # -- The image pull policy determining when to pull new images.
    pullPolicy: IfNotPresent
    # -- The image tag to use.
    tag: ""

  # -- OpenTelemetry configuration overrides for the api deployment.
  telemetry: {}

  # -- Number of replicas for the API service.
  replicaCount: 1
  # -- Platform API server settings.
  server:
    # -- Seconds Uvicorn keeps idle HTTP connections open. Must be greater than envoyProxy.timeouts.upstreamIdle when Envoy is enabled.
    keepAliveTimeoutSeconds: 5

  # -- Predefined service group passed to `nemo services run` with `--service-group`. Ignored when api.services is non-empty.
  serviceGroup: all
  # -- Explicit services passed to `nemo services run` with `--services`. When non-empty, overrides api.serviceGroup. Must be a list.
  services: []
  # -- Additional arguments to pass to the Platform API service
  extraArgs: []
  # -- Additional volume mounts to add to the Platform API container.
  extraVolumeMounts: []
  # -- Additional volumes to add to the Platform API pod.
  extraVolumes: []
  # -- Service account configuration for the API service.
  # @default -- This object has the following default values for the service account configuration.
  serviceAccount:
    # -- Specifies whether a service account should be created.
    create: true
    # -- Automatically mount a ServiceAccount's API credentials.
    automount: true
    # -- Annotations to add to the service account.
    annotations: {}
    # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template.
    name: ""
  # -- Annotations to add to the API service deployment.
  annotations: {}
  # -- Annotations to add to the API service pod.
  podAnnotations: {}
  # -- Labels for the API service pod.
  podLabels: {}
  # -- Pod-level security context settings for the API service.
  # @default -- This object has the following default values for the pod security context.
  podSecurityContext:
    # -- The file system group ID to use for all containers.
    fsGroup: 1000
  # -- Container-level security context settings for the API service.
  securityContext: {}
  # -- Service configuration for the API service.
  # @default -- This object has the following default values for the service configuration.
  service:
    # -- The Kubernetes service type to create.
    type: ClusterIP
    # -- The port number to expose for the service.
    port: 8080
    # -- Annotations for the API service.
    annotations: {}
  # -- Kubernetes deployment resources configuration for the API service. Utilization-based autoscaling requires a matching resource request.
  resources: {}

  # -- Startup probe configuration for the api service.
  # @default -- This object has the following default values for the startup probe configuration.
  startupProbe:
    # -- Number of seconds to wait before the first startup probe. Allows time for DB connection retries (e.g. Postgres pod booting).
    initialDelaySeconds: 10
    # -- The HTTP GET request to use for the startup probe.
    httpGet:
      path: /health/ready
      port: http
    # -- The frequency in seconds to perform the startup probe.
    periodSeconds: 15
    # -- The timeout in seconds for the startup probe.
    timeoutSeconds: 5
    # -- The failure threshold for the startup probe.
    failureThreshold: 24

  # -- Liveness probe configuration for the api service.
  # @default -- This object has the following default values for the liveness probe configuration.
  livenessProbe:
    # -- The HTTP GET request to use for the liveness probe.
    httpGet:
      path: /health/live
      port: http
    # -- The frequency in seconds to perform the liveness probe.
    periodSeconds: 10
    # -- The timeout in seconds for the liveness probe.
    timeoutSeconds: 5
    # -- The failure threshold for the liveness probe.
    failureThreshold: 3

  # -- Readiness probe configuration for the api service.
  # @default -- This object has the following default values for the readiness probe configuration.
  readinessProbe:
    # -- The HTTP GET request to use for the readiness probe.
    httpGet:
      path: /health/ready
      port: http
    # -- The frequency in seconds to perform the readiness probe.
    periodSeconds: 10
    # -- The timeout in seconds for the readiness probe.
    timeoutSeconds: 5
    # -- The failure threshold for the readiness probe.
    failureThreshold: 3

  # -- PodDisruptionBudget configuration for the API service.
  # @default -- This object has the following default values for the pod disruption budget configuration.
  podDisruptionBudget:
    # -- Whether to create a PodDisruptionBudget for the API pods.
    enabled: false
    # -- Minimum number of API pods that must remain available during voluntary disruptions.
    # Only one of minAvailable or maxUnavailable may be set.
    minAvailable: 1
    # -- Maximum number of API pods that can be unavailable during voluntary disruptions.
    # Only one of minAvailable or maxUnavailable may be set.
    # maxUnavailable: 0
    # -- Annotations for the PodDisruptionBudget.
    annotations: {}

  # -- Specifies autoscaling configurations for the deployment.
  autoscaling:
    # -- Whether to enable horizontal pod autoscaler.
    enabled: false
    # -- The minimum number of replicas for the deployment.
    minReplicas: 1
    # -- The maximum number of replicas for the deployment.
    maxReplicas: 10
    # -- The target CPU utilization percentage. Requires api.resources.requests.cpu.
    targetCPUUtilizationPercentage: 80
    # -- The target memory utilization percentage. Requires api.resources.requests.memory.
    targetMemoryUtilizationPercentage: null
    # -- Annotations for the HorizontalPodAutoscaler.
    annotations: {}

  # Environment variables to pass to containers. This is an object formatted like NAME: value or NAME: valueFrom: {object}
  env: {}
  # -- Node selector configuration for the API service.
  nodeSelector: {}
  # -- Affinity configuration for the API service.
  affinity: {}
  # -- Tolerations configuration for the API service.
  tolerations: []
  # -- Topology spread constraints for the API service pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
  topologySpreadConstraints: []

  # ServiceMonitor configuration for Prometheus Operator
  serviceMonitor:
    # -- Enable ServiceMonitor resources for Prometheus Operator
    enabled: false
    # -- Scrape interval for the ServiceMonitor
    interval: "30s"
    # -- Scheme to use for scraping metrics (http or https)
    scheme: "http"
    # -- Additional labels to add to the ServiceMonitor
    labels: {}
    # -- Additional annotations to add to the ServiceMonitor
    annotations: {}

# -- Platform seed Job (Helm hook: runs after install/upgrade)
# Runs the platform-seed task (guardrails configs, evaluator system entities, data designer filesets).
# Uses post-install,post-upgrade hooks so it runs on fresh installs and can be re-triggered on no-op upgrade.
# @default -- This object has the following default values for the platform seed Job configuration.
platformSeedJob:
  # -- Specifies whether to enable the platform-seed Job.
  enabled: true
  # -- Seconds after the Job finishes (success or failure) before it is eligible for automatic deletion.
  ttlSecondsAfterFinished: 86400
  # -- Number of retries before considering the Job failed.
  backoffLimit: 6
  # -- Maximum time in seconds the Job can run.
  activeDeadlineSeconds: 600
  # -- Pod-level security context for the platform seeding Job pod.
  podSecurityContext: {}
  # -- Container-level security context for the platform-seed container.
  securityContext: {}
  # -- Resource requests/limits for the platform-seed container.
  resources: {}
  # -- Extra environment variables for the platform-seed container (e.g. CONFIG_STORE_PATH, NMP_PLATFORM_SEED_*).
  extraEnv: []
  # -- Node selector for the platform seeding Job pod.
  nodeSelector: {}
  # -- Affinity for the platform seeding Job pod.
  affinity: {}
  # -- Tolerations for the platform seeding Job pod.
  tolerations: []
  # -- Additional labels for the platform seeding Job pod.
  podLabels: {}

# -- Core deployment configuration settings
# @default -- This object has the following default values for the core deployment configuration.
core:
  # -- Specifies whether to enable the core deployment.
  enabled: true

  # -- Container image configuration for the core deployment.
  # @default -- This object has the following default values for the image configuration.
  image:
    # -- The registry where the NeMo Platform image is located.
    repository: nvcr.io/nvidia/nemo-platform/nmp-api
    # -- The image pull policy determining when to pull new images.
    pullPolicy: IfNotPresent
    # -- The image tag to use.
    tag: ""

  storage:
    # -- If set, pods will mount this persistent volume for job-scoped storage
    # and we will not create a new persistent volume claim.
    existingPersistentVolumeName: ""
    # -- Which storageClass to use when creating a new persistent volume claim. Empty string uses the cluster's default StorageClass.
    storageClass: ""
    # -- accessModes for the persistent volume claim. This should include `ReadWriteMany` to ensure
    # multiple job pods can write to the volume concurrently.
    accessModes:
      - ReadWriteMany
    # -- size of the persistent volume claim used for persistent storage
    size: 200Gi
    # -- volumePermissionsImage is the image used to set permissions on the volume
    volumePermissionsImage: "docker.io/library/busybox:stable"
    # -- Annotations to add to the persistent volume claim
    annotations: {}

  # -- OpenTelemetry configuration overrides for the platform deployment.
  telemetry: {}

  # -- Service account configuration for pods created by the jobs controller (Kubernetes/Volcano job pods).
  # @default -- This object has the following default values for the jobs service account configuration.
  jobs:
    serviceAccount:
      # -- Specifies whether a service account should be created for job pods.
      create: true
      # -- Automatically mount a ServiceAccount's API credentials.
      automount: true
      # -- Annotations to add to the service account.
      annotations: {}
      # -- The name of the service account to use. If not set and create is true, a name is generated with a '-jobs' suffix.
      name: ""

  # @default -- This object has the following default values for the controller configuration.
  controller:
    # -- Service account configuration for the controller service.
    # @default -- This object has the following default values for the service account configuration.
    serviceAccount:
      # -- Specifies whether a service account should be created.
      create: true
      # -- Automatically mount a ServiceAccount's API credentials.
      automount: true
      # -- Annotations to add to the service account.
      annotations: {}
      # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template.
      name: ""

    # -- Predefined controller group passed to `nemo services run` with `--controller-group`. Ignored when core.controller.controllers is non-empty.
    controllerGroup: all
    # -- Explicit controllers passed to `nemo services run` with `--controllers`. When non-empty, overrides core.controller.controllerGroup. Must be a list.
    controllers: []
    # -- Additional arguments to pass to the Core Controller service
    extraArgs: []

    # -- Service configuration for the controller service. This only configures a headless service for DNS resolution.
    # @default -- This object has the following default values for the service configuration.
    service:
      # -- The port for the service.
      port: 8080
      # -- Annotations for the headless controller service.
      annotations: {}
    # -- Annotations to add to the controller service deployment.
    annotations: {}
    # -- Annotations to add to the controller service pod.
    podAnnotations: {}
    # -- Labels for the controller service pod.
    podLabels: {}
    # -- Pod-level security context settings for the controller service.
    # @default -- This object has the following default values for the pod security context.
    podSecurityContext:
      # -- The file system group ID to use for all containers.
      fsGroup: 1000
    # -- Container-level security context settings for the controller service.
    securityContext: {}
    # -- Kubernetes deployment resources configuration for the controller service.
    resources: {}

    # -- Startup probe configuration for the core service.
    # @default -- This object has the following default values for the startup probe configuration.
    startupProbe:
      # -- Number of seconds to wait before the first startup probe. Allows time for DB connection retries (e.g. Postgres pod booting).
      initialDelaySeconds: 10
      # -- The HTTP GET request to use for the startup probe.
      httpGet:
        path: /health/ready
        port: http
      # -- The frequency in seconds to perform the startup probe.
      periodSeconds: 15
      # -- The timeout in seconds for the startup probe.
      timeoutSeconds: 5
      # -- The failure threshold for the startup probe.
      failureThreshold: 24

    # -- Liveness probe configuration for the controller service.
    # @default -- This object has the following default values for the liveness probe configuration.
    livenessProbe:
      # -- The HTTP GET request to use for the liveness probe.
      httpGet:
        path: /health/live
        port: http
      # -- The frequency in seconds to perform the liveness probe.
      periodSeconds: 10
      # -- The timeout in seconds for the liveness probe.
      timeoutSeconds: 5
      # -- The failure threshold for the liveness probe.
      failureThreshold: 3

    # -- Readiness probe configuration for the controller service.
    # @default -- This object has the following default values for the readiness probe configuration.
    readinessProbe:
      # -- The HTTP GET request to use for the readiness probe.
      httpGet:
        path: /health/ready
        port: http
      # -- The frequency in seconds to perform the readiness probe.
      periodSeconds: 10
      # -- The timeout in seconds for the readiness probe.
      timeoutSeconds: 5
      # -- The failure threshold for the readiness probe.
      failureThreshold: 3
    # -- Additional environment variables to pass to containers. This is an object formatted like NAME: value or NAME: valueFrom: {object}.
    env: {}
    # -- Node selector configuration for the controller service.
    nodeSelector: {}
    # -- Affinity configuration for the controller service.
    affinity: {}
    # -- Tolerations configuration for the controller service.
    tolerations: []
    # -- Topology spread constraints for the controller service pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
    topologySpreadConstraints: []

  # ServiceMonitor configuration for Prometheus Operator
  serviceMonitor:
    # -- Enable ServiceMonitor resources for Prometheus Operator
    enabled: false
    # -- Scrape interval for the ServiceMonitor
    interval: "30s"
    # -- Scheme to use for scraping metrics (http or https)
    scheme: "http"
    # -- Additional labels to add to the ServiceMonitor
    labels: {}
    # -- Additional annotations to add to the ServiceMonitor
    annotations: {}


# -- Envoy proxy configuration settings. Resources are created only when platform config has auth.enabled: true (see platformConfig.auth.enabled).
# @default -- This object has the following default values for the envoy proxy configuration.
envoyProxy:
  # -- Specifies whether to enable the Envoy proxy deployment. Rendered only when platform config has auth.enabled: true.
  enabled: true

  # Headers considered internal-only
  trustedHeaders:
    - x-nmp-principal-id
    - x-nmp-principal-email
    - x-nmp-principal-groups
    - x-nmp-principal-on-behalf-of
    - x-nmp-principal-on-behalf-of-groups
    - x-nmp-principal-on-behalf-of-email
    - x-nmp-principal-filters
    - x-nmp-principal-roles
    - x-nmp-internal

  # Number of Envoy proxy replicas
  replicaCount: 2

  # Envoy image
  image:
    repository: docker.io/envoyproxy/envoy
    tag: v1.37.0
    # -- Optional image digest. When set, the Envoy image renders as repository@digest.
    digest: ""
    pullPolicy: IfNotPresent

  # -- Service account configuration for the Envoy service.
  # @default -- This object has the following default values for the service account configuration.
  serviceAccount:
    # -- Specifies whether a service account should be created.
    create: true
    # -- Automatically mount a ServiceAccount's API credentials.
    automount: true
    # -- Annotations to add to the service account.
    annotations: {}
    # -- The name of the service account to use. If not set and create is true, a name is generated using the fullname template.
    name: ""
  # -- Annotations to add to the Envoy service deployment.
  annotations: {}
  # -- Annotations to add to the Envoy service pod.
  podAnnotations: {}
  # -- Labels for the Envoy service pod.
  podLabels: {}
  # -- Pod-level security context settings for the Envoy service.
  # @default -- This object has the following default values for the pod security context.
  podSecurityContext:
    # -- The file system group ID to use for all containers.
    fsGroup: 1000
  # -- Container-level security context settings for the Envoy service.
  securityContext: {}
  # -- Service configuration for the Envoy service.
  # @default -- This object has the following default values for the service configuration.
  service:
    # -- The Kubernetes service type to create.
    type: ClusterIP
    # -- The port number to expose for the service.
    port: 8080
    # -- Expose the Envoy admin port through the Kubernetes Service. Enable only for controlled in-cluster scraping or debugging.
    exposeAdminPort: false
    # -- Annotations for the Envoy service.
    annotations: {}

  # -- Envoy Admin port
  adminPort: 9901

  # -- Timeouts for proxying to long-lived streams (e.g. inference gateway). Use "0s" to disable a timeout.
  # @default -- Tuned for streaming; increase or set to "0s" if requests are cut off.
  timeouts:
    # -- Stream idle timeout. Time with no activity before stream is closed. 0 = disabled (required for long-lived streams).
    streamIdle: "0s"
    # -- Time to receive full request headers. 0 = disabled.
    requestHeaders: "60s"
    # -- Total request timeout. 0 = disabled (required for streaming; not compatible with streaming if set).
    request: "0s"
    # -- Per-route timeout for the passthrough to backend. 0 = disabled.
    route: "0s"
    # -- Cluster connect timeout (time to establish connection to backend).
    connect: "30s"
    # -- Positive whole-second upstream connection idle timeout. Must be less than api.server.keepAliveTimeoutSeconds when Envoy is enabled.
    upstreamIdle: "4s"

  # -- Kubernetes deployment resources configuration for the Envoy service. Utilization-based autoscaling requires a matching resource request.
  resources: {}

  # -- Liveness probe for the Envoy container (admin interface /ready).
  livenessProbe:
    httpGet:
      path: /ready
      port: admin
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3
  # -- Readiness probe for the Envoy container (admin interface /ready).
  readinessProbe:
    httpGet:
      path: /ready
      port: admin
    periodSeconds: 10
    timeoutSeconds: 5
    failureThreshold: 3
  # -- Startup probe for the Envoy container (admin interface /ready).
  startupProbe:
    httpGet:
      path: /ready
      port: admin
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 12

  # -- PodDisruptionBudget configuration for the Envoy service.
  # @default -- This object has the following default values for the pod disruption budget configuration.
  podDisruptionBudget:
    # -- Whether to create a PodDisruptionBudget for the Envoy pods.
    enabled: false
    # -- Minimum number of Envoy pods that must remain available during voluntary disruptions.
    # Only one of minAvailable or maxUnavailable may be set.
    minAvailable: 1
    # -- Maximum number of Envoy pods that can be unavailable during voluntary disruptions.
    # Only one of minAvailable or maxUnavailable may be set.
    # maxUnavailable: 0
    # -- Annotations for the PodDisruptionBudget.
    annotations: {}

  # -- Specifies autoscaling configurations for the deployment.
  autoscaling:
    # -- Whether to enable horizontal pod autoscaler.
    enabled: false
    # -- The minimum number of replicas for the deployment.
    minReplicas: 1
    # -- The maximum number of replicas for the deployment.
    maxReplicas: 10
    # -- The target CPU utilization percentage. Requires envoyProxy.resources.requests.cpu.
    targetCPUUtilizationPercentage: 80
    # -- The target memory utilization percentage. Requires envoyProxy.resources.requests.memory.
    targetMemoryUtilizationPercentage: null
    # -- Annotations for the HorizontalPodAutoscaler.
    annotations: {}

  # Environment variables to pass to containers. This is an object formatted like NAME: value or NAME: valueFrom: {object}
  env: {}
  # -- Node selector configuration for the Envoy pods.
  nodeSelector: {}
  # -- Affinity configuration for the Envoy pods.
  affinity: {}
  # -- Tolerations configuration for the Envoy pods.
  tolerations: []
  # -- Topology spread constraints for the Envoy pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/
  topologySpreadConstraints: []

  # -- Extra arguments to append to the envoy container command. Useful for passing server flags such as concurrency.
  # Example: ["--concurrency", "4"]
  extraArgs: []

  # -- Full Envoy config override. When set, this replaces the chart's default passthrough Envoy config.
  configOverride: ""

  # -- Additional volume mounts to add to the Envoy container.
  extraVolumeMounts: []

  # -- Additional volumes to add to the Envoy pod.
  extraVolumes: []

  # ServiceMonitor configuration for Prometheus Operator
  serviceMonitor:
    # -- Enable ServiceMonitor resources for Prometheus Operator
    enabled: false
    # -- Scrape interval for the ServiceMonitor
    interval: "30s"
    # -- Scheme to use for scraping metrics (http or https)
    scheme: "http"
    # -- Additional labels to add to the ServiceMonitor
    labels: {}
    # -- Additional annotations to add to the ServiceMonitor
    annotations: {}
```