Skip to main content
In this lesson we’ll start writing real Terraform code using HCL (HashiCorp Configuration Language). Up to now you’ve learned what Terraform is and how it works conceptually — here we’ll put that into practice by describing infrastructure as code. If this is your first time with Terraform, follow along: we’ll build everything step by step and explain each line. Terraform configuration typically follows three steps:
  1. Tell Terraform which cloud/provider to talk to (provider block).
  2. Define what you want to create (resource block).
  3. Provide details about the resource (arguments).
Mastering these three building blocks lets you read and author most Terraform configurations with confidence.

Minimal example: Create a Resource Group in Azure

This minimal configuration contains the provider, a resource block, and the arguments Terraform needs to create a resource group in Azure.
  • provider block: configures how Terraform talks to Azure.
  • resource block: declares what to create.
  • arguments: name and location define the resource properties.

Terraform three-command workflow

After you write HCL, Terraform uses a simple workflow: Representative outputs you will commonly see are shown below. Initialize the project (downloads providers):
Preview the changes with plan:
Apply the plan to create resources:
We won’t deeply cover terraform validate and terraform fmt here — for now remember that the HCL code declares desired state, and Terraform’s commands make and reconcile those changes.

Provider block details

The provider block configures how Terraform communicates with an external system — in this case Azure via the AzureRM provider.
The features {} block is required by the AzureRM provider and enables provider defaults. You can supply credentials in the provider block (for example subscription_id), but it’s common and recommended to authenticate via environment variables, Azure CLI (az login), or managed identities for automation scenarios.
Example with subscription_id embedded (less common for production):

Resource block details

A resource block declares the infrastructure to create. The syntax pattern is: resource "<PROVIDER>_<TYPE>" "<LOCAL_NAME>" { ... }
  • <PROVIDER>_<TYPE>: the resource type, for example azurerm_storage_account.
  • <LOCAL_NAME>: a local reference used inside Terraform configurations (this name is not visible to Azure).
Example: create an Azure Storage Account. Arguments define properties like name, location, tier, and replication.
Some arguments are required and others optional. Always check the provider documentation for required fields and recommended defaults.

Quick reference: workspace and main.tf

Set up a workspace folder (for example first-code) and add main.tf. You can keep everything in main.tf while learning, and later split into multiple files and modules. Example main.tf combining provider and resource group:
Steps to run locally in VS Code / Terminal:
  1. Save your files before running Terraform commands (Ctrl+S / Cmd+S).
  2. From the directory containing main.tf, run terraform init. This downloads the provider plugin into the .terraform directory.
  3. Run terraform plan to preview changes.
  4. Run terraform apply to create the resources (type yes when prompted, or use -auto-approve for automation).
Representative success output from terraform init:
Representative terraform plan output:
Apply to create the resource group:

Getting started in Visual Studio Code

Before you start writing HCL, ensure:
  • Terraform is installed and available in your PATH.
  • You’re authenticated to Azure CLI via az login and have a subscription selected (az account show).
  • Optionally, install the HashiCorp Terraform extension for VS Code to get syntax highlighting and IntelliSense. There are also third-party extensions — only install from trusted sources.
This image shows the Visual Studio Code (VS Code) interface with the Extensions Marketplace open, displaying search results for "Terraform" extensions. Various extensions related to Terraform configuration and syntax highlighting are listed with options to install them.
Running az account show returns account details similar to this (trimmed output):

State file and drift detection

Terraform stores the state of managed resources in the state file (by default terraform.tfstate) inside your workspace. This file maps Terraform resources to real-world objects and is essential for planning and updates. Key points:
  • Deleting the state file causes Terraform to “forget” the resources it manages — future plans may attempt to recreate them.
  • If a resource is modified outside Terraform (for example, changing tags in the Azure Portal), the next terraform plan will detect this drift and display the changes needed to reconcile the infrastructure with your code.
Example workflow: add a tag to the resource group in the Azure Portal, then run terraform plan. Terraform will detect the difference and propose the actions to match the declared configuration.
The image shows the Microsoft Azure portal, specifically the Resource Manager section where a user is editing tags for a resource group named "kodekloud-tf-rg."
When Terraform refreshes state (during plan or apply), it compares actual resources in Azure with the local state and the configuration declared in HCL, and then reconciles them according to your code.

Helpful references and next topics

Tip: Use the official HashiCorp Terraform extension for VS Code to get verified tooling and IntelliSense. If you use third-party extensions, ensure they come from trusted sources.

Watch Video