> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kubox.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Writing a cluster document

> A minimal cluster document that builds, and how to grow it into the one you need.

A cluster document describes the cluster you want. It is the `-f` file of [`kubox admin create`](/reference/cli/kubox_admin_create) and [`kubox cluster create`](/reference/cli/kubox_cluster_create), and the `configYAML` of a `Cluster` resource.

Start here, then use the [full field list](/reference/config/cluster) for everything else.

<Warning>
  A key Kubox does not recognise is **ignored, not reported**. A typo is dropped silently. If a setting has no effect, check its spelling against the [reference](/reference/config/cluster).
</Warning>

## The smallest document that builds

```yaml cluster.yaml theme={null}
metadata:
  clusterName: demo
  pulumi:
    projectName: demo

aws:
  region: ap-southeast-2
  nodeGroups:
    - vmType: t3.small
      count: 1
      role: control-plane
    - vmType: t3.medium
      count: 1
      role: worker
```

```bash theme={null}
kubox admin create -f cluster.yaml
```

Four things are doing the work:

<ResponseField name="metadata.clusterName" type="string">
  What the cluster is called.
</ResponseField>

<ResponseField name="metadata.pulumi.projectName" type="string">
  Names the Pulumi project this cluster's stacks belong to. **It cannot change once the cluster is built.**
</ResponseField>

<ResponseField name="aws.region" type="string" default="us-east-1">
  Where it is built.
</ResponseField>

<ResponseField name="aws.nodeGroups" type="AwsNodeGroup[]">
  The machines. You need at least one `control-plane` group and usually one `worker` group.
</ResponseField>

## Growing it

Each snippet below is a fragment to merge into the document above.

### More workers, and the spot-instance trap

```yaml theme={null}
aws:
  nodeGroups:
    - vmType: t3.medium
      count: 3
      role: worker
      labels:
        nodetype: default
      spotInstance: false
```

<Warning>
  `spotInstance` defaults to **true**. If no spot capacity is available, the request waits instead of failing — so the build sits with no error and no machine. Set `spotInstance: false` to use on-demand.
</Warning>

### GPU nodes

GPUs need an AMI with the NVIDIA extensions, and a taint so ordinary pods do not land on them.

```yaml theme={null}
aws:
  nodeGroups:
    - vmType: g6.xlarge
      count: 1
      awsAMI: ami-05261ad044523904f
      osDiskSizeGB: 200
      role: worker
      systemExtensions:
        - siderolabs/nonfree-kmod-nvidia-lts
        - siderolabs/nvidia-container-toolkit-lts
      labels:
        nodetype: gpu
      taints:
        - key: gpu
          value: true
          effect: NoExecute
```

The AMI is region-specific. See [using GPU instances](/kb/advance-config#using-gpu-instances) for the images and instance types that have been tested.

### Volumes that actually bind

```yaml theme={null}
aws:
  nodeGroups:
    - vmType: t3.medium
      count: 2
      role: worker
      awsIAMInstanceProfile: KuboxEC2Instance
```

`awsIAMInstanceProfile` is the IAM role these nodes run as. Without it, Kubox cannot create disks and your `PersistentVolumeClaims` stay `Pending`.

Which value you need depends on how you are building:

| Building via | Set it to |
| - | - |
| A [cloud connection](/concepts/cloud-accounts) | Leave it out — nodes get the connection's node profile |
| `kubox admin create` from your machine | Name one, e.g. `KuboxEC2Instance` |
| Neither, deliberately | `none` launches nodes with no AWS role |

### A hostname and TLS

```yaml theme={null}
dns:
  rootDomain: example.com

aws:
  ingress:
    enabled: true
```

Kubox checks the DNS zone before it builds, so a mistake fails straight away instead of halfway through.

### Controllers

Controllers are installed from a registry. `aws-ebs-csi-driver`, `aws-s3-csi-driver` and `runtime-class` are on by default.

```yaml theme={null}
controllers:
  - name: metrics-server
    config:
      image: registry.k8s.io/metrics-server/metrics-server:v0.7.2
  - name: headlamp
    enabled: false
```

### Roles and bindings

```yaml theme={null}
rbac:
  - name: developer
    rules:
      - apiGroups: [""]
        resources: ["*"]
        verbs: ["*"]
```

Roles are applied to the cluster during creation. See [`RbacRole`](/reference/config/cluster#rbacrole) and [`RoleBinding`](/reference/config/cluster#rolebinding).

### Tagging for cost reporting

```yaml theme={null}
tags:
  - key: Environment
    value: dev
```

### Pulling from a private ECR registry

Add the credential provider extension to every node group whose workloads pull from a private ECR registry.

```yaml theme={null}
aws:
  nodeGroups:
    - vmType: t3.medium
      count: 2
      role: worker
      systemExtensions:
        - siderolabs/ecr-credential-provider
```

The Kubox agent does not need this. It is pulled from a public registry.

## Where the document goes

<CardGroup cols={3}>
  <Card title="Direct" icon="terminal" href="/reference/cli/kubox_admin_create">
    `kubox admin create -f cluster.yaml` builds from your machine with your own credentials, no management plane.
  </Card>

  <Card title="Through a plane" icon="tower-control" href="/reference/cli/kubox_cluster_create">
    `kubox cluster create -f cluster.yaml` asks a management plane to build it.
  </Card>

  <Card title="As a resource" icon="file-code" href="/concepts/architecture">
    Inside a `Cluster` resource as `spec.configYAML`, applied with `kubectl`.
  </Card>
</CardGroup>

Use `--plan` with either command to see what would be built without building it.

## Next

<CardGroup cols={2}>
  <Card title="Every field" icon="list" href="/reference/config/cluster">
    The complete cluster document reference, generated from the types that parse it.
  </Card>

  <Card title="Plane documents" icon="server" href="/reference/config/plane">
    The `plane.yaml` that describes a management plane.
  </Card>

  <Card title="Worked examples" icon="flask" href="/kb/advance-config">
    GPU instances, secrets, and other advanced configuration.
  </Card>

  <Card title="Build your first cluster" icon="box" href="/hello-world-aws">
    The end-to-end walkthrough, with cleanup.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.