Nutanix Blueprint – Self-Service Application Blueprints
Last updated: March 4, 2026
Table of Contents
Why I Started Using Blueprints
After getting AHV running and Prism Central deployed, I had a functional cluster. But spinning up VMs still meant clicking through the Prism Element UI each time — same OS image, same network, same CPU/memory settings, same cloud-init script — over and over.
I explored Terraform's Nutanix provider for a while, which works. But I kept running into situations where I needed repeatable Day 2 operations on top of the initial provisioning: scaling out a service tier, running a database restore, or updating a configuration without destroying and recreating VMs.
That's what Blueprints solve. A Blueprint in Nutanix is not just an infrastructure template — it is an application lifecycle definition.
What Is NCM Self-Service?
NCM Self-Service (previously called Nutanix Calm) is a component of Nutanix Cloud Manager, enabled via Prism Central. It provides:
Blueprint Designer — a visual and code-based tool for defining multi-VM application topologies
Self-Service Portal — end users can launch applications from approved blueprints without needing direct Prism access
Application Marketplace — a catalog of publishable blueprints
Runbook Automation — for operations independent of blueprint applications
NCM Self-Service requires Prism Central. It is a separate license from AOS/AHV, but it is available in Nutanix CE for exploration.
Blueprint Concepts and Terminology
Before building anything, I needed to understand the vocabulary. The terms map roughly to familiar concepts but have Nutanix-specific meanings.
Blueprint
The full application definition — services, profiles, variables, credentials, and actions
Service
One logical tier of the application (e.g., web server, DB server). A service corresponds to one or more VMs
Substrate
The infrastructure specification for a VM: provider (AHV, AWS, Azure, etc.), image, vCPUs, memory, disk, network
Profile
A deployment configuration variant. The same blueprint can have a "dev" profile (small VMs) and a "prod" profile (large VMs)
Variable
Runtime or design-time inputs. Can be simple strings, secrets (marked as hidden), or dynamic (fetched via script at runtime)
Credential
Stored username/password or SSH key used by Tasks to connect to VMs
Action
A sequence of Tasks that runs at a lifecycle event. Built-in: create, delete, start, stop. Custom: anything you define
Task
The individual unit of work within an Action: shell script, HTTP call, Ansible playbook, or another blueprint (sub-blueprint)
Application
A running instance deployed from a Blueprint
Blueprint Types
Single VM Blueprint
The simplest type — one Blueprint defines one VM. Best for:
Standalone developer machines
Single-tier tools (bastion hosts, monitoring agents, DNS servers)
Templates with pre-configured cloud-init
Multi-VM Application Blueprint
One Blueprint defines multiple Services, each with its own VMs. Services can have dependencies on each other, controlling deployment order. Best for:
Three-tier apps (load balancer, app servers, database)
Clustered services where you need N replicas of one tier
Any deployment where VMs need to communicate their IPs to each other post-provision
This is the type I use most — specifically for deploying a two-tier setup (one VM for a service + one VM running a Postgres database) in my home-lab projects.
Building a Single VM Blueprint
Here's the process I follow when creating a Single VM Blueprint in the Prism Central UI.
Step 1: Create the Blueprint
Navigate to: Prism Central → NCM Self-Service → Blueprints → Create Blueprint → Single VM
Step 2: Add a Substrate
A Substrate defines what the VM looks like. Key fields:
Cloud: AHV (or AWS/Azure if you have multi-cloud configured)
OS: Linux or Windows
Image: Select from images synced to your cluster's image library
vCPUs / Memory: Start conservative, tune via profiles
Disk: At least one disk (the boot image), optionally additional data disks
Network: Select your AHV network (VLAN)
Cloud-init example (pasted into the "Guest Customization" field of the Substrate):
The @@{variable_name}@@ syntax is Nutanix's macro substitution — variables are replaced at runtime.
Step 3: Configure Variables
SSH_PUBLIC_KEY
String
Injected into authorized_keys
vm_name_prefix
String
Used to construct the hostname
Step 4: Add an Install Action (optional for single VM)
Even in single VM blueprints, I add an extra Task in the create action to verify the VM came up properly:
Building a Multi-VM Blueprint
My personal use-case: a two-tier setup with a web service VM and a Postgres database VM.
Service Dependency
The DB service must provision before the app service, and the app service needs to know the DB VM's IP at provision time.
In Blueprint Designer:
Add Service
postgres-dbAdd Service
app-serviceDraw a dependency arrow from
app-service → postgres-db
This ensures postgres-db finishes its create action before app-service starts.
Cross-Service Variable Access
After postgres-db provisions, its VM IP is exposed via:
In the app-service install script, I reference this:
Application Profile Example
A profile named small might define:
postgres-db
2
4 GB
app-service
1
2 GB
A profile named standard might define:
postgres-db
4
8 GB
app-service
2
4 GB
At launch time, the user picks a profile. The blueprint deploys the same topology with different VM sizing. No blueprint duplication needed.
Variables and Credential Management
Variable Types
String
Plain text, visible in forms
Integer
Numeric input with optional min/max
Multi-line string
For large text like scripts or keys
Secret
Masked in UI and logs — use for passwords
Date/Time
Parsed datetime input
Data Source (HTTP/DB)
Fetched dynamically at runtime via an API call or script
Secret Variables and Credentials
There are two ways to handle sensitive values:
Secret Variables — defined in the blueprint, marked as secret. Good for values that change per deployment (like a DB password the user enters at launch)
Credentials — defined separately in the blueprint credential section. Used by Tasks that need to SSH into or WinRM into a VM. Credentials can be:
Username + Password
SSH Key (paste PEM contents, or reference Prism Central's stored keys)
I keep credentials as SSH keys wherever possible. For my home-lab, I store the private key content as a secret credential in the blueprint and inject the corresponding public key via cloud-init.
Dynamic Variables
A dynamic variable runs a script or HTTP call at launch time to populate the value. I use this for things like fetching the current version tag of an application from a GitLab API before deploying:
The output (print()) becomes the variable value.
Day 2 Actions
Day 2 Actions are the feature that differentiated Blueprints from simple VM templates for me. After a Blueprint is deployed, I can run additional Actions against the running application without redeploying.
Built-in Actions
These are predefined lifecycle actions triggered automatically:
Create — provisions all services in dependency order
Delete — deprovisions all services
Start — powers on services
Stop — gracefully powers off services
Custom Actions
Custom actions are manually triggered from the Application view. Examples:
Scale Out web tier:
DB Backup:
Application Update:
Action Variables
Custom actions can define their own input variables. When you trigger the action from the UI, Prism Central prompts you for the values. This lets you parameterize operations like "update to this specific version" without hardcoding.
Marketplace Publishing
Once a blueprint is stable and tested, I publish it to the Self-Service Marketplace so that I (or others on the same Prism Central) can launch it with a single click.
Steps to Publish
In Blueprint Designer, click Publish
Fill in: Name, Description, Version, Application Icon (optional)
Set the Marketplace Approval Mode:
Admin-Approved— requires an admin to approve before it appears in the catalog (useful for shared clusters)Self-Approved— appears immediately (fine for personal use)
Click Submit for Approval (or approve it directly if you're admin)
The published item appears in NCM Self-Service → Marketplace, where any authorized project member can click Get to launch an instance.
Blueprint DSL (calm-dsl)
Nutanix provides an official Python-based DSL for defining blueprints as code: calm-dsl.
This is how I prefer to manage blueprints — version-controlled in Git, not defined only in the UI.
Installation
Configuration prompts for your Prism Central address, port, and credentials, storing them in ~/.calm/config.ini.
Example Blueprint as Code
The specs/app-vm.yaml holds the AHV VM spec (network, vCPU, memory, disk configuration) as a YAML file, keeping the DSL file focused on behavior.
Push Blueprint to Prism Central
Common Mistakes I Made
1. Not setting a Readiness Probe If you skip the readiness probe, Tasks in the create action start running before the VM's SSH service is ready. Add a readiness probe with a few retries and a delay.
2. Circular Service Dependencies If Service A depends on B and B depends on A, the blueprint fails at launch. Map out dependencies before drawing arrows.
3. Secrets in Variable Values I once put a password directly in a String variable value (not Secret type) and it appeared in plain text in the Prism Central logs. Always use Secret type for any sensitive value.
4. Forgetting @@{calm_array_index}@@ for replicated services When a service has more than one replica, each VM needs a unique hostname. Use the @@{calm_array_index}@@ macro to differentiate:
5. Day 2 Actions don't run on the right node in replicated services For multi-replica services, be explicit about whether the action runs on one replica or all. This is controlled by the "Run on" setting in the Task — either replicas (all) or replicas (first).
Next Steps
Continue to the next article: Blueprint Syntax and Best Practices — a structured syntax reference for calm-dsl, macro substitution, task types, and the best practices I settled on after iterating through several blueprint versions.
Last updated