All required self-hosted NVCF artifacts (see self-hosted-artifact-manifest) must be available to be pulled by pods in your Kubernetes cluster for a successful installation using the split stack bundles (nvcf-self-managed-stack for control plane and nvcf-compute-plane-stack for compute plane). This page provides examples on how to pull artifacts from NGC and push them to your desired registry.
Use this page to mirror NVCF artifacts into the registry your cluster can access. The examples below show the commands for pulling from NGC and pushing to a private registry such as ECR, Harbor, or another OCI-compatible registry.
For ECR mirroring, make sure your AWS credentials have permission to create repositories and push images. Verify access with `aws sts get-caller-identity`.You must have access to the NGC nvcf-onprem organization to begin.
- Navigate to https://org.ngc.nvidia.com/setup/api-keys and ensure you have selected the
nvcf-onpremorganization in the upper right. - Create a Personal API key with the required scopes to pull entities.
- Set the NGC API key as an environment variable for use in any subsequent commands:
export NGC_API_KEY="nvapi-xxxxxxxxxxxxx" # Replace with your NGC API keyIf you plan to deploy Low Latency Streaming (LLS), you must mirror the following additional artifacts beyond the core NVCF control plane:
Container Images:
streaming-proxy- Streaming Proxy container for streaming
Helm Charts:
gdn-streaming- GDN Streaming Proxy Helm chart
Optional (for streaming workloads):
- Streaming application images (e.g.,
usd-composer)
See self-hosted-lls-installation for LLS deployment instructions.
**Important:** The examples below show how to pull individual artifacts. You must pull **each image, chart, and resource** listed in the [self-hosted-artifact-manifest](./manifest.md) individually. These examples demonstrate the process for one artifact of each type - you will need to repeat these steps for every artifact required for your deployment.Complete the following for each artifact:
- Pull each container image from NGC
- Pull each Helm chart from NGC
- Pull each required resource bundle from NGC
- Push each artifact to your target registry (ECR, Harbor, etc.)
See the self-hosted-artifact-manifest for the complete list of all required artifacts.
**Platform Architecture Mismatch**When pulling images, Docker pulls the architecture matching your local machine by default. If you're running on an Apple Silicon Mac (arm64) but deploying to an amd64 cluster (most EKS/GKE clusters), you must specify the target platform:
# Pull for amd64 clusters (most common)
docker pull --platform linux/amd64 <image>
# Pull for arm64 clusters
docker pull --platform linux/arm64 <image>Failing to specify the correct platform will result in exec format error when pods attempt to start. See image-mirroring-troubleshooting for more details.
-
Login using the Personal API key you have generated in the previous step:
docker login nvcr.io -u '$oauthtoken' -p <NGC_API_KEY>
-
Pull the image (specify platform matching your target cluster):
# For amd64 clusters (most EKS, GKE, AKS clusters) docker pull --platform linux/amd64 nvcr.io/nvidia/nvcf/nats-box:0.19.7-nonroot # For arm64 clusters (Graviton-based EKS, etc.) docker pull --platform linux/arm64 nvcr.io/nvidia/nvcf/nats-box:0.19.7-nonroot
Public NVCF Helm Charts
# Add and update the public NVCF Helm repository
helm repo add nvcf https://helm.ngc.nvidia.com/nvidia/nvcf --force-update
helm repo update
# Pull the chart
helm pull nvcf/helm-nvca-operator --version 1.12.7
# Prerelease charts require --devel when searching
helm search repo nvcf/helm-nvcf-vanity-gateway --versions --develOther Repository-based Helm Charts (Non-OCI)
The GPU Operator and the Omniverse DDCS, UCC, storage-service, and discovery-service charts are also available from traditional Helm repositories rather than OCI registries. Pull them directly from the public NVIDIA NGC Catalog.
# Add the NVIDIA Helm repository
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia --force-update
helm repo add omniverse https://helm.ngc.nvidia.com/nvidia/omniverse --force-update
# Update repositories
helm repo update
# Pull charts (downloads as .tgz files)
helm pull nvidia/gpu-operator --version 25.3.1
helm pull omniverse/ddcs --version 5.0.0
helm pull omniverse/usd-content-cache --version 3.0.3
helm pull omniverse/storage-service --version 1.0.2
helm pull omniverse/discovery-service --version 2.3.8- Pull directly from the public repository at runtime (simplest approach)
- Mirror to your private registry for air-gapped environments (see below)
Converting Non-OCI Charts for ECR
To push repository-based Helm charts to Amazon ECR (which requires OCI format), you must convert them:
# Pull the chart from the traditional repository
helm repo add omniverse https://helm.ngc.nvidia.com/nvidia/omniverse --force-update
helm repo update
helm pull omniverse/ddcs --version 5.0.0
# Login to ECR
aws ecr get-login-password --region us-east-1 | \
helm registry login --username AWS --password-stdin <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com
# Create ECR repository for the chart (include your repository prefix)
aws ecr create-repository --repository-name nvcf-self-hosted/ddcs --region us-east-1
# Push the .tgz file as an OCI artifact (include repository prefix)
helm push ddcs-5.0.0.tgz oci://<aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/nvcf-self-hostedUsing NGC CLI
First, ensure you have the NGC CLI installed and configured using the Personal API key you created.
{/* docs-version-sync:BEGIN image-mirroring-resource-examples */}
# Set stack versions
export STACK_VERSION="0.6.0"
export COMPUTE_STACK_VERSION="1.0.6"
# Download a specific control-plane stack version
ngc registry resource download-version \
"nvidia/nvcf/nvcf-self-managed-stack:${STACK_VERSION}"
# Download a specific compute-plane stack version
ngc registry resource download-version \
"nvidia/nvcf/nvcf-compute-plane-stack:${COMPUTE_STACK_VERSION}"{/* docs-version-sync:END image-mirroring-resource-examples */}
The nvcf-self-managed-stack repository contains Helmfile configurations for deploying the NVCF control plane components.
Download and extract:
{/* docs-version-sync:BEGIN image-mirroring-stack-snippet */}
# Set the version
export VERSION="0.6.0"
ngc registry resource download-version "nvidia/nvcf/nvcf-self-managed-stack:${VERSION}" && \
mkdir -p nvcf-self-managed-stack && \
tar -xzf nvcf-self-managed-stack_v${VERSION}/nvcf-self-managed-stack-${VERSION}.tar.gz -C nvcf-self-managed-stack && \
rm -rf nvcf-self-managed-stack_v${VERSION}{/* docs-version-sync:END image-mirroring-stack-snippet */}
If you don't have access to this repository, contact your NVIDIA representative.The nvcf-compute-plane-stack repository contains Helmfile configurations for deploying compute-plane components.
Download and extract:
{/* docs-version-sync:BEGIN image-mirroring-compute-stack-snippet */}
# Set the version
export COMPUTE_VERSION="1.0.6"
ngc registry resource download-version "nvidia/nvcf/nvcf-compute-plane-stack:${COMPUTE_VERSION}" && \
mkdir -p nvcf-compute-plane-stack && \
tar -xzf nvcf-compute-plane-stack_v${COMPUTE_VERSION}/nvcf-compute-plane-stack-${COMPUTE_VERSION}.tar.gz -C nvcf-compute-plane-stack && \
rm -rf nvcf-compute-plane-stack_v${COMPUTE_VERSION}{/* docs-version-sync:END image-mirroring-compute-stack-snippet */}
Use both stack bundles for split-stack local and self-managed installs: `nvcf-self-managed-stack` for the control plane and `nvcf-compute-plane-stack` for compute-plane components.The nvcf-cli is a command-line interface for managing NVIDIA Cloud Functions in self-hosted deployments.
Download and extract:
{/* docs-version-sync:BEGIN image-mirroring-cli-snippet */}
# Set the version
export VERSION="1.10.3"
# Set your platform (linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64)
export PLATFORM="linux-amd64"
ngc registry resource download-version "nvidia/nvcf/nvcf-cli:${VERSION}"
tar -xzf nvcf-cli_v${VERSION}/${PLATFORM}/nvcf-cli-${PLATFORM}-${VERSION}.tar.gz
mv nvcf-cli-${PLATFORM}-${VERSION} nvcf-cli
chmod +x nvcf-cli/nvcf-cli{/* docs-version-sync:END image-mirroring-cli-snippet */}
The extracted directory contains:
nvcf-cli- The CLI binary.nvcf-cli.yaml.template- Configuration templateexamples/- Sample configuration files for different environmentsUSAGE-GUIDE.md- Detailed usage documentation
See self-hosted-cli for detailed configuration instructions
If you don't have access to this repository, contact your NVIDIA representative. Ensure all artifacts listed in the [self-hosted-artifact-manifest](./manifest.md) are mirrored to your registry before beginning the installation process.This example assumes you're configured and authenticated using the AWS CLI.
**Identify Your AWS Account ID**The examples below use <aws-account-id> as a placeholder. To get your AWS account ID, run:
aws sts get-caller-identity --query Account --output textThe Helm templates expect images at: {{ registry }}/{{ repository }}/image-name:tag
For example, with environment configuration:
global:
image:
registry: <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com
repository: nvcf-self-hostedThe resulting image path would be: <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/nvcf-self-hosted/nats-box:0.19.7-nonroot
In ECR, you must create repositories with the full path including the prefix, e.g., nvcf-self-hosted/notary-service, nvcf-self-hosted/nats-box, etc.
Initial Setup
# Set your repository prefix (must match global.image.repository in your environment config)
REPO_PREFIX="nvcf-self-hosted"
# Login to AWS ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin <aws-account-id>.dkr.ecr.us-east-1.amazonaws.comPush an Image to ECR
# Create ECR repository with the full path (including prefix)
aws ecr create-repository --repository-name ${REPO_PREFIX}/nats-box --region us-east-1
# Tag the image for ECR (include repository prefix in path)
docker tag nvcr.io/nvidia/nvcf/nats-box:0.19.7-nonroot \
<aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/${REPO_PREFIX}/nats-box:0.19.7-nonroot
# Push to ECR
docker push <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/${REPO_PREFIX}/nats-box:0.19.7-nonrootPush a Helm Chart to ECR
# 1. Add and update the public NVCF Helm repository
helm repo add nvcf https://helm.ngc.nvidia.com/nvidia/nvcf --force-update
helm repo update
# 2. Pull the Helm chart from NGC
helm pull nvcf/helm-nvca-operator --version 1.12.7
# This creates: helm-nvca-operator-1.12.7.tgz
# 3. Login to AWS ECR with Helm
aws ecr get-login-password --region us-east-1 | \
helm registry login --username AWS --password-stdin <aws-account-id>.dkr.ecr.us-east-1.amazonaws.com
# 4. Create ECR repository with prefix (must match your environment config)
aws ecr create-repository --repository-name ${REPO_PREFIX}/helm-nvca-operator --region us-east-1
# 5. Push to ECR as OCI artifact (include repository prefix)
helm push helm-nvca-operator-1.12.7.tgz oci://<aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/${REPO_PREFIX}This example shows how to push images and Helm charts to Volcano Engine Container Registry (CR) using the web console, Docker commands and Helm commands.
**Volcano Engine CR Repository Naming Convention**The Helm templates expect images at: {{ registry }}/{{ repository }}/image-name:tag
For example, with environment configuration:
global:
image:
registry: cr-example-cn-beijing.cr.volces.com
repository: nvcf-self-hostedThe resulting image path would be: cr-example-cn-beijing.cr.volces.com/nvcf-self-hosted/nats-box:0.19.7-nonroot
Docker Authentication
# Set your Volcano Engine CR endpoint
CR_ENDPOINT="cr-example-cn-beijing.cr.volces.com"
CR_USERNAME="your-username"
CR_PASSWORD="your-password"
# Login to Volcano Engine CR
echo "${CR_PASSWORD}" | docker login "${CR_ENDPOINT}" \
--username "${CR_USERNAME}" --password-stdinPush an Image to Volcano Engine CR
# Set your registry endpoint and namespace
CR_ENDPOINT="cr-example-cn-beijing.cr.volces.com"
NAMESPACE="nvcf-self-hosted"
# Tag the image for Volcano Engine CR
docker tag nvcr.io/nvidia/nvcf/nats-box:0.19.7-nonroot \
${CR_ENDPOINT}/${NAMESPACE}/nats-box:0.19.7-nonroot
# Push to Volcano Engine CR
docker push ${CR_ENDPOINT}/${NAMESPACE}/nats-box:0.19.7-nonrootPush a Helm Chart to Volcano Engine CR
# Set your registry endpoint and namespace
CR_ENDPOINT="cr-example-cn-beijing.cr.volces.com"
NAMESPACE="nvcf-self-hosted"
CR_USERNAME="your-username"
CR_PASSWORD="your-password"
# 1. Add and update the public NVCF Helm repository
helm repo add nvcf https://helm.ngc.nvidia.com/nvidia/nvcf --force-update
helm repo update
# 2. Pull the Helm chart from NGC
helm pull nvcf/helm-nvca-operator --version 1.12.7
# This creates: helm-nvca-operator-1.12.7.tgz
# 3. Login to Volcano Engine CR with Helm
helm registry login ${CR_ENDPOINT} \
--username "${CR_USERNAME}" \
--password "${CR_PASSWORD}"
# 4. Push to Volcano Engine CR as OCI artifact
helm push helm-nvca-operator-1.12.7.tgz oci://${CR_ENDPOINT}/${NAMESPACE}Symptom: Pods fail to start with Init:CrashLoopBackOff or CrashLoopBackOff status. Checking the logs shows:
exec /bin/sh: exec format error
or
exec /usr/local/bin/docker-entrypoint.sh: exec format error
Cause: This error occurs when container images were pulled/pushed with an architecture that doesn't match your cluster's node architecture. This commonly happens when:
- Mirroring from an Apple Silicon Mac (arm64) to an amd64 EKS/GKE cluster
- Mirroring from an Intel/AMD machine (amd64) to an arm64 cluster (e.g., AWS Graviton)
Solution:
-
Delete the incorrectly mirrored images from your registry (e.g., ECR):
# Delete all repositories with your prefix aws ecr describe-repositories --region us-west-2 \ --query "repositories[?starts_with(repositoryName, 'nvcf-self-hosted')].repositoryName" \ --output text | tr '\t' '\n' | while read repo; do aws ecr delete-repository --repository-name "$repo" --region us-west-2 --force done
-
Clean local Docker cache to ensure fresh pulls:
# Remove all NGC and ECR images from local cache docker images --format "{{.Repository}}:{{.Tag}}" | \ grep -E "(nvcr.io|\.ecr\.)" | \ xargs -r docker rmi -f # Prune dangling images docker image prune -f
-
Re-mirror images with the correct platform:
When pulling images, explicitly specify the target platform:
# For amd64 clusters (most common) docker pull --platform linux/amd64 <image> # For arm64 clusters docker pull --platform linux/arm64 <image>
Then re-tag and push to your registry.
-
Force Kubernetes to re-pull images by either:
- Setting
imagePullPolicy: Alwaystemporarily in your Helm values - Deleting and redeploying the affected StatefulSets/Deployments
# Delete StatefulSets to force recreation kubectl -n cassandra-system delete statefulset cassandra kubectl -n nats-system delete statefulset nats # Redeploy using helmfile HELMFILE_ENV=<environment-name> helmfile sync
- Setting
