Handing the Trading Platform a Boundary described what the i26g Control Plane is given: a resource pool, a network zone, storage, and scoped credentials. Inside that boundary it creates everything the platform needs. This post is about how it does that without knowing, or caring, whose infrastructure it runs on.

Two Ways to Talk to Infrastructure
The control plane has to create VMs, networks, storage, and DNS records. There are two common ways to make that work across different providers:
| Approach | What it is | What it costs |
|---|---|---|
| A facade service | A separate application in front of the infrastructure, translating one API into each provider’s | Another service to run, secure, and keep available — and a new point of failure between the platform and what it runs on |
| Adapters used directly by the control plane | A published set of capabilities the control plane depends on, implemented by a small adapter per provider | Each provider needs an adapter, and each adapter has to meet the same contract |
A facade could also publish a contract and use adapters internally; the difference is whether i26g needs a separate intermediary to run. It does not. The control plane uses provider-specific adapters through a published contract, without a separate facade service to operate.
The Capabilities
The interface covers only what the control plane needs. Each capability says what can be declared, what values come back, and which operations the adapter supports:
| Capability | Declared | Returned values | Operations |
|---|---|---|---|
| VM | Size, operating system, cloud-init, network, disks | Identifier, address | Query power state; start; stop |
| Network | Name, address range within the zone | Identifier, gateway, available addresses | — |
| Storage | Size, attached VM, within the supplied storage | Volume identifier | — |
| DNS | Name, record type, value, within a delegated zone | Record identifier | — |
| Snapshot and backup | VM or volume, schedule | Snapshot identifiers | Restore a snapshot |
| Inventory | — | — | List what exists in the boundary, and its state |
When DNS management is enabled, the boundary includes a delegated zone, such as trading.example.com. The control plane manages records only within that zone.
Modules and Operations
An adapter has two parts.
Declared resources are OpenTofu modules with fixed variables and outputs: i26g-vm, i26g-network, i26g-storage, i26g-dns, and i26g-snapshot. The control plane writes the desired state into those modules and applies it; the outputs are the returned values in the table above. Every provider gets its own implementation of the same modules — for example a hypervisor such as Proxmox for VMs, networks, and storage on your own hardware, or a VPS or cloud provider for rented machines. DNS can come from a local DNS server, from the VPS or cloud provider, or from a separate DNS service.
Queries and actions are adapter operations. Some things are not desired state: what is running right now, whether a VM is powered on, or restoring a snapshot. OpenTofu outputs expose values, not behaviour, so each adapter also provides a small, fixed set of operations — inventory, power state, start, stop, and restore — that the control plane calls directly against the provider’s API, with the same scoped credentials.
The modules manage resource configuration; explicit start and stop requests belong to adapter operations. After an operation such as a restore, the control plane refreshes state and generates a new plan before applying further changes.
Which implementation sits behind each capability is part of the boundary you hand over: you declare which adapter provides it, and the control plane checks that declaration at startup, alongside the resources the infrastructure contract requires. A new provider that fits the interface needs a new adapter, not a change to the control plane.
Where the Adapters Come From
The interface and its conformance tests live with the i26g Control Plane, because the control plane is what depends on them. The adapters are delivered as part of i26g too, as the i26g Infrastructure Adapters, but not built into the control plane: they are released together as a versioned adapter set, tested against each control plane release. Anyone can still write another adapter; passing the conformance tests is what makes it valid.
They reach the control plane through the boundary you hand over:
- You pin the set. The boundary declaration names the adapter-set version — and which adapter provides each capability — from a Git tag, a registry, or a local mirror for setups without internet access.
- Its dependencies are pinned with it. An adapter set uses OpenTofu providers and sometimes other modules. It ships with an OpenTofu dependency lock file, which fixes the provider versions and their checksums, and includes any modules it uses rather than fetching them remotely, since the lock file does not cover remote modules.
- The control plane checks it. At startup it fetches the pinned set, verifies its integrity, installs providers only as recorded in the lock file, and confirms that each adapter declares a supported interface version. If any check fails, startup stops.
- You decide on upgrades. The control plane can notice a newer set and propose the upgrade, but changing the pinned version is your change to make.
Releasing adapters separately lets adapter fixes and third-party implementations reach you without requiring a control plane release. A tested, versioned set preserves compatibility while letting you control upgrades.
Required and Optional
Providers differ. Proxmox networks work differently from a cloud provider’s; snapshots are instant on one platform and slow on another. An interface that demands everything every provider can do would fit none of them.
So the capabilities are split. The boundary already supplies a network zone and storage; the required capabilities are what the control plane needs to use them: creating VMs, creating a network within the zone, creating volumes within the supplied storage, and listing what exists. Without those, the platform cannot run.
The optional capabilities are detected and used when an adapter provides them. When it does not, the design falls back to something simpler:
- No snapshots: backups are taken at file level inside the VMs instead, to a backup destination declared in the boundary, and restored through a documented file-level recovery procedure.
- No DNS: services find each other by the addresses inventory reports, and features that need a public name are not enabled.
- No additional networks: all VMs share the one network in the zone.
Proving an Adapter Works
“Runs on any infrastructure” is only true if every adapter meets the same contract. Each one has to pass the same conformance tests: exercise each required capability and each optional capability the adapter declares — creating, querying, changing, and deleting resources, and calling each operation — and check that the results match what the interface promises.
The interface is versioned, and each adapter declares which version it implements. At startup, the control plane rejects adapters that declare an unsupported interface version. Older interface versions can stay supported for a while, so an interface change does not force every adapter to upgrade at once.
What You Get
You choose the infrastructure and the adapters. The control plane gets exactly the capabilities it needs, through an interface that is small enough to implement for a new provider and strict enough to trust. The adapter code and the providers that act on your infrastructure are the versions you pinned. And there is no extra service to keep alive — only the control plane, your infrastructure, and the contract between them.
Do your infrastructure adapters run inside the platform, or behind a separate service? Leave a comment below, or reach out through another channel if you would rather keep the conversation private. Follow the RSS feed for more.