> For the complete documentation index, see [llms.txt](https://docs.i3d.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.i3d.net/compute/flexvm/using-terraform.md).

# Using Terraform

FlexVM can be used through our API or through our Terraform provider. As with the API, you'll need an API token; the procedure is documented in [API v3 Authentication](/game-hosting/overview/apiv3-authentication.md).

Refer to the [i3D.net Terraform Documentation](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs) for the full provider reference.

## Overview

A typical FlexVM deployment is built in three steps, in this order:

1. **Cloud** — a private cloud that groups your VMs onto dedicated FlexMetal nodes of a single instance type within one site.
2. **Node** — bare metal capacity provisioned inside the Cloud. The Cloud must have enough node capacity to host your VMs.
3. **VM** — the virtual machines that run your workloads, scheduled onto the Cloud's nodes.

The examples below follow that order.

## 1. Creating a Cloud

Use the [`i3dnet_flexvm_cloud`](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs/resources/flexvm_cloud) resource to create a private cloud. A Cloud fixes the FlexMetal `instance_type` and `site` that every node in it will share.

There is no update API for a Cloud: changing any attribute forces it to be destroyed and recreated.

```hcl
resource "i3dnet_flexvm_cloud" "my-cloud" {
  name          = "my-private-cloud"
  description   = "Cloud for the odyssey project"
  site          = "frmtl1"
  instance_type = "bm9.hmm.gpu.4rtx4000.64"
}
```

> **Note:** The Cloud's `id` (its UUID) is assigned by the platform and is only known after the Cloud is created — you don't set it yourself. In the next steps you reference it as `i3dnet_flexvm_cloud.my-cloud.id`. Terraform recognizes this reference and automatically creates the Cloud first, then fills in the real UUID when creating the Node and VM. You don't need a `depends_on` for this ordering to work.

## 2. Adding a Node

Use the [`i3dnet_flexvm_node`](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs/resources/flexvm_node) resource to provision a bare metal node inside the Cloud. A Node inherits the Cloud's instance type and location, so `cloud_id` is the only required input — all other attributes are assigned by the platform.

Provisioning bare metal hardware can take a while; the resource waits until the Node reaches the `running` status.

```hcl
resource "i3dnet_flexvm_node" "my-node" {
  cloud_id = i3dnet_flexvm_cloud.my-cloud.id
}
```

## 3. Creating a VM

Use the [`i3dnet_flexvm_vm`](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs/resources/flexvm_vm) resource to create a VM, which is scheduled onto the Cloud's nodes.

Exactly one of `ssh_keys` or `user_data_file` must be set. Use `ssh_keys` for simple SSH access, or `user_data_file` to pass a cloud-init file for more advanced first-boot configuration.

```hcl
resource "i3dnet_flexvm_vm" "my-vm" {
  cloud_id           = i3dnet_flexvm_cloud.my-cloud.id
  name               = "test-gaming-vm1"
  description        = "Test Gaming VM 1"
  instance_type_name = "vm.gpu.1rtx4000.15c.248g"
  image_name         = "ubuntu-2404-server-amd64"
  ssh_keys           = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHwdgjY0AlmkeLknBpoVmJg/quNSifyBHEK1MREpV4Ri john.doe@i3d.net"]

  # Optional free-form labels for grouping in the monthly usage report.
  tags = ["project:odyssey", "env:build"]
}
```

To provide cloud-init user-data from a file instead of `ssh_keys`, use `user_data_file`. Relative paths are resolved against Terraform's working directory, so prefer an absolute path or wrap it with `abspath("${path.module}/...")`:

```hcl
resource "i3dnet_flexvm_vm" "my-vm-with-user-data" {
  cloud_id           = i3dnet_flexvm_cloud.my-cloud.id
  name               = "test-gaming-vm2"
  description        = "Test Gaming VM 2"
  instance_type_name = "vm.gpu.1rtx4000.15c.248g"
  image_name         = "ubuntu-2404-server-amd64"
  user_data_file     = abspath("${path.module}/cloud-init.yaml")
}
```

## Referencing existing resources

If a Cloud or Node already exists and is not managed by your Terraform configuration, reference it through a data source instead of a resource. Because it is referenced through a data source, `terraform destroy` leaves the underlying Cloud or Node untouched.

Use the [`i3dnet_flexvm_cloud`](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs/data-sources/flexvm_cloud) data source to look up an existing Cloud by its UUID:

```hcl
data "i3dnet_flexvm_cloud" "existing" {
  id = "019256ab-1554-73a7-b091-f024b0a724ea"
}

resource "i3dnet_flexvm_vm" "my-vm" {
  cloud_id           = data.i3dnet_flexvm_cloud.existing.id
  name               = "development-ubuntu-2404"
  instance_type_name = "vm.4c.8g"
  image_name         = "ubuntu-2404-server-amd64"
  ssh_keys           = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHwdgjY0AlmkeLknBpoVmJg/quNSifyBHEK1MREpV4Ri john.doe@i3d.net"]
}
```

Use the [`i3dnet_flexvm_node`](https://registry.terraform.io/providers/i3dnet/i3dnet/latest/docs/data-sources/flexvm_node) data source to look up a single Node by its Cloud and Node UUID:

```hcl
data "i3dnet_flexvm_node" "example" {
  cloud_id = "019256ab-1554-73a7-b091-f024b0a724ea"
  id       = "019256ab-1554-73a7-b091-f024b0a724eb"
}

output "node_serial" {
  value = data.i3dnet_flexvm_node.example.serial
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.i3d.net/compute/flexvm/using-terraform.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
