Terraform Commands Cheat Sheet: init, plan, apply, destroy, and More
Complete Terraform commands reference. Learn terraform init, plan, apply, destroy, state, import, output, workspace, fmt, validate
HCL
Learn HCL (HashiCorp Configuration Language) for Terraform. Covers syntax, data types, variables, blocks, expressions, functions
HCL (HashiCorp Configuration Language) is the declarative language used to write Terraform configurations. It's designed to be human-readable while remaining machine-parseable — you describe what you want, and Terraform figures out how to create it.
HCL files use the .tf extension. If you've seen Terraform code, you've seen HCL:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "my-server"
}
}Terraform also accepts JSON (.tf.json files), but HCL is the standard:
HCL (readable):
resource "aws_instance" "web" {
ami = "ami-12345"
instance_type = "t3.micro"
}JSON (verbose):
{
"resource": {
"aws_instance": {
"web": {
"ami": "ami-12345",
"instance_type": "t3.micro"
}
}
}
}Use HCL for human-written configs. Use JSON only for machine-generated configs.
# Single-line comment
// Also a single-line comment
/*
Multi-line
comment
*/ami = "ami-12345" # String
count = 3 # Number
enabled = true # BooleanBlocks are containers for related configuration. They have a type, optional labels, and a body:
# Block with two labels
resource "aws_instance" "web" {
ami = "ami-12345"
}
# Block with one label
variable "instance_type" {
default = "t3.micro"
}
# Block with no labels
terraform {
required_version = ">= 1.5"
}resource "aws_instance" "web" {
ami = "ami-12345"
instance_type = "t3.micro"
root_block_device {
volume_size = 20
volume_type = "gp3"
}
tags = {
Name = "web-server"
}
}| Type | Example | Description |
|---|---|---|
string | "hello" | Text |
number | 42, 3.14 | Integer or float |
bool | true, false | Boolean |
List (ordered sequence):
variable "availability_zones" {
type = list(string)
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
# Access by index
availability_zones[0] # "us-east-1a"Map (key-value pairs):
variable "instance_tags" {
type = map(string)
default = {
Name = "web-server"
Environment = "production"
}
}
# Access by key
instance_tags["Name"] # "web-server"Set (unique unordered values):
variable "allowed_ports" {
type = set(number)
default = [80, 443, 8080]
}Object (structured type with named attributes):
variable "server_config" {
type = object({
name = string
instance_type = string
disk_size = number
public = bool
})
default = {
name = "web"
instance_type = "t3.micro"
disk_size = 20
public = true
}
}Tuple (fixed-length sequence with different types):
variable "mixed" {
type = tuple([string, number, bool])
default = ["hello", 42, true]
}resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
tags = {
Environment = "production"
}
}data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
# Reference: data.aws_ami.ubuntu.idvariable "environment" {
type = string
description = "Deployment environment"
default = "dev"
validation {
condition = contains(["dev", "staging", "production"], var.environment)
error_message = "Environment must be dev, staging, or production."
}
}output "instance_ip" {
value = aws_instance.web.public_ip
description = "The public IP of the web server"
}locals {
common_tags = {
Project = "my-app"
Environment = var.environment
ManagedBy = "terraform"
}
name_prefix = "${var.project}-${var.environment}"
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = local.common_tags
}module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
}provider "aws" {
region = "us-east-1"
}terraform {
required_version = ">= 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state"
key = "global/s3/terraform.tfstate"
region = "us-east-1"
}
}name = "web-${var.environment}"
# Result: "web-production"instance_type = var.environment == "production" ? "t3.large" : "t3.micro"# Transform a list
upper_names = [for name in var.names : upper(name)]
# Filter a list
long_names = [for name in var.names : name if length(name) > 5]
# Transform a map
tagged = {for k, v in var.servers : k => "${v}-tagged"}# Get all IDs from a list of resources
instance_ids = aws_instance.web[*].idHCL includes many built-in functions:
upper("hello") # "HELLO"
lower("HELLO") # "hello"
format("Hello, %s!", "world") # "Hello, world!"
join(", ", ["a", "b", "c"]) # "a, b, c"
split(",", "a,b,c") # ["a", "b", "c"]
replace("hello", "l", "L") # "heLLo"
trimspace(" hello ") # "hello"max(5, 12, 9) # 12
min(5, 12, 9) # 5
ceil(4.3) # 5
floor(4.7) # 4
abs(-5) # 5length(["a", "b", "c"]) # 3
contains(["a", "b"], "a") # true
merge({a=1}, {b=2}) # {a=1, b=2}
lookup({a=1, b=2}, "a", 0) # 1
flatten([[1,2],[3,4]]) # [1,2,3,4]
keys({a=1, b=2}) # ["a", "b"]
values({a=1, b=2}) # [1, 2]tostring(42) # "42"
tonumber("42") # 42
tobool("true") # true
tolist(toset([1,2])) # [1, 2]
tomap({a = "b"}) # {a = "b"}jsonencode({name = "hello"}) # '{"name":"hello"}'
jsondecode("{\"name\":\"hello\"}") # {name = "hello"}
base64encode("hello") # "aGVsbG8="
base64decode("aGVsbG8=") # "hello"Test functions in the Terraform console:
$ terraform console
> upper("hello")
"HELLO"
> length([1, 2, 3])
3resource "aws_instance" "web" {
count = 3
ami = "ami-12345"
instance_type = "t3.micro"
tags = {
Name = "web-${count.index}"
}
}resource "aws_instance" "web" {
for_each = toset(["app", "api", "worker"])
ami = "ami-12345"
instance_type = "t3.micro"
tags = {
Name = each.value
}
}See our detailed guide: Terraform count and for_each Explained
Learn by doing with interactive courses on CopyPasteLearn:
HCL is the foundation of every Terraform project. It's designed to be readable and declarative — you describe your desired infrastructure state, and Terraform handles the rest. Master the block types (resource, data, variable, output, locals), understand the type system, and use expressions and functions to keep your configurations DRY and maintainable.
Complete Terraform commands reference. Learn terraform init, plan, apply, destroy, state, import, output, workspace, fmt, validate
Install and run Terraform on Ubuntu 26.04 LTS Resolute Raccoon. Covers sudo-rs as default, APT 3.2 rollback, Kernel 7.0, Wayland-only, ROCm, and building...
Set up Terraform with Microsoft Azure from scratch. Covers Azure CLI login, service principal, provider configuration, resource groups, and first deployment.
Learn the purpose and benefits of Terraform modules and how they enhance reusability, organization, and scalability in managing infrastructure as code.