terraform init
Learn exactly what terraform init does, downloading providers, setting up backends, creating the lock file, and how to use init flags like -upgrade and -reconfigure.
What Is terraform init?
terraform init is the very first command you run in any Terraform project. It prepares your working directory so that every other Terraform command (plan, apply, destroy) can work correctly.
Think of it like npm install or pip install, it sets up the dependencies your project needs before you can do anything else.
terraform init
What terraform init Does Internally
When you run terraform init, Terraform does three things:
1. Downloads Provider Plugins
Terraform reads the required_providers block in your configuration and downloads the declared providers from the Terraform Registry (or a private registry):
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "3.6.0"
}
}
}
Running init on this configuration downloads both the AWS and Random providers into .terraform/providers/. This directory can be hundreds of megabytes, always add it to .gitignore.
Sample output:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Finding hashicorp/random versions matching "3.6.0"...
- Installing hashicorp/aws v5.54.1...
- Installing hashicorp/random v3.6.0...
Terraform has been successfully initialized!
2. Sets Up the Backend
If you have a backend block configured, init connects to it and migrates state if needed:
terraform {
backend "s3" {
bucket = "my-tfstate-bucket"
key = "production/terraform.tfstate"
region = "us-east-1"
}
}
When switching from local state to a remote backend, init asks:
Do you want to copy existing state to the new backend?
yes/no:
3. Creates the Lock File
terraform init writes .terraform.lock.hcl, a file that pins the exact provider versions downloaded:
# .terraform.lock.hcl (auto-generated)
provider "registry.terraform.io/hashicorp/aws" {
version = "5.54.1"
constraints = "~> 5.0"
hashes = [
"h1:abc123...",
]
}
Always commit .terraform.lock.hcl to Git. It ensures every team member and every CI/CD pipeline uses exactly the same provider versions, preventing "works on my machine" failures caused by version drift.
The .terraform Directory
After init, your project will have:
my-project/
├── main.tf
├── variables.tf
├── .terraform/ # ← created by init, add to .gitignore
│ ├── providers/
│ │ └── registry.terraform.io/
│ │ └── hashicorp/
│ │ └── aws/5.54.1/ # downloaded provider binary
│ └── terraform.tfstate # backend config cache
└── .terraform.lock.hcl # ← commit this to Git
Common init Flags
-upgrade
Re-download all providers, selecting the newest version that satisfies your constraints:
terraform init -upgrade
Use this when you want to update providers to the latest allowed version. Without -upgrade, init uses the versions already in the lock file.
Warning: Always run
terraform planafter-upgradeto check for breaking changes in the new provider version.
-reconfigure
Force init to reconfigure the backend without migrating state:
terraform init -reconfigure
Useful when you have changed your backend configuration and want to switch without copying existing state.
-backend=false
Skip backend initialisation entirely:
terraform init -backend=false
Useful in CI pipelines where you only want to validate the configuration without connecting to a remote backend.
-backend-config
Pass backend configuration values at init time instead of hardcoding them in the backend block, great for keeping bucket names or credentials out of source code:
terraform init \
-backend-config="bucket=my-tfstate-bucket" \
-backend-config="key=production/terraform.tfstate" \
-backend-config="region=us-east-1"
When to Re-run init
You must re-run terraform init whenever you:
| Change | Why |
|---|---|
Add or remove a required_providers entry | New provider needs to be downloaded |
Change provider version constraints | Different version needs to be installed |
Change the backend block | Backend connection must be re-established |
| Clone a repo for the first time | Providers are not committed to Git |
Add or update a module source | Module code needs to be downloaded |
It is always safe to re-run init, it never modifies your infrastructure.
init in CI/CD Pipelines
In a CI/CD pipeline, always run init before plan or apply. Use the -input=false flag to prevent interactive prompts:
# GitLab CI example
terraform-plan:
script:
- terraform init -input=false
- terraform plan -out=tfplan
Knowledge Check
Question 1: Lock File Purpose
After running terraform init, you see a .terraform.lock.hcl file. A teammate asks if they should commit it. What do you tell them?
Question 2: When to Re-run init
You add a new provider to required_providers in your main.tf. You run terraform plan immediately. What happens?
Question 3: terraform init -upgrade
Your lock file pins AWS provider at v5.0.0. A new version v5.54.1 is available. You want to update. What command do you run?