For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
    • Overview
    • Quickstart
  • Before You Deploy
    • Infrastructure Sizing
    • Manifest
  • Deployment
    • Installation Overview
    • Image Mirroring
    • Helmfile Installation
  • GPU Cluster Setup
    • GPU Cluster Setup
    • Self-Managed Clusters
  • Configuration
    • Optional Enhancements
    • LLM Function Enablement
    • Gateway Routing
    • Third-Party Registries
    • Registry Allowlist
    • Cluster Configuration
    • KAI Scheduler
  • Using Cloud Functions
    • API
    • Service Keys
    • Function Creation
    • LLM Gateway
    • Generic HTTP Function Invocation
    • gRPC Function Invocation
    • Container Functions
    • Helm Functions
    • Streaming Functions
    • Configure Autoscaling
    • CLI
  • Function Autoscaling
    • Function Autoscaling Overview
    • Architecture
    • Operations
    • Observability
  • Observability
    • Observability
    • Example Dashboards
  • Operations
    • Control Plane Operations
    • Cluster Monitoring
    • Troubleshooting
  • Runbooks
    • Runbooks
    • Key Rotation
  • Reference
    • Cluster Reference
    • gRPC Load Testing
    • gRPC Load Test SLI Guide
    • HTTP Load Testing
    • HTTP Load Test SLI Guide
    • HTTP Soak Testing
  • Development
    • Architecture Overview
      • Local Development
      • Single-cluster (CLI)
      • Single-cluster (Helmfile)
      • Multi-cluster (CLI)
      • Multi-cluster (Helmfile)
    • Fake GPU Operator
    • Release Process
  • Managed (Legacy)
    • Function Lifecycle
    • Observability
NVIDIANVIDIA
Developer-friendly docs for your API
Privacy Policy | Your Privacy Choices | Terms of Service | Accessibility | Corporate Policies | Product Security | Contact

Copyright © 2026, NVIDIA Corporation.

LogoLogoCloud Functions
On this page
  • Prerequisites
  • Step 1: Bring up the local k3d cluster
  • Step 2: Author the Helmfile environment file
  • Step 3: Author the secrets file
  • Step 4: Pre-create the image pull secret in NVCF namespaces
  • Step 5: (Optional) Validate the rendered manifests
  • Step 6: Install the control plane
  • Step 7: Register the cluster
  • Step 8: Install the NVCA operator
  • Step 9: Verify
  • Teardown
DevelopmentLocal Development

Single-cluster Local Development with Helmfile

||View as Markdown|
Previous

Single-cluster (CLI)

Next

Multi-cluster (CLI)

Install the NVCF self-hosted control plane and the NVCA operator on a single local k3d cluster using the documented Helmfile workflow. Useful when you want to drive the install through the same Make targets used in production.

This setup is for local development only. It uses fake GPUs, a single Cassandra replica, and ephemeral storage. Do not use this for production workloads.

Prerequisites

Install the following tools:

  • Docker (running)

  • k3d v5.x or later

  • kubectl

  • helm >= 3.12

  • helmfile >= 1.1.0, < 1.2.0

  • helm-diff plugin: helm plugin install https://github.com/databus23/helm-diff

  • An NGC API key from ngc.nvidia.com with access to the NVCF chart and image registry.

  • The NGC organization and team slugs that hold the chart/image repository you have access to.

  • nvcf-cli built from this repo. Steps 7 and 8 pass NVCF_CLI=$(pwd)/nvcf-cli to the make targets, so the binary must exist on disk before those steps run:

    $go build -o nvcf-cli ./src/clis/nvcf-cli

Export the env vars used below:

$export NGC_API_KEY="<your-ngc-api-key>"
$export SAMPLE_NGC_ORG="<your-ngc-org>"
$export SAMPLE_NGC_TEAM="<your-ngc-team>"

Step 1: Bring up the local k3d cluster

$make -C tools/ncp-local-cluster build-and-deploy-cluster

The single-cluster (ncp-local) and multi-cluster (ncp-local-cp + ncp-local-compute-N) topologies both claim host ports 8080/8443/4222 and cannot coexist. If you already have the multi-cluster topology running:

$make -C tools/ncp-local-cluster destroy-multicluster

Step 2: Author the Helmfile environment file

