> This page is for version 0.8.0.
> For other versions, use one of these documentation indexes:
> - Latest (default): https://docs.nvidia.com/nemo-helix/latest/llms.txt
> - 0.8.0: https://docs.nvidia.com/nemo-helix/v0.8.0/llms.txt
> - 0.7.1: https://docs.nvidia.com/nemo-helix/v0.7.1/llms.txt
> - 0.7.0: https://docs.nvidia.com/nemo-helix/v0.7.0/llms.txt
> - 0.6.0: https://docs.nvidia.com/nemo-helix/v0.6.0/llms.txt
> - 0.5.1: https://docs.nvidia.com/nemo-helix/v0.5.1/llms.txt
> - 0.5.0: https://docs.nvidia.com/nemo-helix/v0.5.0/llms.txt
> - 0.4.0: https://docs.nvidia.com/nemo-helix/v0.4.0/llms.txt
> - 0.3.0: https://docs.nvidia.com/nemo-helix/v0.3.0/llms.txt
> - 0.2.0: https://docs.nvidia.com/nemo-helix/v0.2.0/llms.txt

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

# NeMo Helix Helm Chart

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

For deployment guide, see [Kubernetes Deployment](/documentation/kubernetes-deployment/setup) in the NeMo Helix documentation.

## Upgrading installations from before the rename

Kubernetes Deployment selectors are immutable. If your existing component labels
differ from the chart defaults, set `api.componentLabel` and
`core.controller.componentLabel` to match the deployed selectors. For example,
an installation using the legacy labels would use:

```yaml
api:
  componentLabel: nmp-api
core:
  controller:
    componentLabel: nmp-core-controller
```

Retain these overrides on subsequent upgrades for the lifetime of those
Deployments. Also preserve your existing release name, resource names, storage
configuration, and encryption key and its Secret reference. Fresh installations
use the chart defaults.

## Platform Secrets Encryption Key

The platform secrets service reads `NHX_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
`NHX_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-helix/latest/documentation/kubernetes-deployment/setup/helm/multinode-networking](https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-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-helix/latest/documentation/kubernetes-deployment/setup/helm/volcano](https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-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: [k8s/helm/examples/opensandbox](https://github.com/NVIDIA-NeMo/nemo-helix/tree/main/k8s/helm/examples/opensandbox).
Shared-kernel (cluster default OCI runtime): [https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-deployment/setup/helm/open-sandbox](https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-deployment/setup/helm/open-sandbox)
Kata QEMU: [https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-deployment/setup/helm/opensandbox-kata](https://docs.nvidia.com/nemo-helix/latest/documentation/kubernetes-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 Helix 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 NHX_SECRETS_DEFAULT_ENCRYPTION_KEY string.
      key: NHX_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-helix/documentation/kubernetes-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
          nhx.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
        nhx.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-helix/nhx-automodel-training
      tag: ""
    resources:
      requests:
        cpu: "4"
        memory: 8Gi
      limits:
        cpu: "8"
        memory: 16Gi

# -- Local PostgreSQL configuration for the NeMo Helix.
# @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: nemohelix
    # -- Name of an existing secret containing the PostgreSQL password. If set, the chart does not create a secret.
    existingSecret: ""
    # -- Key in the existing secret containing the PostgreSQL password.
    existingSecretPasswordKey: password

  # -- 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: nemohelix
  # -- 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 `baseHelixConfig` 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-helix
platformConfig: {}

# -- Base platform configuration settings
# @default -- This object has the following default values for the base platform configuration.
baseHelixConfig: |
  # -- 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 Helix when deploying with Helm.
    runtime: kubernetes

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

    # Image configuration for launching containers via the platform
    image_registry: nvcr.io/nvidia/nemo-helix
    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.nhx-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 "nhx-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 "nhx-core.jobsServiceAccountName" . | quote }}
        launcher_image: {{ include "nhx-core.image" . | quote }}
        storage:
          pvc_name: {{ (include "nhx-core.persistentVolumeClaim" . ) }}
          volume_permissions_image: {{ .Values.core.storage.volumePermissionsImage | quote }}
        pod_security_context: {{ .Values.podSecurityContext | toYaml | nindent 10 }}
      volcano_job:
        service_account_name: {{ include "nhx-core.jobsServiceAccountName" . | quote }}
        launcher_image: {{ include "nhx-core.image" . | quote }}
        storage:
          pvc_name: {{ (include "nhx-core.persistentVolumeClaim" . ) }}
          volume_permissions_image: {{ .Values.core.storage.volumePermissionsImage | quote }}
        pod_security_context: {{ .Values.podSecurityContext | toYaml | nindent 10 }}
        {{- if include "nemo-helix.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: "NHX_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
            - nhx.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

  # -- garak is the configuration specific to the Garak service
  garak: {}

  # -- 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:
    # -- default_training_execution_profile is the single-node GPU profile used when the job
    # omits training.execution_profile. Matches automodel and unsloth.
    default_training_execution_profile: default
    # -- 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 "nhx-core.persistentVolumeClaim" . ) }}
    # Gym sandbox pod size.
    sandbox_resources:
      cpu: "2"
      memory: 4Gi

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

  # -- evals is the configuration specific to the Evals service
  evals: {}

  # -- 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-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.ingressBackendPort" . }}'
        - path: /apis
          pathType: Prefix
          service: '{{ include "nemo-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.ingressBackendPort" . }}'
        - path: /studio
          pathType: Prefix
          service: '{{ include "nemo-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.ingressBackendPort" . }}'
        - path: /cluster-info
          pathType: Exact
          service: '{{ include "nemo-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.ingressBackendPort" . }}'
        - path: /status
          pathType: Exact
          service: '{{ include "nemo-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.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-helix.ingressBackendService" . }}'
          port: '{{ include "nemo-helix.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-helix.ingressBackendService" . }}'
  # -- Target port on the service. Defaults to Envoy or API port depending on auth (tpl-evaluated).
  targetPort: '{{ include "nemo-helix.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:
  # -- Component label shared by API selectors and matching resources. Keep unchanged for existing Deployments.
  componentLabel: nhx-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 Helix image is located.
    repository: nvcr.io/nvidia/nemo-helix/nhx-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, NHX_PLATFORM_SEED_*).
  extraEnv: []
  # -- Extra volume mounts for the platform-seed container.
  extraVolumeMounts: []
  # -- Extra volumes for the platform-seed pod.
  extraVolumes: []
  # -- 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 Helix image is located.
    repository: nvcr.io/nvidia/nemo-helix/nhx-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:
    # -- Component label shared by controller selectors and matching resources. Keep unchanged for existing Deployments.
    componentLabel: nhx-core-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: {}
    # -- Additional volume mounts to add to the controller container.
    extraVolumeMounts: []
    # -- Additional volumes to add to the controller pod.
    extraVolumes: []
    # -- 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-nhx-principal-id
    - x-nhx-actor-account-id
    - x-nhx-principal-email
    - x-nhx-principal-groups
    - x-nhx-actor-aliases
    - x-nhx-principal-on-behalf-of
    - x-nhx-subject-account-id
    - x-nhx-subject-aliases
    - x-nhx-principal-on-behalf-of-groups
    - x-nhx-principal-on-behalf-of-email
    - x-nhx-principal-filters
    - x-nhx-principal-roles
    - x-nhx-internal
    - x-nhx-scopes

  # 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: {}
```