Quickstart Deployment#

Try OSMO on your local workstation — no cloud account, no infrastructure costs, no enterprise approval needed.

This Quickstart is the fastest way to try the complete OSMO platform locally. It creates a multi-node Kubernetes-in-Docker cluster with KIND or nvkind and deploys the unified osmo Helm chart.

Deployment Architecture#

../../_images/deployment_quickstart.svg

Tip

Perfect for evaluation – Test your workflows, explore the platform, and assess fit for your robotics development needs before cloud deployment of OSMO.

Warning

Local deployment is not recommended for production use because it uses development-only authentication and has limited features.

Why Deploy Locally?#

Local deployment provides the complete OSMO experience on your workstation:

✓ Full workflow orchestration – Task dependencies, parallel execution, state management

✓ Real containerized execution – Your Docker images running in local Kubernetes

✓ Complete data management – Local object storage for workflow inputs, outputs, and artifacts

✓ The same YAML workflows that scale to cloud environments

✓ Zero cloud costs – Everything runs on your workstation

Seamless Scale to Cloud

If OSMO works for your use case locally, it will scale to hundreds of GPUs in the cloud. You can use the exact same workflows; no code changes required.

Prerequisites#

Install the following tools on your workstation:

  • Docker - Container runtime (>=28.3.2)

  • KIND - Kubernetes in Docker (>=0.29.0)

  • kubectl - Kubernetes command-line tool (>=1.32.2)

  • helm - Helm package manager (>=3.16.2)

The resulting cluster requires Kubernetes 1.30 or newer and a default dynamic StorageClass.

Important

System Configuration:

  1. Raise inotify limits to prevent “too many open files” errors.

  2. Ensure your user has Docker permissions .

Clone the repository and run the remaining commands from its root:

git clone https://github.com/NVIDIA/OSMO.git
cd OSMO

Create KIND Cluster#

Choose the appropriate setup based on whether your workstation has a GPU.

Option A: GPU Workstations (with nvkind)#

If your workstation has a supported NVIDIA GPU, install the NVIDIA driver and NVIDIA Container Toolkit and confirm that they work with Docker. Install nvkind by following its prerequisites , setup , and installation guides.

Create Cluster Configuration

Create the following multi-node configuration. Every node has exactly one OSMO role: the Kubernetes control-plane and control worker host platform services, and the compute worker hosts submitted workflows. The compute worker receives the GPU from nvkind. The control worker maps gateway NodePort 30080 to host port 80.

kind-osmo-cluster-config.yaml (GPU version)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: osmo
nodes:
  - role: control-plane
    kubeadmConfigPatches:
    - |
      kind: InitConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=control-plane"
  - role: worker
    kubeadmConfigPatches:
    - |
      kind: JoinConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=control-plane"
    extraPortMappings:
      - containerPort: 30080
        hostPort: 80
        protocol: TCP
  - role: worker
    extraMounts:
      - hostPath: /dev/null
        containerPath: /var/run/nvidia-container-devices/all
    kubeadmConfigPatches:
    - |
      kind: JoinConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=compute"

Create the Cluster

Create the cluster, select its context, and confirm that nvkind passes the host GPU through:

nvkind cluster create --config-template=kind-osmo-cluster-config.yaml
nvkind cluster print-gpus
kubectl config use-context kind-osmo

Note

You can ignore umount errors from nvkind if nvkind cluster print-gpus lists the workstation GPUs.

Install GPU Operator

Install GPU Operator v25.10.1. The host driver and NVIDIA Container Toolkit are already managed by the nvkind prerequisites, so disable their in-cluster management. Version v25.10.1 includes the Kubernetes 1.33 schema-validation fix required by this quickstart.

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update nvidia
helm upgrade --install gpu-operator nvidia/gpu-operator \
  --version v25.10.1 \
  --namespace gpu-operator \
  --create-namespace \
  --set driver.enabled=false \
  --set toolkit.enabled=false \
  --set nfd.enabled=true \
  --wait \
  --timeout 10m

Option B: CPU Workstations (with KIND)#

If your workstation does not have a GPU, create a standard CPU-only cluster. The Kubernetes control-plane and control worker host platform services, while the compute worker hosts submitted workflows.

Create Cluster Configuration

