TL;DR · Key Takeaways
- A VMware Cloud Template is a YAML blueprint with three core sections: formatVersion, inputs, and resources.
- Inputs build the request form a user sees, and they are your first line of governance. Constrain them with enums and ranges.
- Resources declare the machines, networks, and storage to build, referencing the flavor, image, and network names from Part 11.
- You author two ways at once: a visual design canvas and a code editor, kept in sync, so you can drag or type.
- Templates are infrastructure as code. Version them in Git, then publish to the catalog. The YAML is the source of truth.
Everything in this series so far has been scaffolding for one file. A VMware Cloud Template is where it pays off: a few dozen lines of YAML that become a running, networked, governed deployment. The provider, the tenants, the projects, the zones, the mappings, all of it exists so that this file can be short. Learn to write one well and the platform finally does what it promised, which is to turn a request into infrastructure without a ticket in sight.
The anatomy of a template
A cloud template has three sections that matter. The top declares formatVersion and a name, the boilerplate that identifies the template. The inputs section defines what the user is asked when they request it, which becomes the form in the catalog. The resources section declares what gets built, referencing the flavor, image, and network names you set up as mappings and profiles. That is the whole shape: identify, ask, build.
| Section | What it does | Becomes |
|---|---|---|
| formatVersion + name | Identifies and versions the template | The blueprint’s identity |
| inputs | Declares what to ask the requester | The catalog request form |
| resources | Declares the machines, networks, storage | The deployment |
A real template, top to bottom
Here is a complete, small template that asks for a size and an environment, then builds a machine on an on-demand network. Notice how little is hard-coded: the flavor and image are names that the region’s mappings resolve, and the inputs carry constraints so the form cannot be used to request something silly.
formatVersion: 1
name: linux-app-server
inputs:
size:
type: string
title: Machine size
enum: [small, medium, large] # constrains the form
default: small
hostname:
type: string
title: Hostname
pattern: '^[a-z][a-z0-9-]{2,30}$' # validation, not trust
resources:
app_net:
type: Cloud.Network
properties:
networkType: outbound # on-demand, built by the network profile
app_vm:
type: Cloud.vSphere.Machine
properties:
flavor: '${input.size}' # resolved by the flavor mapping
image: ubuntu # resolved by the image mapping
name: '${input.hostname}'
networks:
- network: '${resource.app_net.id}'
Two things are doing quiet work here. The ${input.x} and ${resource.x.id} bindings wire the form to the build and the resources to each other, so the machine attaches to the very network this template created. And the enum and pattern on the inputs are governance: a user cannot request a size you did not bless or a hostname that breaks your naming, because the form will not let them. Constraints in the template beat policy documents nobody reads.
Inputs are your first governance
It is worth dwelling on inputs, because authors underuse them. Every input is both a question and a guardrail. An enum restricts choice to known-good values. A pattern validates format. A default makes the common case one click. Inputs can also be conditional, shown or required only when another input has a certain value, so the form stays simple until complexity is actually needed. The more intent you push into well-constrained inputs, the less you rely on approvals and clean-up later. A loose input is a support ticket waiting to happen.
inputs:
environment:
type: string
enum: [dev, prod]
default: dev
data_disk_gb:
type: integer
title: Data disk size (GB)
minimum: 10
maximum: 500 # a hard ceiling on what anyone can request
default: 50
# An input with a min, a max and a default is a guardrail and a convenience
# at the same time. Most governance problems are an unconstrained input.
Canvas and code, the same template
You do not have to choose between clicking and coding. VCF Automation gives you a visual design canvas and a code editor for the same template, kept in sync: drag a machine onto the canvas and the YAML appears; edit the YAML and the canvas updates. The canvas is good for sketching a shape and for people newer to the syntax; the code editor is where you do the precise work, the bindings, the constraints, the conditionals. Treat the YAML as the source of truth, because it is what you version and review, and use the canvas as a fast way to see and shape it.
Worked example
A single linux-app-server template with three inputs, size, hostname, and environment, can serve a whole organization. The size enum caps what anyone provisions, the hostname pattern enforces naming, and the environment input drives a constraint that lands dev requests on dev capacity and prod on prod. One file, maybe forty lines, replaces a request form, a provisioning runbook, and a naming policy, and because it references mapping names rather than real resources, the same forty lines deploy in every region you support. That is the leverage this layer gives you: the more correct the template, the less everything downstream has to do.
Composing bigger systems
One machine is the hello-world of cloud templates. Real systems are several resources that depend on each other, and the same file describes them all. A template can declare a web tier, an app tier, a database, and the network that joins them, and deploy the whole thing as one unit. The bindings you already saw, where a machine references a network’s id, are also how you express dependencies: because the app VM references the database’s address, the platform knows to build the database first. You rarely write explicit ordering. You write the references, and the dependency graph falls out of them.
The judgment call is how much to put in one template. Keep a tightly coupled system, an app and its private network, in one template so it deploys and tears down as a unit. Split things that have independent lifecycles, a shared database that outlives the apps using it, into their own template or an existing resource, so destroying one app does not take the database with it. The mistake is the mega-template that builds an entire environment in one file: it is impressive in a demo and miserable to change, because every edit risks everything. Small templates that compose beat one template that does everything, and they are far easier to review.
Gotcha
Bindings that point two resources at each other create a circular dependency the platform cannot order, and the deploy fails before it starts. If a template will not deploy and the error mentions dependencies, look for two resources that each reference the other, and break the loop by giving one of them a static value or an input instead of a reference. Most ordering failures are a cycle you can see once you go looking for it.
Iteration is where versioning earns its keep. A template in Git with a version is one you can change safely: edit, review, publish a new version, and roll back if it misbehaves, all without disturbing the deployments already running on the old version. A template edited live in the UI has none of that safety. Treat each published version as a release, and the catalog as something that consumes releases rather than works in progress. That discipline is what lets you improve a template that hundreds of deployments depend on without holding your breath each time.
Versioning and testing templates like code
Release discipline
A cloud template you are still editing is invisible to the catalog, because only released versions are published. That is a feature, not a nuisance: it means the version a tenant deploys is a deliberate, frozen artifact. The discipline that follows is to treat each release like a code release, with a version string that means something and a note on what changed, so that when a deployment behaves oddly you can tell which released version produced it. Editing in place and forgetting to release is the reason a fixed template keeps deploying the old, broken build.
Test before you publish
Validation in the editor proves the template parses, not that it deploys. Run an actual deployment of a new version in a non-production project before you release it to tenants, ideally in every region it claims to support, because the failures that matter, a missing image, an unmatched profile, a bad input default, only appear at provision time. A template that validates and fails to deploy is worse than one that fails to validate, because it fails in front of a user.
Inputs are guardrails, not just fields
Every input is a chance to constrain what a user can ask for. Replace free-form fields with enumerations, set sane defaults, and bound numeric ranges, so the template itself prevents the absurd request rather than relying on a policy to catch it later. An input that offers three sensible sizes is governance; an input that accepts any number is a support ticket waiting to happen.
A workstation template exposes size as an enumeration of small, medium and large with small as the default, region as a constrained choice, and disk as a bounded range rather than an open field. A user cannot request a 40-terabyte volume or an unknown size, because the template does not let them. The same item with free-form inputs would lean entirely on downstream policy and human review. Push the guardrails into the inputs and most bad requests become impossible rather than merely discouraged.
My Take
The template is the smallest, highest-leverage artifact in the whole platform, so invest in writing it well. My recommendation: keep templates small and composable rather than building one giant blueprint that does everything; push governance into constrained inputs instead of trusting requesters; reference mapping and profile names, never real resources, so a template stays portable across regions; and treat the YAML as code, versioned in Git and reviewed, with the canvas as a sketchpad rather than the system of record. Do that and a template becomes a durable asset that outlives the person who wrote it. The reward for getting these forty lines right is that the next thousand deployments need no attention at all.
Next we take this template and put it in front of users: tags and tag-based placement, then the Service Broker catalog. For the names this template resolves, revisit Part 11 on mappings and profiles. How big do your templates get before you split them? Tell me in the comments.
References
- Designing Cloud Templates in VCF Automation (Broadcom TechDocs)
- Documented VCF Automation Template Example (Broadcom TechDocs)
- VCF Automation Infrastructure as Code: Templates (VCF Blog)



