Dedicated-root metal
Lease whole machines to tenants with root, under tenant-controlled trust and node-tenant certificates, and take them back with a BMC-driven teardown.
Some tenants need the whole machine: their own kernel, their own OS image, root on the host. The
moment a tenant has root, nothing running on that machine can be trusted by the platform again: not
its agent, not its inventory, not its reports. A dedicated-root lease is designed around that. For
the lease, the machine's trust changes to tenant-controlled and the platform gives up its identity
on it. Afterwards, the machine comes back only through a teardown driven entirely from the BMC side.
Dedicated-root leases are a v0.5 feature of PLAN.md. They are implemented in metal
(metal/0003_tenant_root) and capacity (whole-node placement), and tested end to end against the
simulated site. The contract between the two modules is rows only; neither imports the other.
Set up a tenant-root pool
Whole-node leases are served only by pools that opt in with policy.tenantRoot. Give the pool a
firmware baseline too: the teardown verifies it, and fails without one.
await compute.api.pools.create(credential, {
tenantId: 'root',
siteId,
class: 'metal-dedicated',
policy: {
hardwareProfile: 'gpu-redfish',
tenantRoot: true,
firmwareBaseline: { bmc: '1.12.0', bios: '2.4.1', 'gpu-vbios': '96.00.5f' },
firmwareRemediation: 'reflash', // or 'quarantine', the default
firmwareImages: {
bios: { url: 'https://firmware.site-a/bios-2.4.1.bin', sha256: '<64 hex digits>' },
},
},
});Prop
Type
Offer the pool to the tenants who may lease from it, as with any pool (see pools). Nodes under tenant control add no capacity to the pool's rollups while they are leased.
Reserve a whole machine
The tenant creates a with binding: 'node' and names
the metal profile to deploy:
const reservation = await client.reservations.create({
tenantId: 'acme',
poolId,
devices: [{ class: 'gpu', count: 8 }],
duration: '7d',
binding: 'node',
node: { profileId: 'acme-root-os', profileVersion: 1 },
idempotencyKey: 'acme-root-2026-09',
});binding: 'node'needsnode.profileId, andnodeneedsbinding: 'node'(INVALID_INPUTotherwise). Always passprofileVersion: metal refuses to start a lease whose reservation names no version, publishesnode.tenant-root.refused, and leaves the nodeready.- A node binding cannot be
spot, and a pool withoutpolicy.tenantRootrefuses it. - Placement takes nodes that are
ready, not in maintenance, not cordoned, withplatformtrust and no live allocation in the window, whose healthy atoms coverdevices. Other NoSchedule reasons do not stop a lease, with one exception: a node tainteddedicated=<tenant>is leased only by that tenant (see taints). The same check guards the lease's commit and BookingRepair. The allocation books every bookable atom of the node, so nothing else can land on it.gangleases several such nodes on one topology value. - The profile resolves in the lessee's tenant: the lessee's own profile, or a public one. The image it deploys resolves in the machine owner's tenant, so the lessee's profile has to name a public (promoted) image.
- If metal has not finished deploying the node within 2 hours, the lease fails and is not placed again elsewhere.
- A bound lease bills
node.metal.hoursper lease-hour, plus the GPU meter for the GPUs that were healthy at the start of each hourly window. See billing and usage.
How a lease starts
- When the reservation reaches its start (
binding), capacity queues the node'smetalwork. - On a
readynode of a tenant-root pool, not in maintenance, metal records the lease, marks the machinetenant_root, sets its release wipe tosecure-eraseand its trust totenant-controlled, and starts a new identity generation, which revokes every platform certificate of the node before any tenant code runs. It then appliesdeploywith the lessee's profile and publishesnode.tenant-root.leased(allocation, reservation, lessee tenant, profile and version). - The deploy workflow runs in the lessee's tenant. When the installed OS joins, JoinService sees the
node's
tenant-controlledtrust and issues anode-tenantinstead of anodeone. - When the deploy completes, the node is
deployedwith the profile's role (usuallydedicated). Metal marks the allocation bound and queues capacity's reservation work, which moves the reservation toactive, and publishesnode.tenant-root.bound.
What the tenant gets, what the platform keeps
A node-tenant certificate runs a session as a node, but carries none of a platform node's
authority:
| Lessee | Platform | |
|---|---|---|
| Root on the OS, its disks and kernel | yes | no |
Session through the gateway, telemetry and leave | yes | |
| Secrets from the broker | never: the broker refuses node-tenant certificates | |
| Destructive commands | never: the gateway rejects them as tenant-controlled | |
| Results that count (wipe, diagnostics) | never: only platform identities attest | the platform ramdisk |
| BMC, power and boot device | no | yes, from the site agent |
| The teardown | no | always |
The attestation check accepts only ramdisk and node certificates by default, so even a wipe
result the lessee's OS signs with its own key for this very node is refused.
The lessee's inventory and health reports are advisory. While the node is tenant-controlled, an
inventory it sends is appended as a snapshot (node.inventory.changed with advisory: true) but
changes none of the node's devices, device health, labels, conditions, image cache or hardware key, and
its XIDs and host pressure are ignored. A GPU the lessee reports missing or unhealthy therefore stays
healthy and on the lease's bill. metal.exitTenantRoot ends the advisory period, so the first report
under platform trust applies for real. See
trust.
PLAN.md also disables in-band BMC access where the vendor supports it. That is not implemented yet, which is one reason the teardown rotates the BMC password.
The teardown
When capacity releases the allocation (a release, the end of its time or a lapsed lease), metal
moves the deployed node to releasing (node.tenant-root.ending) and runs
metal-tenant-root-release@1 instead of the ordinary release. Every step is driven from the site
agent or the control plane:
| # | Step | Why |
|---|---|---|
| 1 | power.setPower off | stop the tenant's OS |
| 2 | metal.fenceTenant | revoke the lessee's certificates first, so nothing left behind can sign for this node |
| 3 | metal.rotateBmcCredential | the lessee may have learned the BMC password; see BMC rotation |
| 4 | metal.ensureRamdisk | boot the platform ramdisk over PXE |
| 5 | disk.wipe secure-erase | an attested wipe of every disk |
| 6 | diag.dcgm level 1 | GPU reset and ECC check |
| 7 | metal.firmwareCheck | every component must match policy.firmwareBaseline |
| 8 | metal.exitTenantRoot | a new identity generation, trust back to platform, the lease cleared |
| 9 | power.setPower off | park the machine |
The cleanup step boot.cleanUp removes the boot entries. As with every release, the node reaches
ready only if the wipe's result is node-signed and every disk passed read-back. The v0.5 exit
criterion holds in the tests: a lease and its release yield a new identity generation.
Agentless pools (agent: 'none') run metal-tenant-root-release-oob@1 instead: power off, fence,
rotate, eject media, firmware check, exit. It has no wipe, so it reaches ready only with
policy.allowUnverifiedRelease.
When the teardown fails
Every failure quarantines the machine: the node is failed with failedFrom: 'releasing' and
maintenance on, and it stays tenant_root with tenant-controlled trust, because only a completed
teardown clears them.
- Firmware drift fails the check with
code: 'FIRMWARE_DRIFT', listing each drifted component. WithfirmwareRemediation: 'reflash'and an image for every drifted component, the site agent writes the images (bmc.firmware) and the check runs again; drift that survives the reflash still quarantines. - A rotation the BMC refuses fails the teardown, and the old credential stays current.
- A wipe not signed by a platform identity never reaches
ready. - A pool without
firmwareBaselinefails the check withINVALID_CONFIG.
metal.recover sends the node back to releasing, and since it is still tenant_root, the teardown
runs again from the start. The same holds for a lessee deploy that failed: recovering it runs the
tenant-root teardown, not the ordinary release. Maintenance stays on after recovery; see
failure and recovery.
When the lessee's tenant is deleted
When Better IAM deletes the lessee's tenant, compute's tenancy teardown ends its reservations through
capacity (capacityTenantDeleted), so each lease is released now and runs the tenant-root teardown above.
Metal's own tenantDeleted hook retires the machines the deleted tenant owns, not the platform machines it
leased. See tenancy.
Limits
- PLAN.md offers dedicated-root only on vetted hardware until TPM measured boot exists, since a tenant with root could otherwise persist below the OS in ways a firmware version check does not see.
- Reservation lifecycle, quotas and offerings work as for any reservation; see reservations.
Better Compute is created by Sean Filimon
Last updated
Deploying machines
Walkthroughs that deploy machines on an emulated QEMU/KVM site, install Ubuntu over virtual media, and run Talos on an agentless pool.
Clients
Every way to call Better Compute, from raw HTTP to the typed client, the CLI, MCP tools and the console, and the credentials each one carries.