> For the complete documentation index, see [llms.txt](https://docs.readyidc.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.readyidc.com/readme/how-to-use-iac-tools-on-ecs.md).

# How to use IaC tools on ECS

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* Install Terraform

### Terraform:

* Creating VPC
* Creating and configuring VMs:
  * Creating network interfaces
  * Creating vRouter
  * Creating boot volumes
  * Attaching additional volumes
  * Attaching network interfaces
  * Attaching port interfaces
  * Attaching the IP address to the router
  * Assigning Internal IP and Floating IP to vm

**As a result, the directory where you will be working should contain the following items:**

```
├── 00-variables.tf    # Variables that we will define for our deployment
├── 010-ssh-key.tf    # This file will hold your public SSH key to access the environments
├── 020-network.tf    # Network creation/configuration 
├── 030-instance.tf    # Instances definition 
├── provider.tf    # OpenStack provider definition 
└── secrets.tfvars    # File with the password and info about your cloud
```

### Step-by-step guide <a href="#step-by-step-guide" id="step-by-step-guide"></a>

1. Create the  `provider.tf`  file that will define the modules and terraform provider versions:

{% code title="provider.tf" lineNumbers="true" %}

```tf
terraform {
  required_version = ">= 0.14.0"

  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 2.1"
    }
  }
}

provider "openstack" {
  auth_url            = var.os_auth_url
  region              = var.os_region
  tenant_name         = var.os_tenant_name
  user_name           = var.os_username
  password            = var.os_password
  user_domain_name    = var.os_user_domain_name != "" ? var.os_user_domain_name : var.os_domain_name
  project_domain_name = var.os_project_domain_name != "" ? var.os_project_domain_name : var.os_domain_name
}
```

{% endcode %}

2\. Create the `secrets.tfvars` file to store your secrets:

{% code title="secrets.tfvars" lineNumbers="true" %}

```tfvars
os_username           = "<your_user_name_login_domain>"
os_tenant_name        = "<your_project_name>"
os_password           = "<your_password_login_domain>"
os_auth_url           = "https://vhi.readyidc.com:5000/v3"
os_region             = "RegionOne"
os_domain_name        = "<your_domain_name>"
```

{% endcode %}

3. Create the  `00-variables.tf`  file and change variables to match your current environment

{% code title="00-variables.tf" lineNumbers="true" %}

```tf
variable "os_username" {}
variable "os_tenant_name" {}
variable "os_password" {}
variable "os_auth_url" {}
variable "os_region" {}
variable "os_domain_name" {}

variable "os_user_domain_name" {
  default = ""
}
variable "os_project_domain_name" {
  default = ""
}

variable "image" {
  type    = string
  default = "Ubuntu-24-v260112" #change this to match the name of the image you'd like to use (must be centos based)
}

variable "flavor_instance" {
  type    = string
  default = "csa.large.v2" # change this to match the available flavor on your cloud
}

variable "volume_instance" {
  type    = number
  default = 20
}

variable "volume_type" {
  type    = string
  default = "default"
}

variable "internal_network_name" {
  type    = string
  default = "network_1" # change this to match the name of your internal network
}

variable "vrouter_name" {
  type    = string
  default = "vrouter_1" # change this to match the name of your internal subnet
}

# UUID of external gateway
variable "external_gateway" {
  type    = string
  default = "35fea6b9-cbe8-40e0-94ea-2440dc609181"
}

# External network/pool name used to allocate floating IPs
variable "external_network_name" {
  type    = string
  default = "Public"
}

variable "dns_ip" {
  type    = list(string)
  default = ["8.8.8.8", "1.1.1.1"] # whatever you like to use here 
}
```

{% endcode %}

4. Create the SSH key file that will define the key to be added to workloads. You need to specify your public SSH key.

{% code title="010-ssh-key.tf" lineNumbers="true" expandable="true" %}

```terraform
#Define ssh to config in instance
resource "openstack_compute_keypair_v2" "user_key" {
  name       = "<your_name_ssh_key>"
  public_key = "ssh-ed25519..." # Your public SSH key here
}
```

{% endcode %}

5. Create the network configuration for your VMs that will define a network, a router, and subnets.

{% code title="020-network.tf" lineNumbers="true" %}

```terraform
# Router creation
resource "openstack_networking_router_v2" "generic" {
  name                = "<router_name>"
  external_network_id = var.external_gateway
}

resource "openstack_networking_router_interface_v2" "router_interface_1" {
  router_id = openstack_networking_router_v2.generic.id
  subnet_id = openstack_networking_subnet_v2.subnet_1.id
}

# Network creation
resource "openstack_networking_network_v2" "generic" {
  name = "<network_name>"
}

resource "openstack_networking_subnet_v2" "subnet_1" {
  network_id = openstack_networking_network_v2.generic.id
  cidr       = "<network_cidr>" # likes 192.168.0.0/24
  ip_version = 4
  dns_nameservers = var.dns_ip
}
```

{% endcode %}

6. Create the VMs:

{% code title="030-instances.tf" lineNumbers="true" %}

```terraform
data "openstack_images_image_v2" "instance" {
  name        = var.image
  most_recent = true
}

resource "openstack_compute_instance_v2" "instance_1" {
  name        = "<instance_name>"
  image_name  = var.image
  flavor_name = var.flavor_instance
  key_pair    = openstack_compute_keypair_v2.user_key.name

  network {
    port = openstack_networking_port_v2.instance_1.id
  }
  # Install system in volume
  block_device {
    volume_size           = var.volume_instance
    destination_type      = "volume"
    delete_on_termination = true
    boot_index            = 0
    source_type           = "image"
    uuid                  = data.openstack_images_image_v2.instance.id
    volume_type           = var.volume_type
  }
}

## add internal ip to vm
resource "openstack_networking_port_v2" "instance_1" {
  network_id     = openstack_networking_network_v2.generic.id
  admin_state_up = true
}
## add floating ip to vm
resource "openstack_networking_floatingip_v2" "instance_1" {
  pool = var.external_network_name
}

resource "openstack_networking_floatingip_associate_v2" "instance_1" {
  floating_ip = openstack_networking_floatingip_v2.instance_1.address
  port_id     = openstack_networking_port_v2.instance_1.id
}

resource "openstack_compute_instance_v2" "instance_2" {
  name        = "<instance_name>"
  image_name  = var.image
  flavor_name = var.flavor_instance
  key_pair    = openstack_compute_keypair_v2.user_key.name

  network {
    port = openstack_networking_port_v2.instance_2.id
  }
  # Install system in volume
  block_device {
    volume_size           = var.volume_instance
    destination_type      = "volume"
    delete_on_termination = true
    boot_index            = 0
    source_type           = "image"
    uuid                  = data.openstack_images_image_v2.instance.id
    volume_type           = var.volume_type
  }
}
## add internal ip to vm
resource "openstack_networking_port_v2" "instance_2" {
  network_id     = openstack_networking_network_v2.generic.id
  admin_state_up = true
}
## add floating ip to vm
resource "openstack_networking_floatingip_v2" "instance_2" {
  pool = var.external_network_name
}

resource "openstack_networking_floatingip_associate_v2" "instance_2" {
  floating_ip = openstack_networking_floatingip_v2.instance_2.address
  port_id     = openstack_networking_port_v2.instance_2.id
}
```

{% endcode %}

### Verify

Now, you are ready to run Terraform commands to deploy the defined IaC in to your project.

1. Initialize Terraform:

```terraform
terraform init
```

<figure><img src="/files/pWfxOVwA9kO2mFNkdxlW" alt=""><figcaption></figcaption></figure>

2\. Once Terraform is successfully initialized, run the `terraform plan` command:

```
terraform plan -var-file="secrets.tfvars"
```

3. If the previous command was successful, proceed with the deployment:

```
terraform apply -var-file="secrets.tfvars"
```

<figure><img src="/files/HMhaLuYghRAza63UXTGd" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/xhN3VkN5tJKbaiu6VVKg" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/IiG7VQVwbB6Gbu512qY6" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/bjYij8FPzvtssyVGrURB" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/JTqlltVeXmJy3g8pkWvp" alt=""><figcaption></figcaption></figure>

Ref: <https://www.virtuozzo.com/infrastructure-docs/infrastructure-management-with-terraform/>


---

# 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.readyidc.com/readme/how-to-use-iac-tools-on-ecs.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.
