0 of 0 complete
Getting Started Cheatsheet Providers

Getting Started with Terraform

Go from zero to deploying your first resource in minutes.

What is Terraform?

Terraform is an Infrastructure as Code (IaC) tool made by HashiCorp. Instead of clicking around in a cloud dashboard to create servers, databases, and networks, you write simple configuration files that describe what you want. Terraform then figures out how to make it happen.

Think of it like a recipe: you write down the ingredients and steps (your .tf files), and Terraform is the chef that follows the recipe to build your infrastructure. Change the recipe? Terraform updates only what changed. Delete the recipe? Terraform tears everything down.

💡 Why does this matter? IaC means your infrastructure is version-controlled, reviewable, repeatable, and shareable — just like application code. No more "I clicked a button somewhere and now things are broken."
Install Terraform

If you have Homebrew installed (and you should!), installing Terraform takes one command:

Terminal
$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform

Verify the install:

Terminal
$ terraform -version
Expected Output
Terraform v1.9.x on darwin_arm64
brew tap hashicorp/tap registers HashiCorp’s official Homebrew tap, and brew install hashicorp/tap/terraform downloads the Terraform binary from that tap and adds it to your PATH so you can run terraform from any terminal window. The -version flag confirms it is installed and shows which version you have.
Your First Terraform Config

We'll build this in three small moves: make a project folder, create an empty config file, then paste your first Terraform code into it. We'll use the local_file resource — it creates a file on your own computer, so no cloud account needed.

1. Create a project folder. mkdir makes the directory and cd moves you into it so every command you run after this happens inside the project.

Terminal
$ mkdir ~/terraform-demo && cd ~/terraform-demo

2. Create an empty main.tf file. Terraform reads every .tf file in the current folder, and main.tf is the conventional name for the primary config. touch creates the file if it doesn't exist yet.

Terminal
$ touch main.tf

3. Open main.tf in your editor and paste the code below. Use the Copy button on the top right of the block, then paste the whole thing into the empty file and save. Don't worry about the syntax yet — we'll unpack it right after.

main.tf
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

resource "local_file" "hello" {
  content  = "Hello, Terraform!"
  filename = "${path.module}/hello.txt"
}
terraform block: Tells Terraform which providers (plugins) to download before doing anything else. Here we declare we need the local provider, version 2.x. When you run terraform init in the next step, this is what drives the download.

resource block: Declares something you want Terraform to create and manage. "local_file" is the resource type (from the local provider), and "hello" is the local name you give this particular instance — you'd use it to reference the resource elsewhere in your config. Inside the braces, you set what goes in the file (content) and where it gets written (filename).
The Core Workflow: init → plan → apply → destroy

Every Terraform project follows this cycle. Let's walk through each step.

Step 1: terraform init

Initialize the project. Downloads the provider plugins you declared.

Terminal
$ terraform init
Expected Output
Initializing the backend... Initializing provider plugins... - Finding hashicorp/local versions matching "~> 2.0"... - Installing hashicorp/local v2.5.1... - Installed hashicorp/local v2.5.1 Terraform has been successfully initialized!
terraform init reads your .tf files, downloads the required providers into a .terraform/ directory, and creates a .terraform.lock.hcl lock file (like package-lock.json in Node). You only need to re-run this when you add or change providers.

Step 2: terraform plan

Preview what Terraform will do — without actually doing it.

Terminal
$ terraform plan
Expected Output
Terraform will perform the following actions: # local_file.hello will be created + resource "local_file" "hello" { + content = "Hello, Terraform!" + filename = "./hello.txt" + id = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy.
terraform plan compares your config files to the current state and shows you what would change. The + symbol means "will be created." This is your safety net — always review the plan before applying!

Step 3: terraform apply

Execute the plan. Terraform will ask you to confirm with yes.

Terminal
$ terraform apply
Expected Output
+ resource "local_file" "hello" { ... } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes local_file.hello: Creating... local_file.hello: Creation complete after 0s Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Check your folder — you should now see a hello.txt file with "Hello, Terraform!" inside it. You just created your first resource with Terraform!

Step 4: terraform destroy

Tear down everything Terraform created. It will ask for confirmation.

Terminal
$ terraform destroy
Expected Output
- resource "local_file" "hello" { ... } Plan: 0 to add, 0 to change, 1 to destroy. Do you really want to destroy all resources? Enter a value: yes local_file.hello: Destroying... local_file.hello: Destruction complete after 0s Destroy complete! Resources: 1 destroyed.
terraform destroy reads the state file to see what exists, then removes everything. The - symbol means "will be deleted." Your hello.txt file is gone. In real cloud projects, this would delete servers, databases, etc. — use with caution!
Understanding State Files

After running terraform apply, Terraform creates a file called terraform.tfstate. This is Terraform's memory — it tracks what resources exist and their current configuration.

Key things about state:

  • State maps your config to real-world resources
  • Without state, Terraform wouldn't know what it already created
  • State files can contain sensitive data — never commit them to Git
  • For teams, use remote state (S3, Terraform Cloud, etc.)
⚠️ Important: Add *.tfstate and *.tfstate.backup to your .gitignore. State files often contain secrets like passwords and API keys in plain text.
.gitignore
*.tfstate
*.tfstate.*
.terraform/
.terraform.lock.hcl
The state file is a JSON file that acts as a database of everything Terraform manages. When you run terraform plan, it compares your .tf files against the state to figure out what changed. Think of it as Terraform's "source of truth" about the real world.

