# Deploy the development environment template with OpenTofu

Source: https://docs.quake.ai/resources/deployments/deploy-dev-environment-template
Markdown: https://docs.quake.ai/resources/deployments/deploy-dev-environment-template.md
> Stand up a bastion with one floating IP, development VMs on a private network, and shared NFS storage at /srv/shared using the dev-environment OpenTofu template.

---

# Deploy the development environment template with OpenTofu

Stand up a bastion host on a floating IP, development VMs on a private network, and a shared block volume exported over NFS at `/srv/shared` using the [validated OpenTofu template](/docs/platform/validation#how-infrastructure-templates-are-checked) `dev-environment`. Cloud-init installs a configurable `dev_tools` package set on every instance.

<PricingCompanion
  components={[
    { kind: "template", slug: "dev-environment", required: true },
  ]}
/>

<Figure size="md" caption="Development environment topology: bastion with one floating IP, dev VMs, and a shared volume exported over NFS at /srv/shared">

```d2
direction: right

cloud: Quake AI {
  fip: Floating IP\n(1)
  bastion: Bastion\nNFS client
  private: Private network {
    dev0: Dev VM 1\nNFS server\nshared volume
    dev1: Dev VM 2\nNFS client
  }
  vol: Block volume\n100 GB
}

cloud.fip -> cloud.bastion
cloud.vol -> cloud.dev0
cloud.dev0 -> cloud.bastion: NFS /srv/shared
cloud.dev0 -> cloud.dev1: NFS /srv/shared
```

</Figure>

## Prerequisites

You need:

- A Quake AI account with [application credentials](/docs/tools/generate-app-credentials) and an [SSH key pair already uploaded to your project](/docs/tools/add-ssh-key)
- OpenTofu 1.6.0 or later ([installation guide](https://opentofu.org/docs/intro/install/))
- OpenStack credentials sourced into the shell (`source openrc.sh`). See [the OpenStack CLI guide](/docs/tools/openstack-cli).
- A copy of the `dev-environment` template from [the template reference page](/resources/iac-templates/dev-environment)
- Enough project quota for two `s1a.medium` dev instances, one `s1a.small` bastion, one 100 GB block volume, and one floating IP

## Step 1: Configure variables

Copy `terraform.tfvars.example` to `terraform.tfvars` and set:

```hcl
key_name = "YOUR_KEY_NAME"
```

Defaults for `dev_vm_count`, flavors, volume size, and `dev_tools` packages are documented on the [Development Environment](/resources/iac-templates/dev-environment) reference page.

## Step 2: Apply the template

From the template directory, run:

```bash
tofu init
tofu plan
tofu apply
```

Type `yes` when prompted. Cloud-init on the dev VMs and bastion can take a few more minutes after `tofu apply` returns.

When the run finishes, note `bastion_ip`, `dev_instance_ips`, and `nfs_server_ip` from the outputs. Dev VM 1 always receives `cidrhost(private_cidr, 10)` and serves the NFS export from that address.

## Step 3: Verify the shared mount and tooling on a dev VM

SSH to dev VM 1 through the bastion floating IP:

```bash
BASTION=$(tofu output -raw bastion_ip)
DEV1=$(tofu output -json dev_instance_ips | jq -r '.[0]')
ssh -i YOUR_PRIVATE_KEY_PATH -J ubuntu@${BASTION} ubuntu@${DEV1}
```

On dev VM 1, confirm the shared volume is mounted at `/srv/shared`:

```bash
df -h /srv/shared
mount | grep /srv/shared
command -v git jq tmux python3
```

Write a marker file on the shared directory from dev VM 1:

```bash
echo "shared from $(hostname)" | sudo tee /srv/shared/shared-check.txt
exit
```

SSH to dev VM 2 and confirm the same file is visible through NFS:

```bash
DEV2=$(tofu output -json dev_instance_ips | jq -r '.[1]')
ssh -i YOUR_PRIVATE_KEY_PATH -J ubuntu@${BASTION} ubuntu@${DEV2} 'cat /srv/shared/shared-check.txt && mount | grep /srv/shared'
```

## Next steps

- [Development Environment template](/resources/iac-templates/dev-environment)
- [Simple VM with Floating IP template](/resources/iac-templates/simple-vm)
- [AI-native development](/resources/solutions/ai-native-development)

## Clean up

Run `tofu destroy` from the project directory when finished. Type `yes` to confirm. Verify in the Console that the instances, volume, and floating IP are gone.
