Providers

How a workstation is placed on a backend: automatic placement, the lima, GCP, Azure and AWS providers, and their config knobs.

A provider is the backend that actually runs a Workstation: a local VM (lima on macOS, qemu on Linux) or a cloud VM (GCP, Azure, AWS). You rarely name one directly: you state requirements and let automatic placement (capability discovery) decide where the workstation runs.

Choosing a provider

  • Automatic placement (default). Omit any provider hint and the scheduler places the workstation on a backend that satisfies its spec.requirements.
  • Pin a provider. spec.provider: gcp (or --provider gcp on create workstation) is shorthand for adding a provider:gcp requirement.
rl workstation create my-box                 # discovery picks a backend
rl workstation create my-box --provider gcp  # pin GCP

The selected backend is reported at status.provider.

Per-provider machine tuning goes in spec.providerConfig, an opaque block read from the Workstation spec only (it is not merged from config layers). Its shape is provider-specific, described below.

An unsupported OS fails loudly, and says what is supported

Each provider carries its own list of distribution + version pairs, given per provider below. Naming a pair a provider does not carry — or leaving distribution or version out on a cloud provider — fails the workstation with a message on status.message that lists the supported pairs, rather than silently booting some default image. The same applies when you ask for an architecture an image has no build for (an Arm machine type with an amd64-only image, say).

lima (local, macOS)

Lima is the local provider on macOS (qemu is the Linux equivalent). It runs a local Linux VM under the platform hypervisor and needs limactl on PATH, bundled with the macOS native app. The in-VM agent is downloaded over HTTP at boot, like every provider; nothing is copied in over a mount.

providerConfig knobs (all optional, an empty config is sized to the host: all CPUs, half its RAM, half its free disk):

KeyTypeDescription
cpusintvCPU count. Default: all host CPUs.
memoryintRAM in GiB. Default: half host RAM.
diskintBoot disk in GiB. Default: half host free disk.
archstringGuest architecture. Default: the host architecture.
apiVersion: workstations.ringleader.dev/v1
kind: Workstation
metadata:
  name: local-box
  namespace: local
spec:
  provider: lima
  providerConfig:
    cpus: 4
    memory: 8
    disk: 60

GCP (cloud)

The GCP provider creates a Compute Engine VM. It authenticates through a CloudIdentity in the workstation’s namespace, which brokers the short-lived credentials — via per-organization federation, an impersonation chain, or the control plane’s own default identity. Set that up first; see the CloudIdentity reference for the credential paths, and cloud onboarding for what to configure in your account.

Machine and disk knobs live under providerConfig.gcp:

KeyTypeDescription
projectstringRequired. GCP project ID. Usually forced by the CloudIdentity’s overrideProviderConfig.
zonestringRequired. e.g. us-central1-a. Usually forced by the CloudIdentity.
machineTypestringMachine type. Default e2-medium; e.g. n2-standard-4. Arm families (t2a, c4a, n4a, …) require an arm64 image.
diskGiBintBoot disk size (grows in place on increase). Default ~40 GiB.
diskTypestringe.g. pd-balanced (default), pd-ssd; hyperdisk-only families default to hyperdisk-balanced. A family/type mismatch fails loudly.
networkstringVPC network name. Default default.
subnetworkstringSubnetwork name, or a full self-link. Required if network is a custom-mode VPC.
networkTags[]stringGCE network tags (firewall targeting).
assignPublicIpboolGive the VM an external IP. Default true.
enableNestedVirtualizationboolEnable nested virtualization on the VM. Default false.
labelsmapGCE instance labels.
metadatamapExtra GCE instance metadata.

The OS image is the ordinary config-layer image field (distribution + version) — debian 12/13, or ubuntu 22.04/24.04/26.04, each resolved to the matching Google-published image family for the machine type’s architecture:

apiVersion: workstations.ringleader.dev/v1
kind: Workstation
metadata:
  name: cloud-box
  namespace: dev
  labels:
    cloud: gcp
spec:
  provider: gcp
  image:
    distribution: debian
    version: "13"
  providerConfig:
    gcp:
      machineType: e2-standard-4
      diskGiB: 100

project and zone are typically supplied by the CloudIdentity’s overrideProviderConfig, so the workstation only needs machineType.

Authorized keys, not instance metadata

The in-VM agent owns the workstation’s authorized_keys on every provider. GCP does not write ssh-keys instance metadata. SSH access is driven entirely by ownership and Grants.

Reachability

A GCP workstation gets an external IP by default. It is still not reachable until a firewall rule allows TCP 22 — a custom VPC has none, and GCP denies ingress by default. rl shell dials the workstation directly on port 22; there is no bastion and no tunnel, so a workstation with egress but no inbound rule finishes setting up, reports Ready, and cannot be opened. See reaching your workstations.

