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 plan after -upgrade to 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:

ChangeWhy
Add or remove a required_providers entryNew provider needs to be downloaded
Change provider version constraintsDifferent version needs to be installed
Change the backend blockBackend connection must be re-established
Clone a repo for the first timeProviders are not committed to Git
Add or update a module sourceModule 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

Exercise

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?

Exercise

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?

Exercise

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?

Continue Learning

Explore Related Topics

Try the Tool

Related Resources