HCL Basics
HCL (HashiCorp Configuration Language) is a declarative language used in Terraform to define infrastructure configurations. It provides a clean and readable syntax for expressing resources and their dependencies.
HCL files typically have a .tf extension and contain the configuration for a Terraform project. HCL uses blocks to define resources.
Within each block, you can specify attributes and their corresponding values to configure the desired behavior of the resource.

Terraform
Terraform block is used for setting the version of the terraform we want.
Terraform block is often put into a separate file called terraform.tf as a way to separate settings into their own file.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 2.0"
}
}
required_version = ">= 1.0.1"
Provider
Provider blocks specifies special type of module that allows Terraform to interact with various cloud-hosting platforms or data centers.
Providers must be configured with proper credentials before we can use them.
provider "aws" {
version = "~> 3.0"
region = "us-east-1"
}
Resource
Resource blocks are used to manage resources such as compute instances, virtual networks, databases, buckets, or DNS resources.
This block type is the backbone of any terraform configuration because it represents actual resources with majority of other block types playing supporting role.
resource "aws_instance" "example_resource" {
ami = "ami-005e54dee72cc1d00" # us-west-2
instance_type = "t2.micro"
credit_specification {
cpu_credits = "unlimited"
}
}
Variable
Variable block provides parameters for terraform modules and allow users to customize the data provided to other terraform modules without modifying the source.
Variables are often in their own file called variables.tf.
variable "example_variable" {
type = var_type
description = var_description
default = value_1
sensitive = var_boolean_value
}
Locals
Often called local variables block, this block is used to keep frequently referenced values or expressions to keep the code clean and tidy.
These variables can be accessed using local.var_name notation, note that it is called local.
locals {
service_name = "forum"
owner = "Community Team"
instance_ids = concat(aws_instance.blue.*.id, aws_instance.green.*.id)
}
Data
Data block's primary purpose is to load or query data from APIs other than Terraform. It can be used to provide flexibility to your configuration or to connect different workspaces.
Data is then accessed using dot notation using var identifier. For example: var.variable_1.
data "data_type" "data_name" {
variable_1 = expression
}
Modules
Modules are containers for multiple resources that are used together. A module consists of .tf and/or .tf.json files stored in a directory. It is the primary way to package and reuse resources in Terraform.
Modules are a great way to compartmentalize reusable collections of resources in multiple configurations.

Output
This is a block which is almost always present in all configurations, along with main.tf and variables.tf block. It allows Terraform to output structured data about your configuration.
This output can be used by users to see data like IPs or resources names in one convenient place.
output "test_server_public_ip" {
description = "My test output for EC2 public IP"
value = aws_instance.test_web_server.public_ip
sensitive = true
}
output "public_url" {
description = "Public URL for my web server"
value = "https://${aws_instance.test_web_server.public_ip}:8000/index.html"
}
Provisioner
Provisioners allows us to specify actions to be performed on local or remote machines to prepare resources for service.
There are two types of Terraform provisioners: local-exec and remote-exec.
resource "aws_instance" "web_server" {
# ...
provisioner "local-exec" {
command = "Get-Date > completed.txt"
interpreter = ["PowerShell", "-Command"]
}
provisioner "remote-exec" {
inline = [
"chmod +x /tmp/script.sh",
"/tmp/script.sh args",
]
}
}
Sample HCL Block
# main.tf
# Define the provider
provider "aws" {
region = "us-west-2" # Specify your desired region
}
# Define the resource for the EC2 instance
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0" # Example AMI ID, change it based on your region
instance_type = "t2.micro"
tags = {
Name = "ExampleInstance"
}
}
Last updated