kind-osmo-cluster-config.yaml (CPU-only version)
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: osmo
nodes:
  - role: control-plane
    kubeadmConfigPatches:
    - |
      kind: InitConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=control-plane"
  - role: worker
    kubeadmConfigPatches:
    - |
      kind: JoinConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=control-plane"
    extraPortMappings:
      - containerPort: 30080
        hostPort: 80
        protocol: TCP
  - role: worker
    kubeadmConfigPatches:
    - |
      kind: JoinConfiguration
      nodeRegistration:
        kubeletExtraArgs:
          node-labels: "osmo.nvidia.com/node-pool=compute"

Create the Cluster

kind create cluster --config kind-osmo-cluster-config.yaml
kubectl config use-context kind-osmo

Install Cluster Dependencies#

Install KAI Scheduler v0.15.3 for OSMO workflow scheduling, then install the CloudNativePG operator chart version 0.29.0 for the embedded PostgreSQL cluster. Keep both operators on the control worker. The checked values files supply OSMO’s scheduler behavior and the placement settings shared by the converged deployment guides:

helm upgrade --install kai-scheduler \
  https://github.com/NVIDIA/KAI-Scheduler/releases/download/v0.15.3/kai-scheduler-v0.15.3.tgz \
  --namespace kai-scheduler \
  --create-namespace \
  --values deployments/charts/osmo/examples/kai-values.yaml \
  --values deployments/charts/osmo/examples/kai-selectors.yaml \
  --wait \
  --timeout 10m

kubectl --namespace kai-scheduler wait \
  --for=condition=Available=True \
  --timeout=10m config.kai.scheduler/kai-config
kubectl wait --for=condition=Available \
  --timeout=10m schedulingshard/default
kubectl --namespace kai-scheduler wait \
  --for=condition=Available \
  --timeout=10m deployment --all

helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update cnpg
helm upgrade --install cnpg cnpg/cloudnative-pg \
  --version 0.29.0 \
  --namespace cnpg-system \
  --create-namespace \
  --set-string 'nodeSelector.osmo\.nvidia\.com/node-pool=control-plane' \
  --wait \
  --timeout 10m

Prepare Values and Secrets#

The Quickstart generates its development credentials in Kubernetes. No site-specific Secret or values file is required. The checked node-selectors.yaml overlay places OSMO and its embedded dependencies on the control worker and workflow Pods on the compute worker.

Install OSMO#

The chart defaults define a cpu platform and a gpu platform in the default pool. CPU workflows use a pod template without a GPU resource key. GPU workflows select the GPU platform, which requests nvidia.com/gpu in both the user-container requests and limits.

The chart defaults are the development Quickstart. Register the HTTP chart repositories, build the pinned dependencies from Chart.lock, and install it without a profile, layering the shared selector file afterward. The chart uses the in-cluster gateway URL for workflow Pods while retaining the public loopback URL for login.

The command uses Helm 4’s --wait=legacy strategy. With Helm 3, replace --wait=legacy with --wait.

helm repo add osmo-dex https://charts.dexidp.io
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo add osmo-rustfs https://charts.rustfs.com
helm dependency build deployments/charts/osmo
helm upgrade --install osmo deployments/charts/osmo \
  --namespace osmo \
  --create-namespace \
  --values deployments/charts/osmo/examples/node-selectors.yaml \
  --wait=legacy \
  --wait-for-jobs \
  --timeout 20m

Log In#

The cluster configuration maps the gateway to http://127.0.0.1. The default embedded Dex account signs in as admin@osmo.local and appears in OSMO as admin. Retrieve its generated initial password:

kubectl --namespace osmo get secret osmo-embedded-dex-admin \
  --output jsonpath='{.data.password}' | base64 --decode
printf '\n'

Visit http://127.0.0.1 and sign in as admin@osmo.local with that password. Embedded Dex is for development and evaluation; use an external OIDC provider and a public HTTPS URL in production.

To validate with the OSMO CLI, read the generated administrator token into a protected temporary file:

curl -fsSL https://raw.githubusercontent.com/NVIDIA/OSMO/refs/heads/main/install.sh | bash
OSMO_URL=http://127.0.0.1
set -o pipefail
umask 077
OSMO_TOKEN_FILE="$(mktemp)" &&
kubectl --namespace osmo get secret osmo-admin-token \
  --output jsonpath='{.data.token}' | base64 --decode > "$OSMO_TOKEN_FILE" &&