Use networkTags to match the firewall rule your onboarding created, and assignPublicIp: false for a workstation with no public IP that you reach privately.

Azure (cloud)

The Azure provider creates a VM in one resource group, authenticating through a CloudIdentity exactly as GCP does. Ringleader synthesizes the per-VM NIC in the subnet you give it (and tears it down with the VM), so subnetId is required unless you supply a pre-existing NIC.

KeyTypeDescription
subscriptionIdstringRequired. The subscription the VM runs in.
resourceGroupstringRequired. The resource group (your cost/RBAC boundary).
locationstringRequired. e.g. eastus. Immutable.
subnetIdstringThe full ARM subnet resource id. Ringleader creates a per-VM NIC in it, and tears it down with the VM.
networkInterfaceIdstringAttach a pre-existing NIC instead. Ringleader never deletes a NIC it did not create.
publicIpboolAttach a Standard public IP. Default false — a workstation without one needs a NAT gateway for egress, or it never finishes setting up.
sizestringThe VM size, e.g. Standard_D4s_v5.
osDiskGiBintOS disk size.
osDiskTypestringOS disk storage type.
osDiskCachingstringOS disk caching mode.
ephemeralOsDiskboolUse an ephemeral OS disk.
securityTypestringDefaults to Standard, which nested virtualization requires (and which needs a subscription feature registered — see onboarding).
adminUsernamestringThe bootstrap admin user Azure creates on the VM.
tagsmapAzure resource tags.
spec:
  provider: azure
  providerConfig:
    azure:
      subscriptionId: 22222222-2222-2222-2222-222222222222
      resourceGroup: ringleader-workstations
      location: eastus
      subnetId: /subscriptions/…/virtualNetworks/ringleader-vnet/subnets/workstations
      publicIp: true
      size: Standard_D4s_v5

The OS image is the ordinary config-layer image field (distribution + version) — debian 12/13, or ubuntu 22.04/24.04/26.04, each resolved to the matching marketplace image for the size’s architecture.

Placement is typically supplied by the CloudIdentity’s defaultProviderConfig, so a workstation names only what it wants to differ.

AWS (cloud)

The AWS provider creates an EC2 instance, authenticating through a CloudIdentity exactly as GCP and Azure do. Set that up first; see onboarding AWS for the IAM role and trust to create in your account, and the CloudIdentity reference for the credential path.

KeyTypeDescription
regionstringRequired. The region the instance runs in. Immutable.
instanceTypestringe.g. m6i.xlarge. Default t3.medium. Must be x86-64 — the image alias table resolves x86-64 AMIs.
subnetIdstringThe subnet the instance is placed in (also fixes the availability zone and VPC).
securityGroupIdslistSecurity groups attached to the instance.
assignPublicIpboolAttach a public IP. Default true. A workstation without one needs a NAT gateway for egress, or it never finishes setting up.
rootVolumeGiBintRoot volume size. Default ~40 GiB.
rootVolumeTypestringRoot volume type. Default gp3.
rootDeviceNamestringRoot device name, if the AMI’s differs from the default.
nestedVirtualizationboolRequest an instance configuration that supports nested virtualization.
iamInstanceProfilestringAn instance profile to attach, so software on the workstation has its own AWS identity. The AWS analogue of the GCP runtime service account (Ringleader attaches, but does not create, the profile).
tagsmapEC2 resource tags.

The OS image is the ordinary config-layer image field (distribution + version), resolved to a vendor-published public AMI: debian 12/13, ubuntu 22.04/24.04/26.04, or amazonlinux 2023. The AMI is resolved at launch, so you always get the latest patched image for the release you named rather than a pinned snapshot.

spec:
  provider: aws
  image:
    distribution: ubuntu
    version: "24.04"
  providerConfig:
    aws:
      region: us-east-1
      instanceType: m6i.xlarge
      subnetId: subnet-0abc123
      securityGroupIds: [sg-0abc123]
      assignPublicIp: true

Placement is typically supplied by the CloudIdentity’s defaultProviderConfig, so a workstation names only what it wants to differ.

Reachability

An AWS workstation gets a public IP by default, so the internet gateway alone gives it egress. It is still not reachable until a security-group rule allows TCP 22. rl shell dials the workstation directly on port 22; there is no bastion and no tunnel, so a workstation with egress but no inbound rule finishes setting up, reports Ready, and cannot be opened. Use assignPublicIp: false for a private workstation reached over VPN or peering, with a NAT gateway for its egress. See reaching your workstations.

See also

  • CloudIdentity: how the control plane authenticates to a cloud provider and injects provider-config defaults and overrides.
  • Workstation: requirements, provider, and providerConfig.