The single-cluster fixture tests/bdd/fixtures/self-managed-local-bdd.yaml is the canonical starting point. Its nvcaOperator.selfManaged.* URLs use in-cluster DNS (for example http://api.sis.svc.cluster.local:8080), which is correct here because compute and control plane share the cluster.

$cp tests/bdd/fixtures/self-managed-local-bdd.yaml \
> deploy/stacks/self-managed/environments/local-bdd.yaml

Substitute your NGC org and team in for the placeholders:

$sed -i.bak \
> -e "s|REPLACE_WITH_SAMPLE_NGC_ORG|${SAMPLE_NGC_ORG}|g" \
> -e "s|REPLACE_WITH_SAMPLE_NGC_TEAM|${SAMPLE_NGC_TEAM}|g" \
> deploy/stacks/self-managed/environments/local-bdd.yaml
$rm deploy/stacks/self-managed/environments/local-bdd.yaml.bak

The fields touched are global.helm.sources.repository, global.image.repository, and api.env.NVCF_SIDECARS_LLM_ROUTER_CLIENT_IMAGE. Set global.imagePullSecrets[0].name if your secret name differs from nvcr-pull-secret.

Step 3: Author the secrets file

$cp deploy/stacks/self-managed/secrets/secrets.yaml.template \
> deploy/stacks/self-managed/secrets/local-bdd-secrets.yaml
$
$BASE64_CRED=$(echo -n "\$oauthtoken:${NGC_API_KEY}" | base64 -w0)
$sed -i.bak "s|REPLACE_WITH_BASE64_DOCKER_CREDENTIAL|${BASE64_CRED}|g" \
> deploy/stacks/self-managed/secrets/local-bdd-secrets.yaml
$rm deploy/stacks/self-managed/secrets/local-bdd-secrets.yaml.bak

The secrets file is gitignored. Keep your NGC key out of the working tree.

Step 4: Pre-create the image pull secret in NVCF namespaces

$for ns in cassandra-system nats-system nvcf api-keys ess sis \
> vault-system nvca-operator nvca-system nvcf-backend cert-manager; do
$ kubectl create namespace "$ns" --dry-run=client -o yaml | kubectl apply -f -
$ kubectl create secret docker-registry nvcr-pull-secret \
> --docker-server=nvcr.io \
> --docker-username='$oauthtoken' \
> --docker-password="${NGC_API_KEY}" \
> --namespace="$ns" \
> --dry-run=client -o yaml | kubectl apply -f -
$done

Step 5: (Optional) Validate the rendered manifests

$make -C deploy/stacks/self-managed template HELMFILE_ENV=local-bdd

The command should exit 0 and its output must not contain Error:.

Step 6: Install the control plane

$make -C deploy/stacks/self-managed install HELMFILE_ENV=local-bdd

When this succeeds, the following helm releases are deployed:

ReleaseNamespace
natsnats-system
cert-managercert-manager
openbao-servervault-system
cassandracassandra-system
api-keysapi-keys
sissis
apinvcf
nvct-apinvcf
invocation-servicenvcf
grpc-proxynvcf
ess-apiess
notary-servicenvcf
admin-issuer-proxyapi-keys
revalnvcf
nats-auth-callout-servicenats-system
ingressenvoy-gateway-system
llm-request-routernvcf
llm-api-gatewaynvcf

Step 7: Register the cluster

$make -C deploy/stacks/self-managed register-cluster \
> CLUSTER_NAME=ncp-local \
> NVCF_CLI=$(pwd)/nvcf-cli \
> NVCF_CLI_CONFIG=$(pwd)/tests/bdd/fixtures/nvcf-cli-local.yaml

make register-cluster runs nvcf-cli init internally before cluster register, so the Helmfile flow does not need a separate init step (unlike the CLI flow).

The target produces deploy/stacks/self-managed/out/ncp-local-register-values.yaml with PSAT identitySource and *.localhost URLs.

Step 8: Install the NVCA operator

$make -C deploy/stacks/self-managed install-nvca-operator \
> CLUSTER_NAME=ncp-local \
> HELMFILE_ENV=local-bdd \
> NVCF_CLI=$(pwd)/nvcf-cli \
> NVCF_CLI_CONFIG=$(pwd)/tests/bdd/fixtures/nvcf-cli-local.yaml

Step 9: Verify

Wait for the NVCA operator to roll out and the backend to become healthy:

$kubectl rollout status deployment/nvca-operator -n nvca-operator --timeout=10m
$
$kubectl wait nvcfbackend ncp-local \
> -n nvca-operator \
> --for=jsonpath='{.status.agentStatus}'=healthy \
> --timeout=10m

Confirm the control-plane API is reachable:

$export NVCF_TOKEN=$(curl -s -X POST "http://api-keys.localhost:8080/v1/admin/keys" \
> | python3 -c "import sys,json; print(json.load(sys.stdin)['value'])")
$
$curl -s "http://api.localhost:8080/v2/nvcf/functions" \
> -H "Authorization: Bearer ${NVCF_TOKEN}" | python3 -m json.tool

Teardown

Remove the helm releases but keep the cluster (stack-only):

$tests/bdd/scripts/destroy-stack.sh single

Or destroy the whole cluster:

$make -C tools/ncp-local-cluster destroy