Guides / Infrastructure as Code

How to Install & Set Up Terraform

Install HashiCorp Terraform from the official APT/Homebrew repositories, understand the core workflow and state model, and provision your first resources.

Updated 202611-step setupDownload Terraform →

Prerequisites

  • ✓Linux, macOS, or Windows — Terraform ships as a single static binary, no runtime to install alongside it
  • ✓For the walkthrough below: nothing extra. It uses the local provider, so no cloud account or credentials are required to follow along
  • ✓For real infrastructure afterward: credentials for whichever platform you plan to manage — AWS, Azure, GCP, and dozens of others each have their own Terraform provider

What Terraform actually does

Terraform is a declarative infrastructure-as-code tool: instead of scripting the steps to create a server, you describe the end state you want in HCL (HashiCorp Configuration Language), and Terraform figures out what needs to change to get there. Each platform — AWS, Cloudflare, Kubernetes, even a local filesystem — is represented by a provider, a plugin that translates your HCL resource blocks into real API calls.

The piece that makes this work is the state file. Every time you apply a configuration, Terraform records what it believes exists — resource IDs, attributes, dependency graph — into terraform.tfstate. Every subsequent plan diffs your configuration against that state (not against the real world directly) to figure out what to create, change, or destroy.

The core workflow: init, plan, apply, destroy

  • •terraform init — downloads the providers your configuration references and sets up the local .terraform directory. Run it once per project, and again whenever you add a provider or backend.
  • •terraform plan — computes a dry-run diff between your configuration and the current state, without touching anything. Always read the plan output before applying it.
  • •terraform apply — re-runs the plan and, after you confirm, actually creates/updates/destroys resources through each provider's API, then updates the state file to match.
  • •terraform destroy — the reverse: tears down every resource Terraform is tracking in the current state. Use it freely on throwaway environments, very carefully on anything else.

Install on Ubuntu/Debian (HashiCorp APT repo)

terminal
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

Install on RHEL, CentOS Stream, Fedora, or Amazon Linux (HashiCorp YUM repo)

terminal
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform
!

dnf works identically to yum here (dnf install terraform) on Fedora and modern RHEL/CentOS Stream releases.

Install with a package manager

macOS (Homebrew)
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Windows (Chocolatey)
choco install terraform

Any Linux distro — the generic binary zip

No repo, no package manager, works on anything: HashiCorp publishes every Terraform release as a plain zip of a single static binary.

terminal
curl -LO https://releases.hashicorp.com/terraform/1.9.8/terraform_1.9.8_linux_amd64.zip
unzip terraform_1.9.8_linux_amd64.zip
sudo mv terraform /usr/local/bin/

Verify the installation

terminal
terraform -version

Your first configuration — no cloud account needed

The hashicorp/local provider manages files on your own disk, which makes it the cleanest way to run the full init → plan → apply → destroy loop for the first time without wiring up AWS or any other account.

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

resource "local_file" "hello" {
  filename = "${path.module}/hello.txt"
  content  = "Managed by Terraform since ${timestamp()}"
}
run the workflow
terraform init
terraform plan
terraform apply -auto-approve
cat hello.txt
terraform destroy -auto-approve
!

terraform apply -auto-approve skips the interactive yes/no confirmation — handy for a first test or CI, but drop the flag once you're applying anything you actually care about.

State: where it lives and why it needs a backend

By default Terraform writes state to a local terraform.tfstate file, which works fine solo but breaks down the moment a second person or a CI pipeline needs to run the same configuration — nothing prevents two concurrent applies from stepping on each other. A remote backend (S3 with a DynamoDB lock table, Terraform Cloud, Azure Blob Storage, and others) moves state off your laptop and adds locking so only one apply can run at a time.

State files can contain sensitive values in plain text (database passwords, private keys generated by a resource), so they belong in a backend with encryption and tightly scoped access — never committed to Git.

example: S3 remote backend
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/network.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}
inspect state without editing it by hand
terraform state list
terraform show

Everyday commands

  • •terraform fmt — rewrites .tf files to the canonical HCL style; run it before every commit.
  • •terraform validate — checks the configuration is internally consistent (types, required arguments) without contacting any provider.
  • •terraform workspace new staging / terraform workspace select staging — keeps separate state per environment from a single configuration.
  • •terraform output — prints the values from any output blocks after an apply, useful for wiring one configuration's results into another.

Reusing configuration with modules

A module is just a directory of .tf files that takes input variables and exposes output values — the same mental model as a function. The root configuration you run terraform apply from is itself a module; anything you call with a module block is a child module. Pulling in a well-maintained module from the public Terraform Registry is usually faster and safer than hand-rolling the same VPC or Kubernetes cluster setup from scratch.

!

Terraform is licensed under the BUSL as of v1.6, so it's no longer OSI-approved open source. If that matters for your project, see the OpenTofu guide — a drop-in, fully open source fork with the same CLI and HCL syntax.

Documentation & Knowledge Base

Official DocumentationTerraform Documentation →Knowledge Base & CommunityHashiCorp Discuss — Terraform →
Download Terraform— all versions & official links→

Related Guides

OpenTofuInstall guide →PulumiInstall guide →HashiCorp VaultInstall guide →

Need Terraform deployed and managed for you?

We're OpenStack Dev — we design, deploy, and operate production DevOps infrastructure.

Get in TouchAll Install Guides