Goal
One-click "Provision Host" from the UI on any cloud (GCP, AWS, Hetzner, …), using the same on-host bootstrap as bare-metal enrollment. Today auto-provisioning is GCP-only and takes a different (GCE-metadata) code path than enrollment.
Background / current state
There are two onboarding paths today:
| Path |
Providers |
Mechanism |
| Enrollment (universal) |
GCP, AWS, Hetzner, bare-metal |
provision-host.sh + curl .../api/agent/install | bash -s -- <token> → /api/agent/register |
| Auto-provision from UI (GCP-only) |
GCP |
backend/internal/provisioner/provisioner.go → GCE Instances.Insert + metadata injection |
The enrollment path is already provider-agnostic and is documented as the unified path (see docs/getting-started.md). The GCP auto-provisioner is a separate, GCP-specific code path (injects agent-token/tunnel-token via GCE metadata; the agent self-configures from the metadata server). No AWS/Hetzner/user-data/cloud-init provisioning code exists.
Proposed design
Make cloud auto-provision a thin wrapper around the same bootstrap the enrollment path runs:
- Control plane mints an enrollment token.
- Renders user-data =
provision-host.sh (install deps) + curl .../api/agent/install | bash -s -- <token>.
- Creates the VM on the chosen provider with that user-data (GCE
startup-script / EC2 user-data / Hetzner cloud-init).
- The host registers via
/api/agent/register exactly like a bare host — tunnel, host record, agent token, and GCS creds all flow through the existing register endpoint. No provider-specific code runs on the host.
Provider-specific code reduces to a thin interface:
type HostProvider interface {
CreateInstance(ctx context.Context, spec ProvisionSpec, userData string) (instanceID string, err error)
DeleteInstance(ctx context.Context, instanceID string) error
}
- GCP impl first (wraps the existing compute
Insert, minus the metadata/tunnel logic, plus startup-script).
- AWS impl = EC2
RunInstances with user-data.
- Hetzner impl = hcloud server create with
user_data (cloud-init).
Scope / tasks
Related
- Unified path documented in
docs/getting-started.md (option A).
- Follow-up: GitHub Action to build + push
ocm-agent + Firecracker kernel artifacts to the artifact bucket.
🤖 Generated with Claude Code
Goal
One-click "Provision Host" from the UI on any cloud (GCP, AWS, Hetzner, …), using the same on-host bootstrap as bare-metal enrollment. Today auto-provisioning is GCP-only and takes a different (GCE-metadata) code path than enrollment.
Background / current state
There are two onboarding paths today:
provision-host.sh+curl .../api/agent/install | bash -s -- <token>→/api/agent/registerbackend/internal/provisioner/provisioner.go→ GCEInstances.Insert+ metadata injectionThe enrollment path is already provider-agnostic and is documented as the unified path (see
docs/getting-started.md). The GCP auto-provisioner is a separate, GCP-specific code path (injectsagent-token/tunnel-tokenvia GCE metadata; the agent self-configures from the metadata server). No AWS/Hetzner/user-data/cloud-init provisioning code exists.Proposed design
Make cloud auto-provision a thin wrapper around the same bootstrap the enrollment path runs:
provision-host.sh(install deps) +curl .../api/agent/install | bash -s -- <token>.startup-script/ EC2 user-data / Hetzner cloud-init)./api/agent/registerexactly like a bare host — tunnel, host record, agent token, and GCS creds all flow through the existing register endpoint. No provider-specific code runs on the host.Provider-specific code reduces to a thin interface:
Insert, minus the metadata/tunnel logic, plusstartup-script).RunInstanceswith user-data.user_data(cloud-init).Scope / tasks
HostProviderinterface +ProvisionSpec(machine type/size, region/zone, image, nested-virt).scripts/provision-host.sh+ enrollment install).provisioner.goto: mint token → render user-data →provider.CreateInstance(...); drop the GCP-metadata path so GCP goes through/api/agent/registerlike every other host.HostProviderimpl (stock image +startup-script, or keepFC_SNAPSHOT_NAMEfast path).HostProviderimpl (EC2, nested-virt-capable instance types e.g.*.metal).HostProviderimpl (hcloud).heartbeat_checker.go)./registerGCS-creds hand-off works for AWS/Hetzner pulling the agent + kernel, or add an HTTP artifact source.Related
docs/getting-started.md(option A).ocm-agent+ Firecracker kernel artifacts to the artifact bucket.🤖 Generated with Claude Code