Nested ESXi inside an NSX VPC: the trunk-subnet design
Plain VPC subnets silently blackhole a nested ESXi host. Here’s why — and the trunk subnet + binding map design that makes nested labs work as an ordinary NSX VPC tenant, verified end to end.
Plain VPC subnets silently blackhole a nested ESXi host. Here’s why — and the trunk subnet + binding map design that makes nested labs work as an ordinary NSX VPC tenant, verified end to end.
Three nested-ESXi pods, byte-identical addressing — same subnets, same VLANs, same host IPs, even the same MACs — with zero reachability between them. How overlapping VPC CIDRs and deterministic subnet realization turn cookie-cutter environments into a first-class feature.
The whole isolated pod — namespace, trunk subnets, binding maps, two dual-NIC nested ESXi hosts with an ISO attached, SSH/HTTPS VIPs — as one VCF Automation blueprint, published to the catalog. Anatomy of the blueprint, the ordering it enforces, and the three things it can’t express.

VCF wants two pNICs per host. In a nested lab the second vNIC adds no physical redundancy — so why add it? Because bringup validation and uplink teaming expect it, and because the failover test tells you something real about the trunk. vmnic0 down, 0% loss, and the SSH session watching it never dropped.
How an interactive PowerShell script grew into a catalog-driven factory that stands up complete nested VCF 9.1 instances — hosts, bringup, supervisor, fleet components — from a single request form. The design rules that made it survivable, and the traps that shaped them.
esxihostdeploy.ps1 was 400 lines of ovftool and PowerCLI behind a menu. It became a cloud template, two vRO actions and two subscriptions — and the interesting part is deciding where each behaviour belongs. The full mapping, four non-obvious decisions, and the ‘yes’ that isn’t ’true’.
Stage 2 of the lab factory: a vRO workflow that turns an environment number into a complete VCF 9.1 deployment spec, runs the installer’s own validation, starts bringup and hands back a task id — because the request dies long before the eight-hour build does. Plus how the wrapper slips the two-hour leash.