> ## Documentation Index
> Fetch the complete documentation index at: https://neuraltrust-92b43583-develop.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Container images

> Pull NeuralTrust images directly with the key we send you, or mirror them into your own registry.

The Helm chart and the container images are distributed differently. The chart
is published to a **public** OCI registry — `helm install` and `helm template`
pull it anonymously, with no `helm registry login`. The **images are private**.

When your account is provisioned, NeuralTrust sends you a **registry key** — a
JSON service-account key — plus the registry server to use it against. Keep it
with your other production credentials; it is the only thing standing between
your cluster and the images. Everything on this page is about the images.

From there you have two supported paths:

|                | **Pull directly**                      | **Mirror to your own registry**                                   |
| :------------- | -------------------------------------- | ----------------------------------------------------------------- |
| Best for       | Clusters with outbound internet access | Air-gapped clusters, or policy that requires an internal registry |
| You manage     | One Kubernetes Secret                  | A registry, a copy of every image, and re-syncing on upgrade      |
| Values changes | None                                   | `global.imageRegistry` and two collector overrides                |

Both paths pull the same images. Hybrid pulls the data path; External
additionally pulls the console and analytics stack; a
[Central control plane](/neuraltrust/deployment/central) pulls everything
External does plus two more — `databridge` and
`opentelemetry-collector-contrib` for the ingest gateway.

## Get the chart sources

