Terraform — Part 2 — Installing Terraform and Running Your First Configuration
With the concepts from Part 1 in place, this part installs the Terraform CLI on Windows, macOS, and Linux, then runs one real configuration from nothing to a finished result, without needing a cloud account to follow along.
.tf files and which commands you run against them.
Terraform ships as one executable, no separate runtime or server component required on your machine.
The single requirement for the terraform command to work from any folder in your terminal.
A plain text file holding your configuration, written in HCL, that Terraform reads when you run a command.
Introduction
Part 1 covered what Terraform is and why declarative infrastructure as code matters. None of that is useful until Terraform is actually installed and you’ve watched it do something for real.
Think of this part as unpacking the toolbox and making one trial cut. It installs the CLI, writes a minimal configuration, and runs it end to end. Part 3 opens the toolbox properly and explains what each command actually does; this part is deliberately about getting a working result first.
The example here uses the local provider instead of a cloud provider, so it needs no AWS, Azure, or GCP account and creates no billable resources. It still exercises the exact same workflow you’ll use against a real cloud provider later in this series.
Installing Terraform
Terraform installs differently depending on your operating system. All methods below install the official HashiCorp-built CLI.
brew tap hashicorp/tap followed by brew install hashicorp/tap/terraform.
On Debian and Ubuntu-based systems, install from HashiCorp’s own APT repository rather than the distro’s default package (which is often outdated or missing):
# Add HashiCorp's GPG key
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
# Add the HashiCorp APT repository
echo "deb [arch=$(dpkg --print-architecture) 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
# Install
sudo apt update && sudo apt install terraform
On RHEL and CentOS, use yum-config-manager to add the HashiCorp repo first:
# Add the HashiCorp RPM repository
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# Install
sudo yum -y install terraform
On Fedora, the equivalent uses dnf:
wget -O- https://rpm.releases.hashicorp.com/fedora/hashicorp.repo | sudo tee /etc/yum.repos.d/hashicorp.repo
sudo dnf -y install terraform
On Windows, and on any platform where a package manager isn’t an option, install manually: download the zip archive matching your OS and CPU architecture from HashiCorp’s releases site, extract it, and place the single terraform.exe (or terraform on Linux/macOS) executable somewhere on your PATH. On Windows, the extracted folder itself can simply be added to the PATH environment variable; on macOS and Linux, /usr/local/bin is the conventional destination.
# macOS/Linux manual install: move the extracted binary onto your PATH
mv ~/Downloads/terraform /usr/local/bin/
Verifying the Install
Open a new terminal session after installing — an already-open shell won’t have picked up a PATH change. Then confirm Terraform is reachable:
# Prints the Terraform CLI version and any installed provider versions
terraform version
A successful install prints something like Terraform v1.x.x on windows_amd64 (or your platform’s equivalent). If nothing is printed and you instead get a “command not found” or “not recognized” error, see the troubleshooting section below before going further.
terraform -help lists every available subcommand and confirms the CLI is working even before you’ve written any configuration.
Install-Time Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
terraform: command not found (macOS/Linux) |
The binary isn’t on a directory listed in $PATH. |
Confirm the binary’s location, then move it into a directory already on your PATH such as /usr/local/bin, or add its folder to $PATH in your shell profile. |
'terraform' is not recognized... (Windows) |
The extracted folder wasn’t added to the Windows PATH environment variable, or the terminal was opened before the PATH change. | Add the folder containing terraform.exe to PATH via System Properties -> Environment Variables, then open a brand new terminal window. |
| Old version still shows after upgrading | A previous terraform binary earlier on the PATH, or a cached shell command lookup. |
Run which terraform (macOS/Linux) or where terraform (Windows) to see which binary is actually being executed, and remove or reorder the stale one. |
| Downloaded the wrong architecture build | Apple Silicon (arm64) vs Intel (amd64) Macs, or 32-bit vs 64-bit Windows, need different binaries. | Re-download the archive matching your actual CPU architecture rather than the first one that looks close. |
| Tab completion doesn’t work | Autocomplete isn’t installed by default. | Run terraform -install-autocomplete in Bash or Zsh, then restart the shell. |
Setting Up a Project Folder
Terraform works from whichever directory you run it in — there’s no global project registry to set up first. Create an empty folder and put your .tf files inside it:
# Create and enter a new project folder
mkdir terraform-first-config
cd terraform-first-config
Writing Your First Configuration
Create a file named main.tf inside that folder with the following content. It uses the local provider, a built-in HashiCorp provider that manages files on your own machine rather than any cloud resource:
# main.tf — declares the provider this configuration needs,
# then describes one file it should create.
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
resource "local_file" "hello" {
filename = "${path.module}/hello.txt"
content = "Hello from Terraform."
}
The required_providers block tells Terraform which provider this configuration depends on and where to fetch it from. The resource block declares one local_file, giving it the local name hello and setting its two required arguments: filename, where the file should be written, and content, what it should contain.
Running It: init and apply
From inside the project folder, run two commands in order:
# Downloads the local provider plugin this configuration requires
terraform init
# Shows the planned change and, after confirming, creates the file
terraform apply
terraform init reads the required_providers block and downloads the matching provider plugin, creating a .terraform folder and a .terraform.lock.hcl lock file alongside your configuration. terraform apply then shows a plan — in this case, one resource to be added — and prompts you to type yes before it does anything. Once confirmed, it finishes with a summary line: Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
hello.txt, containing the text “Hello from Terraform.”, should now exist in the same folder.
Part 3 covers exactly what init, plan, and apply are each responsible for, why plan matters as a separate step from apply, and what terraform destroy does. For now, the point is simpler: the same three commands you just ran are the same three commands used against a real cloud provider, just with a different resource type in the configuration.
Cleaning Up
Since this configuration only created a local file, cleaning up is safe and instant:
# Removes everything this configuration created
terraform destroy
Confirm with yes when prompted, and hello.txt is deleted. This is the same command you’d run to tear down a real environment, which is exactly why it’s worth getting comfortable with it now, on something harmless.
Quick Reference Summary
| Term | Meaning |
|---|---|
terraform version |
Prints the installed Terraform CLI version and provider versions. |
terraform -help |
Lists every available subcommand. |
terraform init |
Downloads the providers a configuration requires. |
terraform apply |
Shows a plan, then carries it out after confirmation. |
terraform destroy |
Removes everything the configuration created. |
required_providers |
Block declaring which providers a configuration needs and their source/version. |
Final Thoughts
Nothing about this configuration was complicated on purpose. A working Terraform install and one successful apply is a low bar, but it’s the bar that everything else in this series builds on.
If you can install the CLI, write a small .tf file, and get through init and apply without errors, you have everything needed to follow the rest of the series on real cloud resources instead of a local file.
Terraform — Part 3 — The Core Workflow: init, plan, apply, destroy. We go deeper into what each command actually does, why plan exists as a distinct step, and how Terraform decides what needs to change.