osmo login "$OSMO_URL" --method token --token-file "$OSMO_TOKEN_FILE"
OSMO_LOGIN_STATUS=$?
rm -f -- "${OSMO_TOKEN_FILE:-}" || OSMO_LOGIN_STATUS=$?
unset OSMO_TOKEN_FILE
test "$OSMO_LOGIN_STATUS" -eq 0

Verify the Deployment#

Check the release, OSMO and KAI readiness, and the API before submitting the canonical CPU verification workflows:

# Verify the Helm release and Kubernetes workloads
helm status osmo --namespace osmo
kubectl --namespace osmo wait --for=condition=Available \
  deployment --all --timeout=10m
kubectl --namespace kai-scheduler wait --for=condition=Available \
  deployment --all --timeout=10m

# Verify API availability
curl --fail "$OSMO_URL/api/version"
# Verify pools and resources
osmo pool list
osmo resource list --pool default

# Verify workflow submission and operation
osmo workflow submit deployments/workflows/verify-hello.yaml \
  --pool default --format-type json
osmo workflow submit deployments/workflows/verify-object-storage.yaml \
  --pool default --format-type json
OSMO_WORKFLOW_ID=<returned-workflow-id>
osmo workflow query "$OSMO_WORKFLOW_ID" --format-type json

For each submission, set OSMO_WORKFLOW_ID to the returned workflow ID and repeat the query until its status is COMPLETED. A FAILED, CANCELLED, or timed-out workflow is a validation failure. Both use the default cpu platform; the object-storage workflow also verifies a round trip between two dependent tasks.

Success!

You now have OSMO configured and running on your workstation. You’re ready to start running robotics workflows!

If you used Option A, submit the GPU verification workflow too:

osmo workflow submit deployments/workflows/verify-gpu.yaml \
  --pool default --format-type json
OSMO_WORKFLOW_ID=<returned-workflow-id>
osmo workflow query "$OSMO_WORKFLOW_ID" --format-type json

The GPU workflow explicitly uses the gpu platform and runs nvidia-smi in a CUDA container, proving that OSMO and KAI scheduled it onto the GPU node and that the NVIDIA driver and Container Toolkit are usable.

Troubleshooting#

If the GPU workflow remains pending or fails, first verify GPU capacity and the GPU Operator:

kubectl get nodes \
  -o custom-columns=NAME:.metadata.name,ALLOCATABLE_GPUS:.status.allocatable.nvidia\.com/gpu
kubectl --namespace gpu-operator get pods
kubectl --namespace osmo get events --sort-by=.lastTimestamp
kubectl --namespace osmo get pods

An allocatable GPU count of zero means the host NVIDIA driver, Container Toolkit, nvkind pass-through, or GPU Operator is not ready. Do not run other GPU workloads until verify-gpu.yaml completes. For OSMO deployment problems, inspect the listed pods and events; a pending PostgreSQL, Valkey, or RustFS PVC usually means the cluster lacks a working default StorageClass.

Capacity and limitations#

This Quickstart runs one replica of each required OSMO service and uses the generated initial credential for the embedded Dex admin@osmo.local account, which appears in OSMO as admin with the osmo-admin role. It disables TLS, rate limiting, backups, monitoring, PodDisruptionBudgets, and autoscaling. It also has no high availability guarantees. The exposed development administrator identity and NodePort are suitable only for a disposable local environment.

CloudNativePG, Valkey, and RustFS use persistent volumes supplied by the cluster’s default StorageClass. Those local volumes, generated credentials, workflow state, and all other quickstart data disappear when the cluster is deleted. Do not use this quickstart for production data or any long-lived environment.

See also

For a persistent, highly available local or edge installation, use the Self-contained Deployment guide.

Cleanup#

Remove the OSMO release, then delete the disposable cluster using the command for the option you selected:

helm uninstall osmo --namespace osmo --wait

# Option A
nvkind cluster delete --name osmo

# Option B
kind delete cluster --name osmo

Deleting the cluster removes all quickstart data, including its local persistent volumes and generated credentials.