Physical AI Infrastructure Setup And Resilient Scaling
NVIDIAOfficialCreated by NVIDIA Physical AI
- Skill
- Workflow
- Cloud and DevOps
- Apache-2.0
- Medium risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a comprehensive framework for deploying, scaling, and validating the infrastructure required for NVIDIA Physical AI synthetic data generation (SDG) workflows. It manages the lifecycle of Kubernetes clusters (MicroK8s or Azure AKS), OSMO orchestration, and inference backends (NIM Operator, NVCF, or Azure AI Foundry). The skill enforces strict preflight checks, reproducible configuration management, and systematic recovery procedures to ensure reliable workload execution.
What it does
- Provisions and configures Kubernetes clusters on MicroK8s or Azure AKS.
- Deploys and manages OSMO orchestration layers for workload submission.
- Sets up inference endpoints using NIM Operator, NVCF, or Azure AI Foundry.
- Executes mandatory preflight checks to validate infrastructure readiness.
- Provides structured recovery paths for failed workflow states or infrastructure issues.
- Ensures secure credential handling and environment-aware configuration.
When to use it
- When setting up a new Physical AI SDG environment from scratch.
- When scaling existing infrastructure to meet new workload demands.
- When validating the health and readiness of cluster, inference, or OSMO components.
- When troubleshooting and recovering from infrastructure or workflow deployment failures.
Advantages
- Standardizes infrastructure deployment across different cloud and local environments.
- Reduces configuration drift by using checked-in scripts and reproducible patterns.
- Improves reliability through mandatory preflight and verification gates.
- Provides a unified interface for complex multi-component stacks.
Usage examples
- “Set up resilient Physical AI infrastructure for VDA on Azure AKS with NIM Operator.”
- The agent will initiate the setup flow for Azure AKS, configure the necessary OSMO and NIM Operator components, run preflight checks, and prepare the environment for VDA workload submission.
- “My MicroK8s cluster for SDG is failing to schedule jobs; help me validate and recover.”
- The agent will guide you through the verification gates for the MicroK8s cluster, inspect OSMO pod status, check storage credentials, and identify the root cause of the scheduling failure.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/nvidia/physical-ai-infrastructure-setup-and-resilient-scaling/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip physical-ai-infrastructure-setup-and-resilient-scaling.zip -d .agents/skills
Documentation by NVIDIA Physical AI
Physical AI Infrastructure Setup And Resilient Scaling
Canonical skill for the Physical AI infrastructure stack. Use it to compose cluster, inference, OSMO, and workload stages into a reproducible Physical AI SDG environment, then keep the environment observable and recoverable.
Operating Rules
Read only the component references needed for the selected target. Do not load every component by default.
Keep the repo as the durable artifact. Fix checked-in config or scripts, then rerun. Do not recover a failed install with untracked one-off changes.
Run mutating cluster, OSMO, Helm, Terraform, or Azure operations through checked-in scripts when a script exists. Read-only diagnostics are allowed.
Stop at the first red gate. Fix the lowest owning layer in this order: config, script, then skill guidance.
Derive values from the environment when possible. Ask only for values that cannot be inferred, such as API keys, target choice, or quota tradeoffs.
Store secrets in
${REPO_ROOT}/.env. Cluster-derived values such as storage, database, Redis, and endpoint names come from Terraform outputs or platform queries, not.env.Preflight means no deployed state: no cluster API, Terraform outputs, Helm releases, OSMO pools, or workflow state. Those belong to deploy/verify gates.
Never print, echo, or paste raw keys into commands, YAML, logs, or transcripts. Prefer credential handles, Kubernetes
secretKeyRef, and runtime-only secret injection. Scan raw transcript exports withscripts/scan_transcript_secrets.pybefore sharing.Use absolute paths. Derive repo root with
git rev-parse --show-toplevel.
Component References
Each component lives inside this skill so the stack has one canonical trigger. Load the component reference only when the selected target needs that slice.
| Concern | Load | Assets |
|---|---|---|
| Stage matrix and old driver notes | components/driver/reference.md | None |
| MicroK8s cluster | components/cluster-microk8s/reference.md | components/cluster-microk8s/scripts/, components/cluster-microk8s/runtimeclass-nvidia-runc.yaml |
| Azure AKS cluster | components/cluster-azure/reference.md | components/cluster-azure/scripts/, components/cluster-azure/terraform/ |
| NIM Operator inference | components/inference-nim-operator/reference.md | components/inference-nim-operator/scripts/, components/inference-nim-operator/nims/ |
| NVCF inference | components/inference-nvcf/reference.md | components/inference-nvcf/scripts/ |
| Azure AI Foundry inference | components/inference-azure/reference.md | components/inference-azure/scripts/ |
| MicroK8s OSMO | components/osmo-k8s/reference.md | components/osmo-k8s/scripts/, upstream OSMO deploy scripts |
| Azure OSMO | components/osmo-azure/reference.md | components/osmo-azure/scripts/, upstream OSMO deploy scripts plus Azure TF outputs |
| Azure access setup | components/azure-access/reference.md | None |
| OSMO CLI and workflow operations | components/osmo-cli/reference.md | components/osmo-cli/scripts/, components/osmo-cli/references/, components/osmo-cli/agents/, components/osmo-cli/tests/ |
| OpenClaw Azure device login | components/openclaw-azure-login/reference.md | None |
OSMO CLI Support Files
The OSMO CLI component has second-level support files because its command and workflow surface is large. Load these directly only for the stated case.
| File | Read when |
|---|---|
components/osmo-cli/agents/workflow-expert.md | Spawning a workflow-generation or workflow-failure subagent. |
components/osmo-cli/agents/logs-reader.md | Spawning a log summarization subagent for OSMO workflow failures. |
components/osmo-cli/references/cli-commands.md | Exact OSMO CLI flags, payloads, or command syntax are needed. |
components/osmo-cli/references/workflow-spec.md | Workflow YAML schema, credentials, outputs, or provider fields are needed. |
components/osmo-cli/references/workflow-patterns.md | Multi-task, data dependency, Jinja, serial, or parallel workflow design is needed. |
components/osmo-cli/references/advanced-patterns.md | Checkpointing, retry/exit behavior, or node exclusion is needed. |
components/osmo-cli/tests/orchestrator-runtime-failure.md | Validating or debugging the OSMO orchestration review pattern. |
Target Selection
Pick exactly one option per stage. Stage 2 follows stage 1.
Kubernetes:
MicroK8sorAzureOSMO:
MicroK8s OSMOwhen Kubernetes is MicroK8s,Azure OSMOwhen Kubernetes is AzureInference:
NIM Operator,NVCF,Azure AI Foundry, orNoneWorkload: Video Data Augmentation, Defect Image Generation, NuRec Carline Adaptation, NRE, NCore, Asset Harvester, or custom workflow YAML
Reject invalid combinations before provisioning:
| Cluster | NIM Operator | NVCF | Azure AI Foundry |
|---|---|---|---|
| MicroK8s | yes | yes | no, Foundry requires Azure identities |
| Azure | yes | yes | yes |
For OpenClaw or any chat-only environment that cannot open a browser, read
components/openclaw-azure-login/reference.md before Azure prerequisites.
For any Azure target, read components/azure-access/reference.md before Azure
component preflights.
Setup Flow
Confirm target choices and workload compute requirements.
Load the selected component references.
Resolve prerequisites up front, including API keys, Azure access, caller CIDR, GPU quota, storage class, and OSMO login requirements.
Run
scripts/preflight.shfor every selected infrastructure component plus any OSMO CLI/workload preflight before provisioning; build the implementation plan from the results and stop on red preflight.Deploy Kubernetes first. Nothing else starts until the cluster gate is green.
Deploy OSMO and inference after Kubernetes. These can proceed in parallel once the cluster exists, but workload submission waits for both selected gates.
Submit the workload only after OSMO, storage credentials, compute pool, and selected inference endpoints are verified. For VDA, this includes
preflight_credentials.sh,pre_submit_guard.pywith resolved--setvalues, non-empty model-cache prefixes, and workflow-namespace endpoint smoke checks.Monitor through completion. On failed workflow state, inspect events and logs from
components/osmo-cli/reference.md; do not resubmit blindly.
Inference Discovery
Avoid over-deploying expensive endpoints.
Scan the chosen workflow spec and default values for endpoint references:
*.osmo-nims.svc.cluster.local,api.nvcf.nvidia.com/*,*.inference.ai.azure.com, or*.cognitiveservices.azure.com.Map each reference to the selected backend:
NIM Operator: service name must match a directory under
components/inference-nim-operator/nims/.NVCF: function URL or function ID must be supplied by the environment.
Azure AI Foundry: endpoint name must be deployed through
components/inference-azure/scripts/install.sh.
If the workflow needs a capability the selected backend lacks, stop and report the mismatch. Do not silently substitute another model.
Verification Gates
Each stage has its own Verify section in the component reference. These gates are mandatory:
| Stage | Gate |
|---|---|
| Kubernetes | Cluster API reachable, nodes Ready, GPU capacity advertised for GPU paths, and CPU+NVCF paths have runtimeclass/nvidia mapped to runc. |
| Inference | Every endpoint referenced by the workload is reachable. NIM readiness uses /v1/health/ready; NVCF and Foundry still need task-specific authenticated checks. |
| OSMO | OSMO pods Ready, pool ONLINE, port-forward watchdogs alive, storage credentials configured, and verify-hello workflow COMPLETED. |
| Workload | Selected workload pre-submit guards pass before submit. osmo workflow query <id> reports COMPLETED and every task is green. Failed terminal states require events and logs before retry. |
Resilient Scaling
Size the cluster from workload needs before provisioning. For Azure, check CPU and GPU quota for the selected VM families before
terraform apply.For NIM Operator, deploy only the NIMServices referenced by the workload. Each service pins GPU and model-cache storage for the lifetime of the cluster.
Keep OSMO storage URL schemes aligned with the active backend. Local MicroK8s uses MinIO, Azure uses Blob-backed configuration.
Treat Pending, Unknown, ImagePullBackOff, unbound PVCs, or 0 Ready replicas as layer failures. Investigate scheduling, storage, image credentials, and adjacent platform state before retrying the same command.
For long deploys or workflow watches, provide heartbeat updates with current state, elapsed time, last useful observation, and next check.
Workload Routing
Video Data Augmentation: use
skills/physical-ai-video-data-augmentation/SKILL.md.Defect Image Generation: use
skills/physical-ai-defect-image-generation/SKILL.md.NuRec carline adaptation: use
skills/carline-adaptation/SKILL.md.NRE, NCore, and Asset Harvester live in the canonical NuRec catalog listed in
skills/INDEX.md.Custom workload: submit the provided workflow YAML through OSMO after checking resource requests, image credentials, data credentials, and inference URLs.
Evaluation Prompts And Results
Positive trigger: "Set up resilient Physical AI infrastructure for VDA on Azure AKS with NIM Operator." Expected: use this skill.
Negative trigger: "Summarize recent OSMO workflow logs for this workflow ID." Expected: do not use this infrastructure setup skill unless the request also involves setup, scaling, validation, or recovery of the infrastructure stack.
Latest static review: 2026-05-26, description keywords match the expected routes above.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.0 KiB
- BENCHMARK.md6.3 KiB
- LICENSELicence file added by AutoGineer11.2 KiB
- SKILL.md10.9 KiB
- components/azure-access/reference.md3.0 KiB
- components/cluster-azure/.gitignore103 B
- components/cluster-azure/reference.md5.9 KiB
- components/cluster-azure/scripts/helmfile.yaml354 B
- components/cluster-azure/scripts/main.tf25.4 KiB
- components/cluster-azure/scripts/outputs.tf1.6 KiB
- components/cluster-azure/scripts/preflight.shScript7.9 KiB
- components/cluster-azure/scripts/setup.shScript4.1 KiB
- components/cluster-azure/scripts/storage-class-nfs.yaml2.3 KiB
- components/cluster-azure/scripts/system_node_capacity_test.shScript915 B
- components/cluster-azure/scripts/terraform.tfvars.example568 B
- components/cluster-azure/scripts/variables.tf2.6 KiB
- components/cluster-azure/scripts/versions.tf588 B
- components/cluster-azure/terraform/main.tf8.0 KiB
- components/cluster-azure/terraform/modules/README.md705 B
- components/cluster-azure/terraform/outputs.tf3.9 KiB
- components/cluster-azure/terraform/prerequisites/az-sub-init.shScript2.2 KiB
- components/cluster-azure/terraform/prerequisites/install-terraform.shScript1.8 KiB
- components/cluster-azure/terraform/prerequisites/register-azure-providers.shScript6.8 KiB
- components/cluster-azure/terraform/prerequisites/robotics-azure-resource-providers.txt336 B
- components/cluster-azure/terraform/terraform.tfvars.example7.6 KiB
- components/cluster-azure/terraform/variables.tf9.1 KiB
- components/cluster-azure/terraform/versions.tf779 B
- components/cluster-microk8s/reference.md1.8 KiB
- components/cluster-microk8s/runtimeclass-nvidia-runc.yaml223 B
- components/cluster-microk8s/scripts/preflight.shScript4.5 KiB
- components/driver/reference.md8.6 KiB
- components/inference-azure/reference.md2.6 KiB
- components/inference-azure/scripts/install.shScript5.9 KiB
- components/inference-azure/scripts/preflight.shScript5.5 KiB
- components/inference-nim-operator/nims/cosmos-predict/nimservice.yaml2.4 KiB
- components/inference-nim-operator/nims/cosmos-reason/nimservice.yaml1.1 KiB
- components/inference-nim-operator/nims/cosmos-transfer/nimservice.yaml1.1 KiB
- components/inference-nim-operator/nims/qwen-image-edit-nvpcb-ovsl2sl/nimservice.yaml2.5 KiB
- components/inference-nim-operator/nims/qwen-image-edit/nimservice.yaml1.2 KiB
- components/inference-nim-operator/nims/qwen25-14b/hf-download-job.yaml2.0 KiB
- components/inference-nim-operator/nims/qwen25-14b/nimservice.yaml1.9 KiB
- components/inference-nim-operator/nims/qwen25-14b/pvc.yaml892 B
- components/inference-nim-operator/nims/qwen3-235b/hf-download-job.yaml1.7 KiB
- components/inference-nim-operator/nims/qwen3-235b/nimservice.yaml1.7 KiB
- components/inference-nim-operator/nims/qwen3-235b/pvc.yaml704 B
- components/inference-nim-operator/nims/qwen3-vl/hf-download-job.yaml2.6 KiB
- components/inference-nim-operator/nims/qwen3-vl/nimservice.yaml4.7 KiB
- components/inference-nim-operator/nims/qwen3-vl/pvc.yaml964 B
- components/inference-nim-operator/reference.md5.5 KiB
- components/inference-nim-operator/scripts/install.shScript11.8 KiB
- components/inference-nim-operator/scripts/preflight.shScript3.0 KiB
- components/inference-nvcf/reference.md3.2 KiB
- components/inference-nvcf/scripts/preflight.shScript2.7 KiB
- components/openclaw-azure-login/reference.md2.8 KiB
- components/osmo-azure/reference.md4.4 KiB
- components/osmo-azure/scripts/preflight.shScript5.9 KiB
- components/osmo-cli/agents/logs-reader.md3.5 KiB
- components/osmo-cli/agents/workflow-expert.md4.0 KiB
- components/osmo-cli/reference.md42.1 KiB
- components/osmo-cli/references/advanced-patterns.md2.4 KiB
- components/osmo-cli/references/cli-commands.md14.6 KiB
- components/osmo-cli/references/workflow-patterns.md8.0 KiB
- components/osmo-cli/references/workflow-spec.md8.5 KiB
- components/osmo-cli/scripts/preflight.shScript2.4 KiB
- components/osmo-cli/tests/orchestrator-runtime-failure.md11.0 KiB
- components/osmo-k8s/reference.md2.5 KiB
- components/osmo-k8s/scripts/preflight.shScript2.8 KiB
- evals/evals.json2.9 KiB
- skill-card.md3.4 KiB
- skill.oms.sig21.3 KiB
components/cluster-azure/scripts/main.tf
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
###############################################################################
# NVIDIA Physical AI Azure Infrastructure
#
# AKS + GPU pool, PostgreSQL (private), Redis, Blob Storage,
# AI Foundry, Key Vault, Jumpbox, NAT Gateway, Log Analytics
#
# PostgreSQL and networking patterns from:
# https://github.com/NVIDIA/OSMO/tree/main/deployments/terraform/azure/example
###############################################################################
locals {
name = "${var.resource_prefix}-${var.environment}"
subnet_aks = cidrsubnet(var.vnet_address_space, 4, 1)
subnet_gpu = cidrsubnet(var.vnet_address_space, 4, 2)
subnet_db = cidrsubnet(var.vnet_address_space, 4, 3)
subnet_pe = cidrsubnet(var.vnet_address_space, 4, 4)
}
data "azurerm_client_config" "current" {}
resource "random_password" "pg" {
length = 32
special = false
}
resource "random_string" "suffix" {
length = 5
special = false
upper = false
}
# ── Resource Group ──────────────────────────────────────────────────────────
resource "azurerm_resource_group" "this" {
name = "rg-${local.name}"
location = var.location
tags = var.tags
}
# ── Virtual Network ─────────────────────────────────────────────────────────
resource "azurerm_virtual_network" "this" {
name = "vnet-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
address_space = [var.vnet_address_space]
tags = var.tags
}
resource "azurerm_subnet" "aks" {
name = "snet-aks"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [local.subnet_aks]
service_endpoints = ["Microsoft.Storage"] # storage account VNet access
}
resource "azurerm_subnet" "gpu" {
name = "snet-gpu"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [local.subnet_gpu]
service_endpoints = ["Microsoft.Storage"] # storage account VNet access
}
resource "azurerm_subnet" "database" {
name = "snet-database"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [local.subnet_db]
delegation {
name = "postgres-delegation"
service_delegation {
name = "Microsoft.DBforPostgreSQL/flexibleServers"
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
}
}
}
resource "azurerm_subnet" "pe" {
name = "snet-private-endpoints"
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [local.subnet_pe]
}
# ── NAT Gateway ─────────────────────────────────────────────────────────────
resource "azurerm_public_ip" "nat" {
name = "pip-nat-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
allocation_method = "Static"
sku = "Standard"
tags = var.tags
}
resource "azurerm_nat_gateway" "this" {
name = "nat-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
sku_name = "Standard"
tags = var.tags
}
resource "azurerm_nat_gateway_public_ip_association" "this" {
nat_gateway_id = azurerm_nat_gateway.this.id
public_ip_address_id = azurerm_public_ip.nat.id
}
resource "azurerm_subnet_nat_gateway_association" "aks" {
subnet_id = azurerm_subnet.aks.id
nat_gateway_id = azurerm_nat_gateway.this.id
}
resource "azurerm_subnet_nat_gateway_association" "gpu" {
subnet_id = azurerm_subnet.gpu.id
nat_gateway_id = azurerm_nat_gateway.this.id
}
# ── Network Security Groups ────────────────────────────────────────────────
resource "azurerm_network_security_group" "aks" {
name = "nsg-aks-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
security_rule {
name = "AllowHTTPS"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefixes = var.allowed_cidr
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "aks" {
subnet_id = azurerm_subnet.aks.id
network_security_group_id = azurerm_network_security_group.aks.id
}
resource "azurerm_network_security_group" "database" {
name = "nsg-database-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
security_rule {
name = "AllowPostgreSQL"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "5432"
source_address_prefixes = [local.subnet_aks, local.subnet_gpu]
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "database" {
subnet_id = azurerm_subnet.database.id
network_security_group_id = azurerm_network_security_group.database.id
}
# ── Log Analytics + Container Insights ──────────────────────────────────────
resource "azurerm_log_analytics_workspace" "this" {
name = "log-${local.name}-${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
sku = "PerGB2018"
retention_in_days = 30
tags = var.tags
}
resource "azurerm_log_analytics_solution" "container_insights" {
solution_name = "ContainerInsights"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
workspace_resource_id = azurerm_log_analytics_workspace.this.id
workspace_name = azurerm_log_analytics_workspace.this.name
plan {
publisher = "Microsoft"
product = "OMSGallery/ContainerInsights"
}
tags = var.tags
}
# ── AKS Cluster ─────────────────────────────────────────────────────────────
resource "azurerm_kubernetes_cluster" "this" {
name = "aks-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
dns_prefix = "aks-${local.name}"
kubernetes_version = var.kubernetes_version
private_cluster_enabled = false
api_server_access_profile {
authorized_ip_ranges = distinct(concat(var.allowed_cidr, [
"${azurerm_public_ip.nat.ip_address}/32", # NAT gateway (pod egress to public API)
]))
}
depends_on = [azurerm_subnet_nat_gateway_association.aks]
tags = var.tags
default_node_pool {
name = "system"
vm_size = var.system_vm_size
auto_scaling_enabled = true
min_count = 3
max_count = 6
vnet_subnet_id = azurerm_subnet.aks.id
os_disk_size_gb = 50
max_pods = 110
temporary_name_for_rotation = "systemtmp"
}
identity {
type = "SystemAssigned"
}
network_profile {
network_plugin = "azure"
load_balancer_sku = "standard"
service_cidr = "192.168.0.0/16"
dns_service_ip = "192.168.0.10"
}
oidc_issuer_enabled = true
workload_identity_enabled = true
lifecycle {
ignore_changes = [default_node_pool[0].node_count]
}
}
# ── GPU Node Pool ───────────────────────────────────────────────────────────
resource "azurerm_kubernetes_cluster_node_pool" "gpu" {
name = "gpu"
kubernetes_cluster_id = azurerm_kubernetes_cluster.this.id
vm_size = var.gpu_vm_size
vnet_subnet_id = azurerm_subnet.gpu.id
os_disk_size_gb = 256
priority = var.gpu_priority
eviction_policy = var.gpu_priority == "Spot" ? "Delete" : null
spot_max_price = var.gpu_priority == "Spot" ? -1 : null
auto_scaling_enabled = true
min_count = var.gpu_min
max_count = var.gpu_max
# Microsoft recommends skipping GPU driver installation in AKS
# and letting NVIDIA GPU Operator handle it.
#
# This way we can use default GPU Operator Helm chart.
# https://learn.microsoft.com/en-us/azure/aks/nvidia-gpu-operator#get-the-credentials-for-your-cluster
gpu_driver = "None"
node_taints = ["nvidia.com/gpu=present:NoSchedule"]
node_labels = {
"nvidia.com/gpu.present" = "true"
}
tags = var.tags
}
# ── PostgreSQL (private, delegated subnet) ──────────────────────────────────
resource "azurerm_private_dns_zone" "postgres" {
name = "${local.name}.postgres.database.azure.com"
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "postgres" {
name = "${local.name}-postgres-dns"
private_dns_zone_name = azurerm_private_dns_zone.postgres.name
virtual_network_id = azurerm_virtual_network.this.id
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_postgresql_flexible_server" "this" {
name = "psql-${local.name}-${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
version = var.pg_version
sku_name = var.pg_sku
storage_mb = var.pg_storage_mb
administrator_login = "postgres"
administrator_password = random_password.pg.result
zone = "1"
delegated_subnet_id = azurerm_subnet.database.id
private_dns_zone_id = azurerm_private_dns_zone.postgres.id
public_network_access_enabled = false
tags = var.tags
depends_on = [azurerm_private_dns_zone_virtual_network_link.postgres]
lifecycle {
ignore_changes = [zone]
}
}
resource "azurerm_postgresql_flexible_server_database" "osmo" {
name = "osmo"
server_id = azurerm_postgresql_flexible_server.this.id
collation = "en_US.utf8"
charset = "utf8"
}
# Osmo's backend drivers don't negotiate TLS with the Azure PG flex server — the
# supported config per Osmo's Azure TF reference is `require_secure_transport=off`
# inside the private VNet.
resource "azurerm_postgresql_flexible_server_configuration" "ssl_off" {
name = "require_secure_transport"
server_id = azurerm_postgresql_flexible_server.this.id
value = "off"
}
resource "azurerm_postgresql_flexible_server_configuration" "extensions" {
name = "azure.extensions"
server_id = azurerm_postgresql_flexible_server.this.id
value = "hstore,uuid-ossp,pg_stat_statements"
depends_on = [azurerm_postgresql_flexible_server_configuration.ssl_off]
}
# ── Redis Cache ─────────────────────────────────────────────────────────────
resource "azurerm_managed_redis" "this" {
name = "redis-${local.name}-${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
sku_name = "Balanced_B1"
tags = var.tags
default_database {
client_protocol = "Encrypted"
clustering_policy = "EnterpriseCluster"
eviction_policy = "VolatileLRU"
access_keys_authentication_enabled = true
}
}
resource "azurerm_private_dns_zone" "redis" {
name = "privatelink.redisenterprise.cache.azure.net"
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "redis" {
name = "${local.name}-redis-dns"
private_dns_zone_name = azurerm_private_dns_zone.redis.name
virtual_network_id = azurerm_virtual_network.this.id
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_endpoint" "redis" {
name = "pe-redis-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
subnet_id = azurerm_subnet.pe.id
tags = var.tags
private_service_connection {
name = "redis-connection"
private_connection_resource_id = azurerm_managed_redis.this.id
subresource_names = ["redisEnterprise"]
is_manual_connection = false
}
private_dns_zone_group {
name = "redis-dns-group"
private_dns_zone_ids = [azurerm_private_dns_zone.redis.id]
}
}
# ── Storage Account ─────────────────────────────────────────────────────────
resource "azurerm_storage_account" "this" {
name = "st${var.resource_prefix}${var.environment}${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
account_tier = "Standard"
account_replication_type = "LRS"
public_network_access_enabled = true # auth + allowed_cidr gate access; network_rules below further restrict by source IP
tags = var.tags
network_rules {
default_action = "Deny"
bypass = ["AzureServices"] # AKS pods access via Azure backbone
ip_rules = [for cidr in var.allowed_cidr : replace(cidr, "/32", "")] # local CLI access
virtual_network_subnet_ids = [azurerm_subnet.aks.id, azurerm_subnet.gpu.id]
}
}
resource "azurerm_storage_container" "osmo" {
name = "osmo"
storage_account_id = azurerm_storage_account.this.id
container_access_type = "private"
}
resource "azurerm_storage_container" "datasets" {
name = "datasets"
storage_account_id = azurerm_storage_account.this.id
container_access_type = "private"
}
# The OSMO CLI Azure data client authenticates with AAD for direct
# `osmo data` operations, so the deployer needs blob data-plane rights in
# addition to the storage key handed to the OSMO deployment.
resource "azurerm_role_assignment" "current_user_storage_blob_data_contributor" {
scope = azurerm_storage_account.this.id
role_definition_name = "Storage Blob Data Contributor"
principal_id = data.azurerm_client_config.current.object_id
}
# Private endpoint for blob SA — AKS pods resolve
# storionsc*.blob.core.windows.net → PE private IP via the linked DNS zone,
# so Osmo backend + workflow tasks never touch the public endpoint / ACL.
# (Subnet service-endpoint path works for plain SDK calls from AKS but Osmo's
# DATA-credential validator returns AuthorizationFailure on the same path;
# PE bypasses firewall evaluation entirely by Azure design.)
# Pattern mirrors the Redis PE above.
resource "azurerm_private_dns_zone" "blob" {
name = "privatelink.blob.core.windows.net"
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "blob" {
name = "${local.name}-blob-dns"
private_dns_zone_name = azurerm_private_dns_zone.blob.name
virtual_network_id = azurerm_virtual_network.this.id
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_endpoint" "blob" {
name = "pe-blob-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
subnet_id = azurerm_subnet.pe.id
tags = var.tags
private_service_connection {
name = "blob-connection"
private_connection_resource_id = azurerm_storage_account.this.id
subresource_names = ["blob"]
is_manual_connection = false
}
private_dns_zone_group {
name = "blob-dns-group"
private_dns_zone_ids = [azurerm_private_dns_zone.blob.id]
}
}
# ── Key Vault ───────────────────────────────────────────────────────────────
resource "azurerm_key_vault" "this" {
name = "kv-${local.name}-${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
purge_protection_enabled = false
rbac_authorization_enabled = true
tags = var.tags
}
resource "azurerm_role_assignment" "kv_admin" {
scope = azurerm_key_vault.this.id
role_definition_name = "Key Vault Administrator"
principal_id = data.azurerm_client_config.current.object_id
}
# NFS-backed Premium FileStorage SA hosting dynamic PVCs from
# `file.csi.azure.com` (see storage-class-nfs.yaml). Pre-created so TF owns
# the lifecycle end-to-end; `terraform destroy` removes it (and all shares
# inside). Without a pre-created SA the driver auto-provisions one with prefix
# `f<hex>` in whatever RG the StorageClass points at — that SA is outside TF
# state and blocks RG deletion.
# Driver default-account behavior:
# https://github.com/kubernetes-sigs/azurefile-csi-driver/blob/master/docs/driver-parameters.md
# NFS on Azure Files requires Premium + FileStorage:
# https://learn.microsoft.com/en-us/azure/storage/files/storage-files-how-to-mount-nfs-shares
resource "azurerm_storage_account" "nfs" {
name = "stnfs${var.resource_prefix}${var.environment}${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
account_tier = "Premium" # FileStorage requires Premium
account_kind = "FileStorage" # NFS shares require FileStorage kind
account_replication_type = "LRS"
public_network_access_enabled = false # NFS shares are VNet-only; no public plane
https_traffic_only_enabled = false # NFS does not use HTTPS; enabling blocks NFS mounts
tags = var.tags
network_rules {
default_action = "Deny"
bypass = ["AzureServices"]
virtual_network_subnet_ids = [azurerm_subnet.aks.id, azurerm_subnet.gpu.id]
}
}
# AKS CP identity roles so the Azure File CSI driver can:
# 1. Network Contributor on the VNet — add Microsoft.Storage service
# endpoint to the subnet (NFS shares are private-VNet-only).
# 2. Storage Account Contributor scoped to stnfs* — create file shares
# inside the pre-provisioned NFS SA via ARM. Scoped to this SA only; does
# NOT grant rights to create new SAs in the RG.
# 3. Network Contributor on each NSG — `subnets/write` (granted by #1) is
# not enough when the target subnet has an NSG attached: the ARM call
# validates `Microsoft.Network/networkSecurityGroups/join/action` on
# the linked NSG too, and that's a separate scope from the VNet. The
# file.csi.azure.com driver iterates ALL VNet subnets to add the
# Microsoft.Storage service endpoint when provisioning a PVC, so it
# needs join on every NSG attached to a sibling subnet, not just the
# one its own pods land in. Without these grants, PVC provisioning
# fails with `LinkedAuthorizationFailed: ...does not have permission
# to perform action(s) Microsoft.Network/networkSecurityGroups/
# join/action on the linked scope...`.
resource "azurerm_role_assignment" "aks_vnet_net_contrib" {
scope = azurerm_virtual_network.this.id
role_definition_name = "Network Contributor"
principal_id = azurerm_kubernetes_cluster.this.identity[0].principal_id
}
resource "azurerm_role_assignment" "aks_nsg_aks_net_contrib" {
scope = azurerm_network_security_group.aks.id
role_definition_name = "Network Contributor"
principal_id = azurerm_kubernetes_cluster.this.identity[0].principal_id
}
resource "azurerm_role_assignment" "aks_nsg_database_net_contrib" {
scope = azurerm_network_security_group.database.id
role_definition_name = "Network Contributor"
principal_id = azurerm_kubernetes_cluster.this.identity[0].principal_id
}
resource "azurerm_role_assignment" "aks_nfs_sa_contrib" {
scope = azurerm_storage_account.nfs.id
role_definition_name = "Storage Account Contributor"
principal_id = azurerm_kubernetes_cluster.this.identity[0].principal_id
}
# Private endpoint for NFS SA — NFS shares must route via PE when the SA has
# `public_network_access_enabled = false` (service-endpoint access is a
# restriction ON the public endpoint, not an alternative path, per
# https://learn.microsoft.com/en-us/azure/storage/files/storage-files-networking-overview
# "NFS file shares are accessible from the storage account's public endpoint
# if and only if [...] restricted to specific virtual networks using service
# endpoints"). With PNA=Disabled the public endpoint is gone entirely, so AKS
# nodes reach the NFS share via the `file` PE's private IP (resolved through
# the linked privatelink.file.core.windows.net DNS zone).
resource "azurerm_private_dns_zone" "file" {
name = "privatelink.file.core.windows.net"
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_dns_zone_virtual_network_link" "file" {
name = "${local.name}-file-dns"
private_dns_zone_name = azurerm_private_dns_zone.file.name
virtual_network_id = azurerm_virtual_network.this.id
resource_group_name = azurerm_resource_group.this.name
tags = var.tags
}
resource "azurerm_private_endpoint" "nfs" {
name = "pe-nfs-${local.name}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
subnet_id = azurerm_subnet.pe.id
tags = var.tags
private_service_connection {
name = "nfs-connection"
private_connection_resource_id = azurerm_storage_account.nfs.id
subresource_names = ["file"]
is_manual_connection = false
}
private_dns_zone_group {
name = "file-dns-group"
private_dns_zone_ids = [azurerm_private_dns_zone.file.id]
}
}
# ── AI Foundry ──────────────────────────────────────────────────────────────
resource "azurerm_cognitive_account" "foundry" {
name = "foundry-${local.name}-${random_string.suffix.result}"
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
kind = "AIServices"
sku_name = "S0"
custom_subdomain_name = "foundry-${local.name}-${random_string.suffix.result}"
project_management_enabled = true
tags = var.tags
identity {
type = "SystemAssigned"
}
}
resource "azurerm_cognitive_account_project" "default" {
name = "${var.resource_prefix}-project"
cognitive_account_id = azurerm_cognitive_account.foundry.id
location = azurerm_resource_group.this.location
identity {
type = "SystemAssigned"
}
}
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs an API key, Needs Node.js
The author says: Requires the selected component prerequisites, usually kubectl plus either MicroK8s or Azure CLI/Terraform, and OSMO or inference credentials for the chosen target.
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- NVIDIA Physical AI
- Publisher
- NVIDIA (Official)
- Source
- NVIDIA/skills · skills/physical-ai-infrastructure-setup-and-resilient-scaling · commit fce3cca
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE-APACHE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- openai/plugins
AutoGineer is not affiliated with or endorsed by NVIDIA Physical AI or NVIDIA.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download physical-ai-infrastructure-setup-and-resilient-scaling.zip