Every install path starts from tracked files that `helm install` does not create:
`create-image-pull-secret.sh`, `values-required.yaml`, and the
`values-*.yaml.example` presets. They live in the chart's public repository,
[NeuralTrust/neuraltrust-platform](https://github.com/NeuralTrust/neuraltrust-platform),
and they are packaged inside the chart artifact, so you can get them without
cloning and without credentials:

```bash theme={null}
helm pull oci://europe-west1-docker.pkg.dev/neuraltrust-app-prod/helm-charts/neuraltrust-platform \
  --version <VERSION> --untar
cd neuraltrust-platform
```

That directory matches the exact chart version you are about to install, which is
why it is preferable to `git clone` for an install. Clone the repository instead
when you want history, issues, or the in-repo operator references: `SECRETS.md`
for the full per-component key contract, `VALUES_SCENARIOS.md` for scenario
walkthroughs, and `docs/` for the architecture, sizing, and network notes.

## Pull directly from NeuralTrust

Create a `docker-registry` Secret from the key. The chart ships
`create-image-pull-secret.sh`, which fills in the registry server and username
for you. Get it by unpacking the chart — `helm pull <chart-ref> --version <VERSION> --untar` — or from the public repository,
[NeuralTrust/neuraltrust-platform](https://github.com/NeuralTrust/neuraltrust-platform/blob/main/create-image-pull-secret.sh):

```bash theme={null}
GCR_KEY_FILE=./neuraltrust-registry-key.json \
  ./create-image-pull-secret.sh --namespace neuraltrust
```

The equivalent by hand — the username is the literal string `_json_key`, and the
password is the **entire contents** of the key file, not a path to it:

```bash theme={null}
kubectl create secret docker-registry gcr-secret -n neuraltrust \
  --docker-server='<registry-server-from-neuraltrust>' \
  --docker-username='_json_key' \
  --docker-password="$(cat ./neuraltrust-registry-key.json)" \
  --docker-email='<your-email>'
```

<Note>
  Name the Secret **`gcr-secret`**. Every component defaults to that name, so no
  values changes are needed. If you must use a different name, see
  [Renaming the pull Secret](#renaming-the-pull-secret).
</Note>

That is the whole setup. Continue with your model's install —
[Hybrid](/neuraltrust/deployment/hybrid#install) or
[External](/neuraltrust/deployment/external#install).

## Mirror to your own registry

Copy every image your deployment uses into your registry, preserving the
repository names and tags — change only the registry host.

### Which images to copy

Render your own values file to get the exact list, including the tags pinned by
your chart version:

```bash theme={null}
helm template neuraltrust-platform \
  oci://europe-west1-docker.pkg.dev/neuraltrust-app-prod/helm-charts/neuraltrust-platform \
  --version <VERSION> -f <your-values.yaml> \
  | grep -o 'image: .*' | sort -u
```

A Hybrid install with all products enabled pulls `agentgateway`, `trustguard`,
`firewall-cpu`, `data-plane-api`, `dataagent`,
`opentelemetry-collector-contrib`, and — unless you use managed stores —
`postgres` and `redis-stack-server`. External adds `control-plane-api`, `app`,
`datacore`, `alertengine`, `clickstack-otel-collector`, and `clickhouse-server`.
A central cluster adds `databridge` and a second
`opentelemetry-collector-contrib` for the ingest gateway on top of the External
set; its data-plane clusters need only the Hybrid set.
GPU Firewall uses a separate image — see
[GPU Firewall workers](/neuraltrust/deployment/configuration#gpu-firewall-workers).

### Point the chart at your registry

```yaml theme={null}
global:
  imageRegistry: registry.example.com/neuraltrust
```

<Warning>
  **`global.imageRegistry` does not rewrite the OTel collector images.** Their
  repositories are pinned in full, so they keep pointing at the NeuralTrust
  registry and their pods fail to pull in an air-gapped cluster. Override them
  explicitly:

  ```yaml theme={null}
  global:
    clickstack:
      egress:
        image:
          repository: registry.example.com/neuraltrust/opentelemetry-collector-contrib
    observability:
      collector:
        image:
          repository: registry.example.com/neuraltrust/opentelemetry-collector-contrib
  ```

  Set only the ones you render. The first is the DataAgent egress sidecar, which
  every Hybrid install runs and External never deploys. The second applies to
  either mode, but only when `global.observability.enabled` is `true`. An External
  install with observability off needs neither, and `global.imageRegistry` covers
  it completely.

  The ingest gateway a central cluster runs is the same upstream collector, but it
  **is** rewritten by `global.imageRegistry` and needs no entry here. Override it
  per component only to pull it from somewhere else than your other images:

  ```yaml theme={null}
  clickstack-ingest-gateway:
    image:
      repository: registry.example.com/neuraltrust/opentelemetry-collector-contrib
  ```

  Either way, re-run the `helm template | grep image:` command above afterwards and
  confirm no image still points at the NeuralTrust registry.
</Warning>

Then create a pull Secret for **your** registry, named `gcr-secret`, in the
release namespace:

```bash theme={null}
kubectl create secret docker-registry gcr-secret -n neuraltrust \
  --docker-server='registry.example.com' \
  --docker-username='<user>' \
  --docker-password='<password>'
```

Re-mirror when you upgrade the chart — tags are pinned per chart version, so a
new version pulls images your registry does not have yet.

## Renaming the pull Secret

Every component defaults to a Secret named `gcr-secret`, and
`global.imagePullSecrets` **does not override that default** — it only applies to
the chart's own in-cluster PostgreSQL and Redis. Setting it alone leaves the
product workloads still asking for `gcr-secret`.

Reusing the name `gcr-secret` for your own registry credential is by far the
simplest option. If your policy forbids it, set the pull secret on each component
instead, and verify with:

```bash theme={null}
helm template neuraltrust-platform \
  oci://europe-west1-docker.pkg.dev/neuraltrust-app-prod/helm-charts/neuraltrust-platform \
  --version <VERSION> -f <your-values.yaml> \
  | grep -A2 imagePullSecrets
```

## Clusters that pull without a Secret

Where node or workload identity already authorizes registry pulls — GKE Workload
Identity, an EKS instance profile, ACR attached to AKS — you do not need to
create anything. Leave the defaults alone: pods keep a reference to a
`gcr-secret` that does not exist, and the kubelet falls back to the node
credentials.

<Warning>
  Do not try to suppress the references with `global.imagePullSecrets: ["none"]`.
  It does not clear them from the product workloads, and it makes the Redis
  Deployment reference a Secret literally named `none`.
</Warning>
