OVHcloud Provider
Read this when you are:
- choosing
provider: ovh; - validating a direct OVHcloud Public Cloud lease;
- changing
internal/providers/ovhor the guarded live smoke.
OVHcloud is a Linux-only SSH lease provider. Crabbox creates a Public Cloud instance, creates a per-lease OVH SSH key, records Crabbox ownership metadata in a local lease claim, waits for a public IPv4 address and SSH bootstrap readiness, and then uses the normal Crabbox SSH sync/run/stop/cleanup path.
OVHcloud is direct-only in this release. It does not run through the Cloudflare Worker broker, so the local CLI must have OVH credentials and direct cleanup remains the operator's responsibility.
#When To Use It
Use OVHcloud for simple Linux lease work when an OVH Public Cloud instance is the desired execution surface and direct local credentials are acceptable. Prefer AWS, Azure, GCP, or Hetzner when you need a brokered team path, coordinator-side credentials, or Crabbox cost accounting.
#Commands
crabbox doctor --provider ovh
crabbox warmup --provider ovh --class standard
crabbox run --provider ovh --type b3-8 -- pnpm test
crabbox ssh --provider ovh --id my-app
crabbox stop --provider ovh my-app
crabbox cleanup --provider ovh --dry-run
--id accepts the canonical lease id (cbx_...), the friendly slug, or the OVH instance id. --type is the exact OVH flavor name or id; there is no separate OVH flavor flag for the generic lease commands.
#Configuration
provider: ovh
target: linux
ovh:
endpoint: https://api.us.ovhcloud.com/1.0
projectId: "<public-cloud-project-id>"
region: BHS5
image: "Ubuntu 24.04"
flavor: b3-8
Config keys under ovh::
| Key | Maps to | Default | Notes |
|---|---|---|---|
endpoint | cfg.OVH.Endpoint | https://api.us.ovhcloud.com/1.0 | Must be an HTTPS OVH or OVHcloud API host. Endpoint aliases ovh-us, ovh-ca, and ovh-eu are accepted by the client. Repo config may not redirect an inherited endpoint. |
projectId | cfg.OVH.ProjectID | empty | Required for doctor, list, warmup, status, stop, and cleanup. |
region | cfg.OVH.Region | empty | Required when acquiring a new instance. Doctor verifies it is returned by the project when set. |
image | cfg.OVH.Image | Ubuntu 24.04 | Public active Debian or Ubuntu image name or exact id. Names must be unique; non-public images require an exact id. Other Linux distributions are rejected because the managed bootstrap currently uses Debian-family package and service conventions. Explicit values bypass the portable --os mapping guard. |
flavor | cfg.OVH.Flavor | b3-8 | Available Linux flavor name or exact id with remaining project quota. Names must be unique. --type overrides this value for new leases. |
Provider-specific flags:
--ovh-endpoint <url-or-alias>
--ovh-project-id <project-id>
--ovh-region <region>
--ovh-image <image-name-or-id>
--ovh-flavor <flavor-name-or-id>
Environment overrides:
OVH_ENDPOINT Override the OVH API endpoint
OVH_APPLICATION_KEY OVH application key
OVH_APPLICATION_SECRET OVH application credential secret
OVH_CONSUMER_KEY OVH consumer key
CRABBOX_OVH_PROJECT_ID Override the Public Cloud project id
CRABBOX_OVH_REGION Override the region
CRABBOX_OVH_IMAGE Override the image name or id
CRABBOX_OVH_FLAVOR Override the flavor name or id
Do not pass OVH credentials as command-line arguments. Keep them in the environment or in a local secret manager. Crabbox config stores only non-secret OVH settings.
These five non-secret settings use the shared typed configuration bindings. Empty YAML or environment strings preserve the previous value; nonempty strings retain whitespace, and explicitly empty flags still assign. Image explicitness records accepted input even when it equals the default. Regional endpoint aliases, machine-class mapping, and native credential handling remain provider-owned.
#Credential Scope
The provider signs requests with OVH application credentials and operates only inside the configured Public Cloud project. It calls the Public Cloud project APIs for regions, flavors, images, SSH keys, and instances, and calls /auth/time for request signing.
The credentials must be able to:
GET /auth/time
GET /cloud/project
GET /cloud/project/{projectId}/region
GET /cloud/project/{projectId}/flavor
GET /cloud/project/{projectId}/flavor/{flavorId}
GET /cloud/project/{projectId}/image
GET /cloud/project/{projectId}/image/{imageId}
GET /cloud/project/{projectId}/sshkey
GET /cloud/project/{projectId}/sshkey/{keyId}
POST /cloud/project/{projectId}/sshkey
DELETE /cloud/project/{projectId}/sshkey/{keyId}
GET /cloud/project/{projectId}/instance
GET /cloud/project/{projectId}/instance/{instanceId}
POST /cloud/project/{projectId}/instance
DELETE /cloud/project/{projectId}/instance/{instanceId}
If a live smoke fails with a permission error, keep the error output secret-safe and adjust the OVH credential grants before retrying. Do not broaden permissions inside scripts.
#Lifecycle
- Validate required project and region configuration.
- Resolve exact ids before names, reject ambiguous image or flavor names, and verify Debian/Ubuntu image status plus flavor availability and project quota before creating credentials.
- Generate a per-lease SSH key under the Crabbox testbox key directory.
- Create a matching OVH project SSH key.
- Create an instance with region, flavor, image, SSH key, and cloud-init
userData. - Wait for a public IPv4 address and Crabbox SSH bootstrap readiness.
- Record a local claim for the lease and run normal Crabbox sync/run/ssh workflows over SSH.
- Delete the instance and managed OVH SSH key on
stop;cleanupdeletes only resources with complete Crabbox OVH ownership metadata and a matching local claim.
Public-IP readiness uses a five-minute elapsed-time context budget for API lookups and retry sleeps, independently of the clock used for lease timestamps. Caller cancellation retains its cause. A completed ready result or permanent API error keeps precedence; a client timeout while the wait context is active remains a client error. When the readiness budget expires, the timeout diagnostic includes the latest completed transient error unless a later successful lookup without an address cleared it.
If instance creation returns an indeterminate error after a key or instance may exist, Crabbox records a recovery claim so crabbox stop --provider ovh <lease-or-slug> can retry cleanup instead of leaving a billed resource without its SSH key.
#Ownership And Cleanup
Heartbeat policy is stored in the local lease claim, not reconstructed from OVH instance labels or the current configuration. Ordinary touches preserve the recorded idle timeout; heartbeat --idle-timeout explicitly replaces it while the original creation-based TTL still caps expiry. Activity timestamps and timeout changes are committed together, so a fresh process observes the same policy after reuse.
Older versions persisted successful heartbeat overrides only in timeout labels, which can disagree with the claim's structured timeout field. Those recorded label values remain authoritative on upgrade: reads preserve them without a write, and the next authorized heartbeat or repository reuse atomically aligns both representations. A new explicit timeout override still takes precedence.
Plain status and list reads do not renew the claim. A ready probe also resolves without modifying local state, although status --wait can subsequently touch the lease while waiting. If another operation changes the claim during a touch, retry the command to resolve its current revision; the stale update is refused. Plain status includes the available public SSH address, configured user/port, and stored lease key for core's readiness probe. Without a public address it remains a metadata-only observation. Status resolution never admits a repository or renews its claim, even when a repository root is supplied.
Crabbox-owned OVH leases use a local claim with ownership metadata such as:
crabbox=true
created_by=crabbox
provider=ovh
lease=cbx_abcdef123456
slug=my-app
target=linux
state=ready
ovh_project=<public-cloud-project-id>
ovh_region=BHS5
ovh_ssh_key_id=<ovh-ssh-key-id>
ovh_ssh_key_owned=true
expires_at=<unix-seconds>
Release and cleanup require a complete ownership predicate: Crabbox marker, provider marker, lease id, slug, project identity, and a matching local claim. Instances with partial, foreign, or malformed Crabbox-like metadata are skipped or refused.
Direct mode has no coordinator alarm. Use:
crabbox list --provider ovh --json
crabbox cleanup --provider ovh --dry-run
crabbox cleanup --provider ovh
#Guarded Live Smoke
The repeatable live check is opt-in:
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=ovh scripts/live-smoke.sh
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=ovh scripts/live-ovh-smoke.sh
The top-level script dispatches to the provider-specific script. The provider-specific script builds bin/crabbox unless CRABBOX_BIN is set, reads OVH credentials and project settings from the environment, requires an empty Crabbox-owned OVH inventory, creates a small b3-8 instance by default, waits for ready status, runs echo ok, verifies list --json, stops the lease, runs dry-run cleanup, and verifies the Crabbox-owned inventory is empty afterward.
Optional smoke overrides:
CRABBOX_LIVE_OVH_ENDPOINT
CRABBOX_LIVE_OVH_PROJECT_ID
CRABBOX_LIVE_OVH_REGION
CRABBOX_LIVE_OVH_IMAGE
CRABBOX_LIVE_OVH_FLAVOR
Final classifications include:
classification=live_ovh_smoke_passed
classification=environment_blocked
classification=quota_blocked
classification=validation_failed
If cleanup fails, use the reported slug and local claim metadata to inspect the instance in crabbox list --provider ovh --json or the OVHcloud console.
#Capabilities
- SSH and Crabbox sync: yes.
- Tailscale: yes through the standard Linux cloud-init path when a direct Tailscale auth key is configured.
- Desktop / browser / code: not advertised in Phase 1.
- Cleanup: yes, claim-backed only.
- Coordinator: never; direct CLI only.
#Gotchas
ovhhas no aliases; use the canonical provider name.ovhis direct-only. Worker broker secrets and cost accounting do not cover these instances.--typemust be a valid OVH flavor name or id such asb3-8.- Portable
--oscurrently maps only the defaultubuntu:24.04flow unlessovh.image,CRABBOX_OVH_IMAGE, or--ovh-imagesets an explicit image. - OVH endpoint URLs are restricted to OVH or OVHcloud API hosts.
- Restrict SSH exposure through project/network policy where needed, and prefer short TTLs for live validation.