DevTools

Cheatsheet Terraform

Infraestrutura como código para provisionar cloud e serviços

Back to languages
Terraform
34 cards found
Categories:
Versions:

CLI


5 cards
Initialize
terraform init
terraform init -upgrade
terraform init -backend=false

Initialize the directory and providers.

Output and Inspection
terraform output
terraform output public_ip
terraform show
terraform state list

See outputs and the current state.

Plan and Apply
terraform plan
terraform plan -out=plan.tfplan
terraform apply
terraform apply plan.tfplan
terraform apply -auto-approve

Preview and apply changes.

Destroy
terraform destroy
terraform destroy -target=aws_instance.web
terraform destroy -auto-approve

Remove all the infrastructure.

Formatting and Validation
terraform fmt
terraform fmt -check
terraform validate
terraform plan -detailed-exitcode

Format and validate code.

HCL and Blocks


4 cards
File Structure
main.tf       # main resources
variables.tf  # input variables
outputs.tf    # outputs
providers.tf  # provider configuration
terraform.tfvars # values
modules/      # reusable modules

Project organization.

Data Types
string  = "text"
number  = 42
bool    = true
list    = ["a", "b", "c"]
map     = { key = "value" }
object  = { name = "x", port = 80 }
tuple   = [1, "two", true]

Types available in HCL.

Expressions
var.name
local.config
resource.type.name.attribute
data.type.name.attribute
module.name.output
terraform.workspace

References to values.

Dynamic Blocks
dynamic "ingress" {
  for_each = var.ports
  content {
    from_port   = ingress.value
    to_port     = ingress.value
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Generate repeated blocks.

Resources


5 cards
Define a Resource
resource "aws_instance" "web" {
  ami           = "ami-12345"
  instance_type = "t3.micro"

  tags = {
    Name = "Web Server"
  }
}

Create an infrastructure resource.

Lifecycle
resource "aws_instance" "web" {
  # ...
  lifecycle {
    create_before_destroy = true
    prevent_destroy       = true
    ignore_changes       = [tags]
  }
}

Control the lifecycle.

Data Sources
data "aws_ami" "ubuntu" {
  most_recent = true
  owners     = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu-*-22.04-*"]
  }
}

Read existing data.

Dependencies
resource "aws_instance" "app" {
  # implicit dependency
  subnet_id = aws_subnet.main.id

  # explicit dependency
  depends_on = [aws_iam_role.app]
}

Creation order.

for_each and count
resource "aws_instance" "servers" {
  for_each = toset(["web", "api", "db"])
  instance_type = "t3.micro"
  tags = { Name = each.value }
}

resource "aws_subnet" "sub" {
  count = 3
  cidr_block = "10.0.${count.index}.0/24"
}

Create multiple instances.

Variables and Outputs


4 cards
Define Variables
variable "instance_type" {
  description = "Instance type"
  type        = string
  default     = "t3.micro"
}

variable "ports" {
  type = list(number)
  default = [80, 443]
}

Module/project inputs.

Validation
variable "env" {
  type = string
  validation {
    condition = contains(
      ["dev", "staging", "prod"],
      var.env)
    error_message = "Invalid env."
  }
}

Validate inputs.

Outputs
output "public_ip" {
  description = "Server IP"
  value       = aws_instance.web.public_ip
}

output "config" {
  value      = aws_instance.web
  sensitive = true
}

Export values.

Locals
locals {
  project_name = "my-app"
  common_tags = {
    Project = local.project_name
    Env     = var.environment
  }
  subnets = [
    for i in range(3) :
    "10.0.${i}.0/24"
  ]
}

Internal computed values.

Modules


4 cards
Use a Module
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
  azs  = ["eu-west-1a", "eu-west-1b"]
}

Use a module from the registry.

Local Module
module "app" {
  source = "./modules/app"

  name          = "web"
  instance_type = "t3.small"
  subnet_id     = module.vpc.private_subnets[0]
}

Custom local module.

Create a Module
# modules/app/main.tf
variable "name" { type = string }
variable "instance_type" { type = string }

resource "aws_instance" "this" {
  instance_type = var.instance_type
}

output "id" {
  value = aws_instance.this.id
}

Structure of a module.

Module Sources
source = "./modules/local"
source = "terraform-aws-modules/vpc/aws"
source = "github.com/user/repo//dir"
source = "s3::https://s3-eu-west-1.amazonaws.com/bucket/module.zip"
source = "git::https://github.com/user/repo.git?ref=v1.0"

Available origins.

State


4 cards
State Commands
terraform state list
terraform state show aws_instance.web
terraform state mv old new
terraform state rm aws_instance.web
terraform state pull > backup.json

Manage the state.

Remote Backend (S3)
terraform {
  backend "s3" {
    bucket          = "my-tf-state"
    key            = "prod/terraform.tfstate"
    region          = "eu-west-1"
    dynamodb_table  = "tf-locks"
    encrypt         = true
  }
}

Shared state with locking.

Import Resources
terraform import aws_instance.web i-12345

# or with an import block (TF 1.5+):
import {
  to = aws_instance.web
  id = "i-12345"
}

Adopt existing resources.

Refresh and Taint
terraform refresh
terraform apply -refresh-only
terraform taint aws_instance.web
terraform untaint aws_instance.web

Sync and mark for recreation.

Providers


4 cards
Configure a Provider
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "eu-west-1"
}

Define the provider and version.

Multiple Providers
provider "aws" {
  region = "eu-west-1"
}

provider "aws" {
  alias  = "us"
  region = "us-east-1"
}

resource "aws_instance" "dr" {
  provider = aws.us
}

Use multiple regions/accounts.

Terraform Version
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws    = { version = "~> 5.0" }
    random = { version = "~> 3.5" }
  }
}

Pin versions.

Common Providers
hashicorp/aws
hashicorp/azurerm
hashicorp/google
hashicorp/kubernetes
hashicorp/helm
hashicorp/null   (provisioners)
hashicorp/random

Popular providers.

Advanced


4 cards
Workspaces
terraform workspace list
terraform workspace new staging
terraform workspace select prod
terraform workspace show

# use in code:
name = "${terraform.workspace}-app"

Isolated environments.

Useful Functions
join("-", ["a", "b"])     # "a-b"
lookup(map, key, default)
merge(map1, map2)
length(list)
format("%s-%s", a, b)
try(expr, fallback)
coalesce(a, b, c)

Manipulation functions.

Provisioners
resource "aws_instance" "web" {
  # ...
  provisioner "remote-exec" {
    inline = [
      "sudo apt update",
      "sudo apt install -y nginx"
    ]
  }
  connection {
    type        = "ssh"
    user        = "ubuntu"
    private_key = file("~/.ssh/id_rsa")
  }
}

Run after creation.

Best Practices
# • Use remote state with locking
# • Small, reusable modules
# • Variables with description and type
# • terraform fmt + validate in CI
# • Never commit .tfstate
# • Use pinned provider versions
# • Separate by environment (workspaces or dirs)

Usage recommendations.