Azure Terraform tutorial

Tutorial: Writing a main.tf File for an Azure Project with Terraform

The main.tf file is often the core of your Terraform configuration, serving as the primary blueprint for the infrastructure you want to provision. It’s where you define the resources, modules, and providers that Terraform will manage.

1. Understanding the Role of main.tf

In any Terraform project, the files with the .tf extension in your current working directory are considered part of the root module. When you run terraform init, terraform plan, or terraform apply in a directory, Terraform treats that directory as the root module. While you can name your Terraform files anything ending in .tf, main.tf is a common convention for the primary configuration file.

The goal of Terraform’s declarative language in main.tf is to describe the desired state of your infrastructure, and Terraform will determine the steps to achieve that state.

2. Basic Structure of a main.tf File

A typical main.tf file for an Azure project will include at least two main blocks: the terraform block and the provider block, followed by resource definitions.

# main.tf

# 1. Terraform Block: Configuration for Terraform itself
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0" # Specify a compatible version
    }
  }
}

# 2. Provider Block: Configuration for Azure
provider "azurerm" {
  features {} # The 'features' block is required
}

# 3. Resource Block(s): Define your Azure infrastructure resources
# Example: Azure Resource Group
resource "azurerm_resource_group" "example" {
  name     = "my-resource-group"
  location = "West US" # Or another Azure region like "westeurope"
}

Let’s break down each part:

a. The terraform Block

This block configures Terraform’s behavior, especially specifying the required providers.

b. The provider "azurerm" Block

This block configures the Azure provider itself.

c. Resource Block(s)

This is where you define the actual infrastructure components you want to create in Azure.

3. Defining Additional Azure Resources

You can add more resource blocks to your main.tf file to build out your Azure infrastructure. For instance, creating a Virtual Network within the resource group:

# ... (terraform and provider blocks as above) ...

resource "azurerm_resource_group" "example" {
  name     = "my-resource-group"
  location = "West US"
}

resource "azurerm_virtual_network" "example" {
  name                = "my-virtual-network"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location # Reference the location from the resource group
  resource_group_name = azurerm_resource_group.example.name   # Reference the name from the resource group
}

Notice how location and resource_group_name in the azurerm_virtual_network block reference attributes from the azurerm_resource_group.example resource. This demonstrates dependencies in Terraform, where one resource relies on another.

4. Using Variables for Dynamic Configuration

To make your main.tf configuration more dynamic and reusable, you should avoid hard-coding values and instead use variables. While variables are typically declared in a variables.tf file, their values are often used in main.tf.

Let’s assume you have a variables.tf file:

# variables.tf
variable "resource_group_name" {
  description = "The name of the resource group"
  type        = string
  default     = "my-dynamic-resource-group"
}

variable "azure_region" {
  description = "The Azure region to deploy resources"
  type        = string
  default     = "eastus"
}

Then, your main.tf would reference these variables:

# main.tf (updated with variables)

# ... (terraform and provider blocks) ...

resource "azurerm_resource_group" "example" {
  name     = var.resource_group_name # Uses the variable
  location = var.azure_region        # Uses the variable
}

resource "azurerm_virtual_network" "example" {
  name                = "${var.azure_region}-vnet" # Using interpolation for dynamic naming
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

You can provide values for these variables via command line (-var), a .tfvars file, or environment variables.

5. Defining Outputs to Expose Information

Output variables are useful for displaying important information about your infrastructure after deployment or for passing values between modules or CI/CD pipelines. Outputs are often defined in an outputs.tf file, but can also be in main.tf.

# main.tf (updated with an output)

# ... (all previous blocks) ...

output "resource_group_id" {
  description = "The ID of the created Resource Group"
  value       = azurerm_resource_group.example.id
}

output "virtual_network_name" {
  description = "The name of the created Virtual Network"
  value       = azurerm_virtual_network.example.name
}

The value attribute typically references an attribute of a resource that Terraform has provisioned.

6. Executing Your main.tf Configuration

Once your main.tf (and any associated variables.tf, outputs.tf) is ready, you’ll use the Terraform CLI to execute it.

  1. Initialize Terraform: Navigate to your project directory in the terminal and run:

    terraform init
    

    This command initializes the working directory, downloads the specified providers, and sets up the backend for state management.

  2. Generate an Execution Plan: Review the changes Terraform proposes to make without actually applying them:

    terraform plan
    

    This command creates an execution plan, showing what resources will be created, modified, or destroyed.

  3. Apply the Changes: If the plan looks correct, apply the changes to your Azure account:

    terraform apply
    

    This command executes the actions outlined in the plan, provisioning your infrastructure. You will typically be prompted for confirmation before changes are made.

7. Best Practices for main.tf

By following these steps, you can effectively write and manage your Azure infrastructure using a main.tf file with Terraform.

comments powered by Disqus

Copyright 2025. All rights reserved.