Chapter 1: Foundations
Topic 04

Installing Terraform and the CLI

ToolingCLI

Terraform ships as a single static binary with no runtime dependency — no language interpreter to install, nothing to compile. Getting it onto a machine is genuinely trivial, which is why this topic spends most of its time on the part that actually causes trouble: keeping everyone on a team running the same version so their plans agree.

A version mismatch is not cosmetic. A newer Terraform can write a state file an older one refuses to read, and two versions can plan the same configuration differently. The install is a five-minute job; version discipline is the lesson worth keeping.

Installing the Binary

On Linux, add HashiCorp's official apt or yum repository and install the terraform package. On macOS, use Homebrew's HashiCorp tap. On Windows, use the installer or a package manager like Chocolatey. In every case the result is one binary on your PATH; confirm it with terraform version, which prints both the core version and the versions of any installed providers.

Avoid installing from a random script or an unofficial package — those drift stale and can miss the features your configuration relies on. When you install outside the official repos, verify the download's checksum and signature, because this binary will hold credentials and change your infrastructure.

Version Management Across a Team

Different engineers running different Terraform versions is the quiet source of "works on my machine" infrastructure bugs. Two tools solve it: a version manager like tfenv or mise that pins and switches the version per project automatically, and the required_version setting inside the configuration, which makes Terraform refuse to run under a version outside the allowed range.

The block below pins both the Terraform core version and a provider version. With this committed, anyone — including CI — who runs an incompatible Terraform gets a clear, early error instead of a subtly different plan. Pin the version on day one; retrofitting it after a state file has been written by several versions is harder.

Pinning the Terraform and provider versions
terraform {
  required_version = "~> 1.13"          # require Terraform 1.x at this minor or newer
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

The Command Surface

The daily vocabulary is small. init downloads providers and sets up the backend; plan previews changes; apply makes them; destroy tears them down. Around those four sit fmt (format), validate (check consistency), state (inspect and surgically edit state), and output (read computed values). That is nearly the entire set of commands you use in a normal week; the rest are specialized tools you reach for occasionally.

CLI Configuration and Shell Integration

A few settings, configured once, smooth daily use. The CLI configuration file (.terraformrc) can define a shared plugin cache so providers are downloaded once and reused across projects, point at provider mirrors for air-gapped environments, and set credentials helpers. Tab completion and the TF_* environment variables (such as TF_VAR_ for inputs and TF_LOG for debugging) round out the setup.

One flag worth knowing early is -chdir, which runs Terraform against another directory without first cd-ing into it. It is safer than changing directories by hand, where it is easy to run the wrong environment's configuration from the wrong place.

Common Mistakes
  • Letting each engineer run a different Terraform version, so plans differ between machines and CI and a state file gets written by a newer version others cannot read.
  • Installing via a random script or unofficial package and ending up on a stale version missing features the configuration needs.
  • Ignoring required_version and discovering mid-incident that only one person has the version that can run the apply.
  • Running Terraform from whatever directory you happen to be in instead of using -chdir, then applying the wrong environment.
  • Skipping checksum or signature verification when installing the binary outside the official package repositories.
Best Practices
  • Set a required_version constraint in every project so an incompatible core version refuses to run, and pin the exact version everyone (including CI) uses with a version manager.
  • Use a version manager (tfenv or mise) so switching between projects on different versions is automatic.
  • Enable a shared plugin cache (plugin_cache_dir) to avoid re-downloading providers on every init.
  • Verify the binary's checksum and signature when installing outside the official repos.
  • Install from HashiCorp's official package repositories so you stay on a current, supported version.
Comparable tools tfenv · mise version managers, like nvm or rbenv for languages Pulumi CLI needs a language runtime alongside it CloudFormation no local binary — it runs inside AWS

Knowledge Check

Why does version skew across a team cause real problems, not just inconvenience?

  • A newer version can write a state file an older one cannot read, and versions can plan the same config differently
  • Each Terraform version silently downloads its own incompatible copy of the AWS provider, breaking every teammate's plan
  • Older versions cannot connect to the internet to fetch providers
  • It only matters for the paid HCP Terraform service

What does the required_version setting do?

  • Makes Terraform refuse to run when the core version falls outside the allowed range
  • Automatically downloads and upgrades the Terraform core binary to the exact version specified in the block
  • Pins the AWS provider version only
  • Locks the state file so no other version can read it

What is the purpose of a shared plugin cache?

  • To download each provider once and reuse it across projects instead of re-downloading on every init
  • To store the state file locally between runs
  • To cache plan output so apply runs faster
  • To keep multiple Terraform core versions installed side by side and switch between them per project automatically

You got correct