Skip to main content

Terraform Init

The terraform init command initialises a Terraform working directory — downloading required provider plugins, configuring the backend, and installing module dependencies. You must run terraform init before any other Terraform command when working in a new directory or after adding a new provider or module.

What Is Terraform Init?

Terraform init is the setup command. Before Terraform can do anything — plan, apply, or even validate — it needs to download the provider plugins your configuration requires and set up the backend where state will be stored. Init does all of this in one command.

Think of it like npm install. Your package.json declares dependencies; npm install downloads them. Your required_providers block declares providers; terraform init downloads them.

Running Terraform Init

Bash
# Basic init — downloads providers, configures backend, installs modules
terraform init
# Upgrade providers to latest allowed version (respects version constraints)
terraform init -upgrade
# Reinitialise without migrating state (when backend config changes)
terraform init -reconfigure
# Migrate state from old backend to new backend
terraform init -migrate-state

What Init Does — Step by Step

Bash
+------------------------------------------+
| 1. Read required_providers block |
| Finds: hashicorp/aws ~> 5.0 |
+------------------------------------------+
|
v
+------------------------------------------+
| 2. Download provider plugins |
| From: registry.terraform.io |
| To: .terraform/providers/ |
+------------------------------------------+
|
v
+------------------------------------------+
| 3. Configure backend |
| Sets up S3 remote state connection |
+------------------------------------------+
|
v
+------------------------------------------+
| 4. Install modules |
| Downloads any modules from source |
+------------------------------------------+
|
v
+------------------------------------------+
| 5. Write .terraform.lock.hcl |
| Locks exact provider versions + hashes |
+------------------------------------------+

The .terraform Directory

Bash
.terraform/
providers/
registry.terraform.io/
hashicorp/
aws/
5.31.0/
linux_amd64/
terraform-provider-aws_v5.31.0_x5 # binary plugin
modules/
vpc/ # downloaded module source
terraform.tfstate # backend config cache
Bash
# This directory should ALWAYS be in .gitignore
echo ".terraform/" >> .gitignore

The Lock File

HCL
# .terraform.lock.hcl — commit this to Git
# Records the exact provider version and platform hashes
provider "registry.terraform.io/hashicorp/aws" {
version = "5.31.0"
constraints = "~> 5.0"
hashes = [
"h1:abc123...", # hash for linux_amd64
"h1:def456...", # hash for darwin_arm64
]
}
Remember

Commit .terraform.lock.hcl to Git. This file ensures every engineer and CI/CD pipeline downloads the exact same provider version with verified hashes. Without it, a provider upgrade could silently change behaviour for one engineer but not another.

When to Re-run Init

Bash
# Always re-run init after:
# 1. Adding or changing a provider
# 2. Adding or changing a module source
# 3. Changing the backend configuration
# 4. Cloning the repo fresh on a new machine
# 5. Changing the required Terraform version

Init in CI/CD

YAML
# GitHub Actions example
- name: Terraform Init
run: terraform init
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# Or with OIDC (preferred — no long-lived keys)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/terraform-ci
aws-region: ap-south-1
- name: Terraform Init
run: terraform init

Troubleshooting Init

Error Cause Fix
Failed to query available provider packages Network issue or registry down Check internet connection; use -plugin-dir offline
Error: Failed to install provider Disk full or permissions issue Check df -h and directory write permissions
The argument -reconfigure is deprecated Old Terraform version Upgrade Terraform
Inconsistent dependency lock file Lock file out of sync with providers block Run terraform init -upgrade
Backend configuration changed Modified backend block Run terraform init -reconfigure
Common Mistake

Running terraform plan or terraform apply in a freshly cloned repo without running terraform init first. Terraform will error immediately: Error: Required plugins are not installed. Always run terraform init first in any new directory or after any CI/CD clone.

Frequently Asked Questions

What exactly does terraform init download, and why does it need to run again sometimes?

It downloads the provider plugins (versioned binaries like the aws or google provider) your configuration references into a local `.terraform` directory, initializes the configured backend, and fetches any module source code referenced by `module` blocks. You need to re-run it whenever you add a new provider or module, change backend configuration, or upgrade a provider version constraint — the `.terraform.lock.hcl` file it maintains pins exact provider versions for reproducibility across a team.

What's a common mistake that causes terraform init to behave unexpectedly in CI/CD?

Not committing `.terraform.lock.hcl` to version control, which means different pipeline runs (or different engineers) can silently resolve to different provider patch versions over time, causing plans that behave differently between environments for no visible reason in the .tf files. Always commit the lock file, and use `terraform init -upgrade` deliberately (and reviewed) when you actually want newer provider versions.