Create Terraform Module and Publish to Terraform Registry

Akurathi Sri Krishna Sagar
3 min readSep 7, 2022

--

In this article, we’re going to create a terraform module for launching azure vm with all the backend infrastructure and upload it to the terraform public registry.

Let’s Start

First, you need to have Azure CLI installed on your system and configure with the command :

az login

Next, gather the subscription_id, client_id, tenant_id, client_secret.

Now create a file providers.tf (for specifying the provider) with the following content :

terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.14.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = "YOUR_SUBSCRIPTION_ID"
tenant_id = "YOUR_TENANT_ID"
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
}

Update the above file with your credentials.

Now create a file main.tf . This file contains all the resources to be created :

resource "azurerm_resource_group" "terr_azure_rg" {
name = "terr_rg"
location = var.location
}
resource "azurerm_virtual_network" "terr_azure_vn" {
name = "terr_network"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.terr_azure_rg.location
resource_group_name = azurerm_resource_group.terr_azure_rg.name
}
resource "azurerm_subnet" "terr_azure_subnet" {
name = "terr_subnet"
resource_group_name = azurerm_resource_group.terr_azure_rg.name
virtual_network_name = azurerm_virtual_network.terr_azure_vn.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_security_group" "terr_azure_sg" {
name = "azure_sg"
location = azurerm_resource_group.terr_azure_rg.location
resource_group_name = azurerm_resource_group.terr_azure_rg.name
security_rule {
name = "allow_all_inbound"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "allow_all_outbound"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "terr_azure_sgAssoc" {
subnet_id = azurerm_subnet.terr_azure_subnet.id
network_security_group_id = azurerm_network_security_group.terr_azure_sg.id
}
resource "azurerm_public_ip" "terr_azure_ip" {
name = "terr_ip"
resource_group_name = azurerm_resource_group.terr_azure_rg.name
location = azurerm_resource_group.terr_azure_rg.location
allocation_method = "Static"
ip_version = "IPv4"
sku = "Standard"
}
resource "azurerm_network_interface" "terr_azure_ni" {
name = "terr_ni"
location = azurerm_resource_group.terr_azure_rg.location
resource_group_name = azurerm_resource_group.terr_azure_rg.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.terr_azure_subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.terr_azure_ip.id
}
}
resource "azurerm_linux_virtual_machine" "terr_azure_vm" {
name = "terr-vm"
resource_group_name = azurerm_resource_group.terr_azure_rg.name
location = azurerm_resource_group.terr_azure_rg.location
size = var.vm_size
admin_username = var.admin_username
network_interface_ids = [
azurerm_network_interface.terr_azure_ni.id,
]
admin_ssh_key {
username = var.admin_username
public_key = file(var.azure_public_key)
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
}

You can view various resources that will be created by terraform in the above file. This file uses some variables which are to be declared in the file variables.tf :

variable "location" {
type = string
description = "Region name for the VM"
}
variable "vm_size" {
type = string
description = "Size of the VM"
}
variable "admin_username" {
type = string
description = "Username for the admin account of VM"
}
variable "azure_private_key" {
type = string
description = "Location of private key file created with ssh-keygen"
}
variable "azure_public_key" {
type = string
description = "Location of public key file created with ssh-keygen"
}

The actual values for the variables are to be given inside the file terraform.tfvars :

location           = "Central India"
vm_size = "Standard_D2s_v3"
admin_username = "adminuser"
azure_private_key = "/home/YOUR_USERNAME/.ssh/id_rsa"
azure_public_key = "/home/YOUR_USERNAME/.ssh/id_rsa.pub"

You can change the values of the variables in the above file.

Now create another file outputs.tf which is used to display the Public IP of the VM created, in this case :

output "vm_public_ip" {
value = azurerm_linux_virtual_machine.terr_azure_vm.public_ip_address
description = "Public IP Address of the VM Launched"
}

Finally, create a README and LICENSE files (optional).

The directory structure of the terraform module created above is :

.
├── LICENSE
├── main.tf
├── outputs.tf
├── providers.tf
├── README.md
├── terraform.tfvars
└── variables.tf

Now the terraform module is ready. You can test the module by running the following commands :

terraform init
terraform plan
terraform apply

To destroy all the resources, you can use the following command :

terraform destroy

Now go to the link and follow the instructions to create a GitHub repository with specified naming convention and don’t forget to add a Tag with proper version number in the GitHub, otherwise terraform registry won’t accept your repository.

Now go to https://registry.terraform.io/ and login with your GitHub and click on Publish->Module and select your GitHub repository and it’s done. If you followed all the requirements correctly, your module will be published withing seconds.

I’ve uploaded my module to the terraform registry :

Thanks for reading!

--

--

No responses yet