Copyright (c) 2026 MindMesh Academy. All rights reserved. This content is proprietary and may not be reproduced or distributed without permission.

2.1.2. Installing and Versioning Providers

💡 First Principle: You declare which providers you need and which versions are acceptable in code, and terraform init resolves those constraints into a concrete download — so installation is a reproducible consequence of your configuration, not a manual setup step.

Providers are declared in a required_providers block inside the terraform block, each with a source address and a version constraint:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"   # shorthand for registry.terraform.io/hashicorp/aws
      version = "~> 5.0"          # any 5.x, but not 6.0
    }
  }
}

The source address has three parts — [hostname/]namespace/type — defaulting to the public registry when the hostname is omitted. The version constraint controls which releases are allowed. Running terraform init reads these constraints, picks the newest matching version, and downloads it into the .terraform directory.

OperatorMeaningExample
= (or none)Exact version= 5.31.0
>= / <=Minimum / maximum>= 5.0
> / <Strictly greater / less< 6.0
!=Excludes a version!= 5.30.0
~>Pessimistic: allows rightmost part to increment~> 5.4 allows 5.x ≥ 5.4, not 6.0

⚠️ Exam Trap: The pessimistic constraint ~> is heavily tested. ~> 5.4 permits 5.4, 5.5, 5.99 — anything in the 5.x line at or above 5.4 — but not 6.0. By contrast ~> 5.4.0 only permits 5.4.x patch releases. Read the number of segments carefully.

Reflection Question: Given the constraint ~> 1.2, which of these would Terraform allow: 1.1.0, 1.3.5, 2.0.0? Explain why for each.

Alvin Varughese
Written byAlvin Varughese
Founder18 professional certifications