Configure run.cua.ai fleets with Terraform
Create Linux and Windows run.cua.ai fleets with the temporary local Cua Fleets provider installation.
Use this guide to create a run.cua.ai fleet backed by the public Cua Fleets
provider. Terraform represents each fleet as a fleets_pool resource.
Prerequisites#
- A run.cua.ai user key or access token with permission to manage Fleet pools. Keep credentials in environment variables or a secret manager, not in source control.
- Terraform or OpenTofu and Go on the machine where you build the provider.
- The temporary local provider installation from the public terraform-provider-fleets README.
The provider is not published to the Terraform Registry yet. Follow the public
README to clone https://github.com/trycua/terraform-provider-fleets.git, build
for your current OS and architecture, and configure its filesystem mirror. That
flow installs a local binary; it is not Registry resolution. Replace this
temporary setup with the normal Registry installation after trycua/fleets is
published.
The provider source address remains trycua/fleets; do not use a GitHub URL in
required_providers.source. Set the CLI configuration file created by the
public README before initializing either example:
export TF_CLI_CONFIG_FILE="$HOME/.terraformrc-fleets-local"For OpenTofu, run the same commands with tofu in place of terraform.
Authentication#
The provider accepts either CYCLOPS_ACCESS_TOKEN, or all three OAuth user-key
variables: CYCLOPS_CLIENT_ID, CYCLOPS_CLIENT_SECRET, and
CYCLOPS_TOKEN_URL. Configure the run.cua.ai endpoint separately:
export CYCLOPS_ENDPOINT="https://run.cua.ai"
export CYCLOPS_ACCESS_TOKEN="<your-access-token>"Create a Linux fleet#
Create a new directory, save this as main.tf, and choose a unique lowercase
DNS-label pool name. This example creates a KubeVirt Linux pool and exposes SSH.
terraform {
required_providers {
fleets = {
source = "trycua/fleets"
version = "1.0.0"
}
}
}
provider "fleets" {
endpoint = "https://run.cua.ai"
}
resource "fleets_pool" "linux" {
name = "linux-fleet"
replicas = 0
cpu_cores = 4
memory = "8Gi"
container_disk_image = "296062593712.dkr.ecr.us-west-2.amazonaws.com/desktop-workspace-duo:main-38352d34"
runtime = "kubevirt"
firmware = "bios"
service {
name = "ssh"
target_port = 22
protocol = "TCP"
}
autoscaling {
min_pool_size = 0
initial_pool_size = 1
max_pool_size = 5
}
}
output "linux_fleet" {
value = {
name = fleets_pool.linux.name
namespace = fleets_pool.linux.namespace
phase = fleets_pool.linux.phase
}
}Create a Windows fleet#
Use a distinct name for Windows. The Windows computer-server image requires
UEFI, so this example sets firmware = "efi" and waits for the service on port
8000.
terraform {
required_providers {
fleets = {
source = "trycua/fleets"
version = "1.0.0"
}
}
}
provider "fleets" {
endpoint = "https://run.cua.ai"
}
resource "fleets_pool" "windows" {
name = "windows-fleet"
replicas = 0
cpu_cores = 4
memory = "4Gi"
container_disk_image = "296062593712.dkr.ecr.us-west-2.amazonaws.com/cua-server-windows:latest"
runtime = "kubevirt"
firmware = "efi"
readiness_probe_json = jsonencode({
tcpSocket = { port = 8000 }
initialDelaySeconds = 60
periodSeconds = 5
timeoutSeconds = 3
failureThreshold = 120
})
service {
name = "computer-server"
target_port = 8000
protocol = "TCP"
}
autoscaling {
min_pool_size = 0
initial_pool_size = 1
max_pool_size = 5
}
}
output "windows_fleet" {
value = {
name = fleets_pool.windows.name
namespace = fleets_pool.windows.namespace
phase = fleets_pool.windows.phase
}
}Apply, verify, and destroy#
With TF_CLI_CONFIG_FILE still set, initialize from the local mirror and run
one example:
rm -rf .terraform .terraform.lock.hcl
terraform init
terraform fmt -check
terraform validate
terraform plan
terraform apply
terraform outputterraform init uses the locally built provider and must not resolve
trycua/fleets from the public Registry. The provider returns namespace,
phase, total_count, available_count, and claimed_count. A ready fleet
has available sandboxes after its warm pool provisions.
Destroy the pool when finished. This deletes both the pool and its same-named namespace:
terraform destroyTroubleshooting and security#
- Use a lowercase DNS label of at most 63 characters for
name. Changing it replaces the pool because it also owns its namespace. - Check the image reference and image-pull-secret policy if creation returns
403.image_pull_secretdefaults toecr-credentials. - Use
biosfor the Linux workspace image andefifor the Windows computer-server image. A firmware mismatch prevents the guest from booting. - Protect Terraform state and shell history as operational secrets.