Configuration
You run one process per OVH region, and you configure it with command-line flags plus the OS_* OpenStack credentials in the environment. You give it three things: a quota of capacity it may provision for your fleet (the offerings), a base image plus the OpenStack user to create instances, and the addresses it listens on. Correctness concerns like retry-safe creates and transition timeouts are handled for you and need no tuning.
This page is the flag reference, the offerings schema, the backend modes, and the create-then-bootstrap contract your image must satisfy. For the OpenStack user the flags imply see Credentials; for how price is sourced see Pricing.
Flags
| Flag | Default | Meaning |
|---|---|---|
--addr | :9000 | gRPC listen address (CapacityProvider + health + reflection). |
--provider | ovh-public | Provider/region label stamped on every HostRef (e.g. ovh-public-GRA). |
--ovh-backend | auto | ovh | fake | auto. auto = ovh when --region is set, else fake. See Backend modes. |
--region | (empty) | OVH/OpenStack region (e.g. GRA, SBG, BHS). Required for the ovh backend; selects the OpenStack service endpoint. |
--offerings | (built-in) | Path to a JSON offerings file. Omit to use a built-in mix sized by --seed-count. |
--seed-count | 32 | Number of Speculative slots in the default offerings (ignored when --offerings is set). |
--region-a | <region>/GRA | First region for the default offerings. |
--region-b | <region>/SBG | Second region for the default offerings. Defaults to --region when set, else SBG. The real backend rejects offerings outside --region, so this only spreads regions on the fake backend. |
--state | (empty) | Durable state file. Empty = in-memory only (state is lost on restart). |
--image | (empty) | Base image id (UUID) for server create. Required for the ovh backend. |
--key-name | (empty) | OpenStack keypair name injected at create, so the provider can SSH in. |
--network | Ext-Net | OpenStack network name or UUID to attach. Ext-Net is OVH’s public network, so instances get a public IPv4 by default (used for SSH bootstrap delivery). For hardened deploys, attach a private network the provider can reach instead, and front it appropriately — see Security → network exposure. Empty = project default. |
--ssh-key | (empty) | SSH private key path for Configure/Drain delivery. Without it, Configure cannot deliver the bootstrap blob. |
--ssh-user | ubuntu | SSH user for Configure/Drain delivery (the base image’s default cloud user). |
--bootstrap-hook | /opt/bigfleet/bootstrap | Image path that consumes the delivered bootstrap blob and joins the cluster. See the image contract. |
--base-user-data | (empty) | Path to the generic, pre-binding cloud-init baked into user_data at create. |
--eur-usd | 1.08 | EUR→USD conversion rate applied to OVH’s EUR prices. See Pricing. |
--price-refresh | 45m | Interval for the background refresh of live hourly prices from the OVH order catalog (0 = off; prices then stay on the dated seed table). The catalog is never fetched on the List/Get hot path. |
--price-subsidiary | FR | OVH subsidiary whose public order catalog supplies live prices. Must be a EUR subsidiary (FR, DE, IE, ES, IT, NL, PT, FI, …) since --eur-usd assumes EUR; a non-EUR catalog is rejected. See Pricing. |
--flavor-price | (empty) | Comma list of flavor=USD/hour price overrides (win over live + seed prices) for flavors the catalog omits or with a negotiated rate (e.g. b2-7=0.03). The provider refuses to start if an offered flavor has neither a seed-table entry nor an override. |
--reconcile-interval | 2m | Background OpenStack→inventory reconcile interval (0 = off). |
--metrics-addr | :9090 | Address for /metrics, /healthz, /readyz. Empty = disabled. |
--reflection | true | Register gRPC server reflection (for grpcurl/debugging). |
--tls-cert | (empty) | Server certificate (PEM). With --tls-key, enables TLS. |
--tls-key | (empty) | Server private key (PEM). |
--tls-ca | (empty) | Client CA bundle (PEM). Enables mTLS (requires + verifies client certs). |
The OpenStack credentials are not flags — they are read from the standard
OS_* environment (OS_AUTH_URL, OS_USERNAME, OS_PASSWORD, OS_PROJECT_ID,
OS_USER_DOMAIN_NAME, OS_PROJECT_DOMAIN_NAME, OS_IDENTITY_API_VERSION=3), so
they arrive from a mounted Secret rather than a process argument. See
Credentials.
A minimal production invocation (OS_* sourced from the environment):
./bin/ovhcloud \ --provider ovh-public-GRA \ --region GRA \ --image <BASE_IMAGE_UUID> \ --key-name bigfleet-ovh \ --ssh-key /etc/bigfleet/ssh/id_ed25519 \ --offerings /etc/bigfleet/offerings.json \ --state /var/lib/bigfleet-ovhcloud/state.json \ --eur-usd 1.08 \ --tls-cert server.pem --tls-key server-key.pem --tls-ca client-ca.pemBackend modes
--ovh-backend selects the substrate client:
ovh— the real OVH Public Cloud client backed bygophercloud/v2. Requires--region,--image, and OS_* credentials; startup fails without them. This is what creates real instances and delivers real SSH bootstrap.fake— an in-memory simulator. No OVH account, credentials, or network needed; no real instances are created. Used for dev and the credential-free conformance run. Selecting it logs a loud warning so it is never mistaken for production.auto(default) — resolves toovhwhen--regionis set, otherwisefake.
So a bare ./bin/ovhcloud (no region) refuses to start — the fake is
testing/conformance only and must be requested with --use-fake-backend (which is
how make conformance-ovhcloud runs credential-free). Setting --region (and
OS_* creds) selects the real backend.
Offerings
An offering is one shape of capacity the provider is allowed to provision: a
flavor, in a region, up to count slots. Each open slot is a Speculative
Machine the shard can actuate (the cloud analogue of a free pool). The
offerings are the provider’s entire quota — it will never create a flavor/region
combination you did not list.
Pass a JSON file with --offerings. The file is a JSON array of objects:
| Field | Type | Required | Meaning |
|---|---|---|---|
flavor | string | yes | OVH flavor name, e.g. b2-7, c2-15, r2-30. |
region | string | yes | OVH region, e.g. GRA. Regionless offerings are rejected at startup (the provider is multi-region). |
capacity_type | string | no | on_demand (default) is the only accepted value. OVH Public Cloud is on-demand only, so spot, reserved, and bare_metal are all rejected at startup (bare metal is the separate Dedicated Servers substrate, not this provider). |
count | int | yes | Number of Speculative slots this offering provides. |
resources | map[string]string | no | The per-replica request shape the offering serves (the Machine.resources). Distinct from allocatable, which is derived from the flavor. |
labels | map[string]string | no | Extra labels carried on the slot. GPU families (t1/t2/a10/l4/l40s) also get an automatic bigfleet.io/accelerator label. |
Example offerings.json:
[ { "flavor": "b2-7", "region": "GRA", "capacity_type": "on_demand", "count": 8, "resources": { "cpu": "1", "memory": "2Gi" } }, { "flavor": "c2-15", "region": "SBG", "capacity_type": "on_demand", "count": 16, "resources": { "cpu": "2", "memory": "4Gi" } }, { "flavor": "r2-30", "region": "BHS", "capacity_type": "on_demand", "count": 4, "resources": { "cpu": "2", "memory": "8Gi" }, "labels": { "team": "memory-heavy" } }]If you omit --offerings, the provider synthesizes a representative mix of four
flavors distributing --seed-count slots evenly. That default is for dev and
conformance; real deployments supply --offerings.
Shrinking an offering (or removing it) does not delete live instances: a tagged, running instance keeps owning its slot, and any tagged instance with no matching offering is surfaced as Idle under its machine id rather than being lost.
Allocatable (flavor capacity)
resources (above) is the per-replica request shape an offering serves;
allocatable is the flavor’s real hardware capacity (cpu, memory), which
the engine compares against demand (density = floor(allocatable / resources)).
You never set allocatable — the provider derives it from the flavor.
It is resolved authoritatively from OpenStack: at startup the provider reads
each offered flavor’s vCPUs and RAM from the Nova flavors API and caches them. A
pinned fallback table of common OVH flavors (b2/c2/r2/c3/r3/b3/d2/GPU) seeds
the cache, so the fake backend, credential-free conformance, and a flavors-API
outage all still produce correct allocatable. A flavor that is neither
offered-and-resolved nor pinned yields no allocatable, which the engine treats
as allocatable == resources.
Create then bootstrap
The provider deliberately splits create from cluster join, because
OpenStack user_data is consumed by cloud-init only at first boot but a slot’s
target cluster is only known when the shard binds it. The lifecycle:
- Create →
servers.Create. Boots the instance from--imagewith--base-user-dataas cloud-init (plus an injected SSH host key), on the chosen network, with the BigFleet metadata (bigfleet-managed,bigfleet-machine-id,bigfleet-host-key-fp). The operation id makes the server name stable, so a retried Create maps to the same instance instead of creating a second one. Create blocks until the instance is actuallyACTIVEbefore returning Idle, so the immediately following Configure never races a still-building host. - Configure → SSH. Delivers the opaque
bootstrap_blobto the node over SSH (--ssh-key/--ssh-user), runs the image’s hook at--bootstrap-hook, then recordsbigfleet-cluster=<id>in metadata. OpenStackuser_datacannot re-bootstrap a running instance, so SSH is the delivery channel — the analogue of AWS SSM. We wait for the hook to succeed, so a failed bootstrap surfaces asFAILED. - Drain → SSH. Cordons and drains the kubelet (
kubectl cordon/drain, honouringgrace_period_seconds), then clears the cluster metadata — leaving the instance running but unbound (Idle).clusterandshard_metadataare cleared. - Delete →
servers.Delete. Deletes the instance; the slot returns to Speculative (host cleared).
The image hook contract
Your base image must satisfy two things:
- Authorise the injected keypair. The provider connects as
--ssh-user(defaultubuntu) using--ssh-key; the matching public key is injected at create via the OpenStack keypair named in--key-name. (You can also bake the public key in via--base-user-datacloud-init.) - Ship the bootstrap hook at
--bootstrap-hook(default/opt/bigfleet/bootstrap). On Configure the provider writes the decoded bootstrap blob to<hook>.bloband runssudo <hook> <cluster-id>; the hook joins the node to the cluster and must exit non-zero on failure (so a broken join becomesFAILED, not a falsely-Idle node). The blob is opaque — the hook consumes it verbatim. The blob carries the cluster join secrets, so the provider removes<hook>.blobfrom the node as soon as the hook returns (via a shelltrapthat fires on any exit, success or failure) — the secret never lingers on disk. Your hook should consume the blob synchronously (read it during its run), not assume it persists afterward.
Reachability for SSH delivery. Configure/Drain SSH to the instance’s reachable IPv4 — a floating address if the instance has one, else its fixed (private) address. With the default public
Ext-Netthat’s a public IP; with a private-only network the provider’s pod must be able to route to the fixed IP, or Configure/Drain fail with “no reachable IPv4”. See Security → network exposure.
If you run without --ssh-key, Configure cannot deliver the blob and the machine
ends up FAILED; Drain degrades to clearing the binding metadata only. For a real
deployment, always set --ssh-key and --key-name.