# modules/runners

**Spinbox is experimental: APIs change and data may be lost.** What is built and what proves it is on [Status](https://spin-stack.github.io/website/reference/status.md); what Spinbox does not do is on [Limitations](https://spin-stack.github.io/website/overview/limitations.md).

> spin-terraform-aws, the runners' autoscaling group, used on its own.

<!-- Generated by tools/refgen from spin-terraform-aws:modules/runners/variables.tf. Edit the source, not this file. -->

Source: `github.com/spin-stack/spin-terraform-aws//modules/runners?ref=<tag>`. Generated from its `variables.tf` and `outputs.tf`.

## Variables

| Variable | Type | Default |
|---|---|---|
| [`controlplane`](#controlplane) | `object({ name = string iam_name = string vpc_id = string subnet_ids = list(string) security_group_id = string runner_document_arn = string runner_user_data = string images = map(object({ id = string, root_device = string })) boot_log_policy_arn = string standard_vcpus = number boundary_arn = string })` | **required** |
| [`instance_types`](#instance_types) | `list(string)` | `["m8id.8xlarge","c8id.8xlarge","r8id.8xlarge","m8id.12xlarge","c8id.12xlarge"]` |
| [`nested_virtualization`](#nested_virtualization) | `bool` | `true` |
| [`spot`](#spot) | `bool` | `true` |
| [`request_quota`](#request_quota) | `bool` | `true` |
| [`max_hosts`](#max_hosts) | `number` | `1` |
| [`rollout`](#rollout) | `string` | `"idle"` |
| [`drain_seconds`](#drain_seconds) | `number` | `150` |
| [`data_volume_gb`](#data_volume_gb) | `number` | `0` |
| [`root_volume_gb`](#root_volume_gb) | `number` | `30` |
| [`tags`](#tags) | `map(string)` | `{}` |

### controlplane

The control plane module's outputs, as they are: its name, where the runners go, their document, and what a runner's machine runs at its first boot.

- Type: `object({ name = string iam_name = string vpc_id = string subnet_ids = list(string) security_group_id = string runner_document_arn = string runner_user_data = string images = map(object({ id = string, root_device = string })) boot_log_policy_arn = string standard_vcpus = number boundary_arn = string })`
- **Required**

### instance_types

What the group may start. Keep them one CPU generation: a checkpoint records the processor
and its flags as -cpu host showed them (MachineIdentity in spin's internal/runner/vmm), and
resumes only onto a host that shows the same - a workspace suspended at night on one family
and brought back on another cold-boots. Nested virtualization is offered on C8i, M8i, R8i
(and their d variants), C7i, M7i, R7i and I7i; a d variant brings the local NVMe the runner's
data goes on.

For spot, name several: AWS gives a spot machine from the pools a request can draw on, and
one type is one pool per zone. m8id.8xlarge alone scored 3 of 10 in us-west-2 and was reclaimed
within minutes; the five below score 9. How a list scores in a region, before installing:
  aws ec2 get-spot-placement-scores --target-capacity 1 --region-names &lt;region> \
    --instance-types &lt;the types>

- Type: `list(string)`
- Default: `["m8id.8xlarge","c8id.8xlarge","r8id.8xlarge","m8id.12xlarge","c8id.12xlarge"]`

### nested_virtualization

Enable KVM inside the instance. False for .metal types, which have it by being metal and refuse the option.

- Type: `bool`
- Default: `true`

### spot

Every host a spot instance. The policy a runner joins under (the control plane module's runner_policy) is what tells each one a stop is a reclaim.

- Type: `bool`
- Default: `true`

### request_quota

Ask AWS for the vCPU quota max_hosts runners need, when the account's is lower (quota.tf). A request costs nothing and lowers nothing when it is removed.

- Type: `bool`
- Default: `true`

### max_hosts

The most runners the group may have. How many it has is the control plane's to decide: none until a workspace waits for a host, and none again once nothing has run for the control plane module's runner_idle_minutes.

- Type: `number`
- Default: `1`

### rollout

How a new release reaches the runners. idle: when the fleet next empties - no workspace running, starting or being saved - the next host boots it, and no workspace is moved for it; a host keeps the old release until then, which its control plane allows for 90 days. rolling: the hosts are replaced at once, one at a time, each old one's workspaces suspended to the bucket and resumed on the new one - for a fleet that never empties.

- Type: `string`
- Default: `"idle"`

### drain_seconds

How long a host the group is taking away is held while it empties itself: the termination hook's timeout. At least the pool token's --shutdown-grace; the hook is left to expire, so this is also how long each scale-in takes.

- Type: `number`
- Default: `150`

### data_volume_gb

An EBS volume for the runner's data, for an instance type with no local NVMe. Zero uses the instance store, which is the right disk for volumes' cache and costs nothing more. A machine's boot takes an empty EBS volume where it has one, and the instance store otherwise.

- Type: `number`
- Default: `0`

### root_volume_gb

The runner's root disk: the OS and the machine's files; its data is on the instance store or data_volume_gb.

- Type: `number`
- Default: `30`

### tags

Tags on everything this module creates.

- Type: `map(string)`
- Default: `{}`

## Outputs

| Output | What it is |
|---|---|
| `autoscaling_group` | The runners' group, which the control plane sizes: empty until a workspace waits for a host. |
| `security_group_id` | The runners' security group: nothing in, everything out - a workspace's egress is filtered on the host by spin. |