Terraform Cheatsheet

Every command and syntax pattern you need, organized by category.

⚙️ Core Commands
terraform init
Initialize working directory, download providers
terraform plan
Preview changes without applying them
terraform apply
Apply changes to reach desired state
terraform destroy
Destroy all managed infrastructure
terraform validate
Check config syntax and consistency
terraform fmt
Format .tf files to canonical style
terraform show
Show current state or a saved plan
terraform output
Display output values from state
terraform refresh
Sync state with real infrastructure
terraform import <addr> <id>
Import existing resource into state
🗃️ State Commands
terraform state list
List all resources in state
terraform state show <addr>
Show attributes of a single resource
terraform state mv <src> <dst>
Rename or move a resource in state
terraform state rm <addr>
Remove a resource from state (not infra)
terraform state pull
Download and print remote state
terraform state push
Upload local state to remote backend
📁 Workspace Commands
terraform workspace list
List all workspaces
terraform workspace new <name>
Create a new workspace
terraform workspace select <name>
Switch to an existing workspace
terraform workspace delete <name>
Delete an empty workspace
terraform workspace show
Show current workspace name
🔢 Variables & Outputs
variable "name" { ... }
Declare an input variable with type and default
terraform.tfvars
Auto-loaded file for variable values
-var="key=value"
Set a variable via command line flag
-var-file="file.tfvars"
Load variables from a specific file
output "name" { ... }
Declare an output value to display after apply
sensitive = true
Hide variable/output values in CLI output
📝 HCL Syntax Blocks
resource "type" "name" { }
Create and manage an infrastructure object
data "type" "name" { }
Read info from an existing resource
module "name" { source = "..." }
Use a reusable group of resources
locals { key = value }
Define local computed values
provider "name" { }
Configure a provider (credentials, region)
terraform { ... }
Settings: required version, backend, providers
🔧 Useful Flags
-auto-approve
Skip the yes/no confirmation prompt
-target=resource.name
Apply/destroy only a specific resource
-out=plan.tfplan
Save a plan to a file for later apply
-json
Output in machine-readable JSON
-parallelism=n
Limit concurrent operations (default 10)
-compact-warnings
Show warnings in a more compact form

Terraform Providers

Providers are plugins that let Terraform talk to APIs — clouds, SaaS tools, and more.

What Are Providers?

A provider is a Terraform plugin that knows how to talk to a specific API. Want to create an AWS EC2 instance? You need the AWS provider. Want to manage a GitHub repo? You need the GitHub provider. Each provider adds resource types and data sources you can use in your config.

Providers are declared in your terraform { required_providers { } } block and downloaded automatically when you run terraform init. Most are maintained by HashiCorp or the service vendor and are published to the Terraform Registry.

☁️ AWS
Manages EC2, S3, RDS, Lambda, IAM, VPC, CloudFront, and 1000+ AWS services.
Example Resource
resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t2.micro" }
Source: hashicorp/aws
☁️ Azure
Manages VMs, App Services, Azure SQL, Storage Accounts, AKS, and more.
Example Resource
resource "azurerm_resource_group" "rg" { name = "my-resources" location = "East US" }
Source: hashicorp/azurerm
☁️ Google Cloud (GCP)
Manages Compute Engine, GKE, Cloud SQL, BigQuery, Cloud Storage, and more.
Example Resource
resource "google_compute_instance" "vm" { name = "my-vm" machine_type = "e2-micro" zone = "us-central1-a" }
Source: hashicorp/google
☸️ Kubernetes
Manages namespaces, deployments, services, config maps, secrets, and K8s objects.
Example Resource
resource "kubernetes_namespace" "ns" { metadata { name = "my-app" } }
Source: hashicorp/kubernetes
🐳 Docker
Manages containers, images, networks, and volumes on a Docker host.
Example Resource
resource "docker_container" "nginx" { image = docker_image.nginx.image_id name = "my-nginx" ports { internal = 80 external = 8080 } }
Source: kreuzwerker/docker
🐙 GitHub
Manages repos, teams, branch protections, actions secrets, and org settings.
Example Resource
resource "github_repository" "repo" { name = "my-project" description = "Managed by Terraform" visibility = "private" }
Source: integrations/github
Cloudflare
Manages DNS records, page rules, Workers, WAF, tunnels, and zero trust.
Example Resource
resource "cloudflare_record" "www" { zone_id = var.zone_id name = "www" content = "203.0.113.50" type = "A" }
Source: cloudflare/cloudflare
📊 Datadog
Manages monitors, dashboards, SLOs, downtimes, and alert configurations.
Example Resource
resource "datadog_monitor" "cpu" { name = "High CPU Usage" type = "metric alert" query = "avg(last_5m):avg:system.cpu.user{*} > 90" message = "CPU is above 90%!" }
Source: DataDog/datadog
Helm
Manages Helm chart releases on Kubernetes clusters.
Example Resource
resource "helm_release" "nginx" { name = "nginx-ingress" repository = "https://charts.bitnami.com" chart = "nginx" namespace = "default" }
Source: hashicorp/helm
🔐 Vault
Manages secrets engines, auth methods, policies, and secret values.
Example Resource
resource "vault_generic_secret" "db" { path = "secret/database" data_json = jsonencode({ username = "admin" password = var.db_password }) }
Source: hashicorp/vault
💡 There are 4,000+ providers in the Terraform Registry. If a service has an API, there's probably a Terraform provider for it.