Skip to main content

Create VM with Terraform

This guide will walk you through the process of creating a virtual machine (VM) with Terraform.

Prerequisites

  • Terraform installed on your machine.
  • Vietnix Cloud account.

Steps to Create VM with Terraform

1. Create a Terraform configuration file.

Terraform Configuration File

The Terraform configuration file is a file that contains the definition of your infrastructure. It is written in the Terraform language and is used to define the resources that you want to create, modify, or destroy.

tip

You can use one configuration file or split the configuration file into multiple files.

# main.tf
terraform {
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = ">= 1.45.0"
}
}
required_version = ">= 1.6.0"
}

# auth provider
provider "openstack" {
auth_url = "https://auth.vietnix.cloud:5000/v3"
user_name = "your-username"
password = "your-password"
tenant_name = "your-tenant-name"
domain_id = "your-domain-id"
}

# Create SSH keypair
resource "openstack_compute_keypair_v2" "terraform_keypair" {
name = "terraform_key"
public_key = file("${var.ssh_key_file}.pub")
}

# Create network
resource "openstack_networking_network_v2" "terraform_network" {
name = "terraform_network"
description = "Network for Terraform instance"
}

# Create subnet
resource "openstack_networking_subnet_v2" "terraform_subnet" {
name = "terraform_subnet"
network_id = openstack_networking_network_v2.terraform_network.id
cidr = "10.0.0.0/24"
gateway_ip = "10.0.0.1"
ip_version = 4
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
}

# Create router
resource "openstack_networking_router_v2" "terraform_router" {
name = "terraform_router"
external_network_id = var.external_network_id
enable_snat = true
}

# Connect router to subnet
resource "openstack_networking_router_interface_v2" "terraform_router_interface" {
router_id = openstack_networking_router_v2.terraform_router.id
subnet_id = openstack_networking_subnet_v2.terraform_subnet.id
}

# Create floating IP
resource "openstack_networking_floatingip_v2" "terraform_floating_ip" {
pool = var.external_network_name
}

# Create security group
resource "openstack_networking_secgroup_v2" "terraform_secgroup" {
name = "terraform_secgroup"
description = "Security group for Terraform instance"
}

# Allow SSH access
resource "openstack_networking_secgroup_rule_v2" "ssh_rule" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.terraform_secgroup.id
}

# Allow HTTP access
resource "openstack_networking_secgroup_rule_v2" "http_rule" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 80
port_range_max = 80
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.terraform_secgroup.id
}

# Allow HTTPS access
resource "openstack_networking_secgroup_rule_v2" "https_rule" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.terraform_secgroup.id
}

# Create virtual machine
resource "openstack_compute_instance_v2" "terraform_instance" {
name = "Terraform-VM"
flavor_name = var.flavor_name
image_id = var.image_id
key_pair = openstack_compute_keypair_v2.terraform_keypair.name
security_groups = [openstack_networking_secgroup_v2.terraform_secgroup.name]

network {
uuid = openstack_networking_network_v2.terraform_network.id
}

block_device {
boot_index = 0
uuid = var.image_id
source_type = "image"
destination_type = "volume"
volume_size = var.volume_size
volume_type = var.volume_type
delete_on_termination = true
}
}

# Get port information
data "openstack_networking_port_v2" "terraform_port" {
device_id = openstack_compute_instance_v2.terraform_instance.id
network_id = openstack_compute_instance_v2.terraform_instance.network.0.uuid
}

# Associate floating IP
resource "openstack_networking_floatingip_associate_v2" "fip_associate" {
floating_ip = openstack_networking_floatingip_v2.terraform_floating_ip.address
port_id = data.openstack_networking_port_v2.terraform_port.id
}

Variables File

Create a variables.tf file to define your variables:

# variables.tf
variable "ssh_key_file" {
description = "Path to the SSH private key file"
type = string
default = "~/.ssh/id_rsa"
}

variable "external_network_id" {
description = "ID of the external network"
type = string
}

variable "external_network_name" {
description = "Name of the external network pool"
type = string
}

variable "flavor_name" {
description = "Name of the flavor for the instance"
type = string
default = "medium.2c.4g"
}

variable "image_id" {
description = "ID of the image to use for the instance"
type = string
}

variable "volume_size" {
description = "Size of the volume in GB"
type = number
default = 20
}

variable "volume_type" {
description = "Type of the volume"
type = string
default = "nvmer3"
}

variable "ssh_user_name" {
description = "SSH username for the instance"
type = string
default = "cloud-user"
}

Outputs File

Create an outputs.tf file to display important information:

# outputs.tf
output "instance_id" {
description = "ID of the created instance"
value = openstack_compute_instance_v2.terraform_instance.id
}

output "instance_name" {
description = "Name of the created instance"
value = openstack_compute_instance_v2.terraform_instance.name
}

output "floating_ip" {
description = "Floating IP address of the instance"
value = openstack_networking_floatingip_v2.terraform_floating_ip.address
}

output "private_ip" {
description = "Private IP address of the instance"
value = openstack_compute_instance_v2.terraform_instance.network.0.fixed_ip_v4
}

2. Run terraform init to initialize the Terraform configuration

terraform init

3. Run terraform plan to plan the Terraform configuration

terraform plan
tip

You can add variables to the plan command to see the plan with specific values.

terraform plan -var="ssh_key_file=~/.ssh/id_rsa" -var="external_network_id=your-external-network-id" -var="external_network_name=your-external-network-name" -var="flavor_name=small.1c.2g" -var="image_id=your-image-id" -var="volume_size=20" -var="volume_type=nvmer3" -var="ssh_user_name=cloud-user"

4. Run terraform apply to create the virtual machine

terraform apply
tip

You can add variables to the apply command to apply the virtual machine with specific values.

terraform apply -var="ssh_key_file=~/.ssh/id_rsa" -var="external_network_id=your-external-network-id" -var="external_network_name=your-external-network-name" -var="flavor_name=small.1c.2g" -var="image_id=your-image-id" -var="volume_size=20" -var="volume_type=nvmer3" -var="ssh_user_name=cloud-user"

5. Run terraform destroy to destroy the virtual machine

terraform destroy

Verify the Virtual Machine

After the virtual machine is created, you can verify it by logging in to the virtual machine.

ssh -i ~/.ssh/id_rsa cloud-user@<floating_ip>

Next Steps