terraform init
terraform init is always the first command you run in a Terraform project. It sets up the working directory by downloading providers, configuring the backend, and installing any referenced modules. Nothing else works until init completes successfully.
What terraform init Does
terraform initUnder the hood, init performs three distinct operations in sequence:
1. Backend Initialization
Configures where Terraform stores its state file. If using the default local backend, this creates a terraform.tfstate file in the working directory. For remote backends (S3, Terraform Cloud), this establishes the connection.
2. Provider Plugin Download
Downloads provider plugins required by required_providers blocks. Plugins are stored in .terraform/providers/ and are platform-specific binaries (different downloads for macOS ARM vs. Linux x86_64).
3. Module Installation
Downloads any external modules referenced with source pointing to a registry, git URL, or local path. Module code is cached in .terraform/modules/.
Output Explained
$ terraform init
Initializing the backend...Successfully configured the backend "s3"! Terraform will automaticallyuse this backend unless the backend configuration changes.
Initializing provider plugins...- Finding hashicorp/aws versions matching "~> 5.50"...- Installing hashicorp/aws v5.54.1...- Installed hashicorp/aws v5.54.1 (signed, key ID 34365D9472D7468F)
Terraform has created a lock file .terraform.lock.hcl to record the providerselections made above. Include this file in your version control repositoryso that Terraform can guarantee to make the same selections by default whenyou run "terraform init" in the future.
Terraform has been successfully initialized!The Lock File: .terraform.lock.hcl
init creates or updates .terraform.lock.hcl, which records exact provider versions and checksums:
# .terraform.lock.hcl — ALWAYS commit this to gitprovider "registry.terraform.io/hashicorp/aws" { version = "5.54.1" constraints = "~> 5.50" hashes = [ "h1:bF6...", # Hash for current platform "zh:abc...", # zh: hashes are canonical across platforms ]}By committing this file, you guarantee that every team member and CI/CD runner uses the same provider version, preventing “works on my machine” issues.
Key Flags
# Upgrade providers to latest within constraintsterraform init -upgrade
# Reconfigure backend (e.g., moved state file location)terraform init -reconfigure
# Skip backend setup (useful for local testing without remote state)terraform init -backend=false
# Pass backend config inline (avoids hardcoding in .tf files)terraform init \ -backend-config="bucket=my-state-bucket" \ -backend-config="key=prod/terraform.tfstate" \ -backend-config="region=us-east-1"
# Non-interactive mode for CI pipelinesterraform init -input=false
# Specify directoryterraform init path/to/moduleBackend Configuration Patterns
Local Backend (Default)
# No backend block needed — state lives in terraform.tfstateS3 Backend
terraform { backend "s3" { bucket = "my-terraform-state" key = "environments/production/terraform.tfstate" region = "us-east-1" dynamodb_table = "terraform-state-lock" encrypt = true }}Terraform Cloud Backend
terraform { cloud { organization = "my-org" workspaces { name = "production" } }}Partial Backend Config (recommended for teams)
Avoid hardcoding backend details by providing them at init time:
# versions.tf — skeleton onlyterraform { backend "s3" {}}# backend.hcl — stored separately, not committed if sensitivebucket = "my-terraform-state"key = "production/terraform.tfstate"region = "us-east-1"dynamodb_table = "terraform-state-lock"terraform init -backend-config=backend.hclCommon init Errors and Fixes
Error: No valid credential sources found
Error: configuring Terraform AWS Provider: no valid credential sources foundFix: Configure AWS credentials via environment variables, ~/.aws/credentials, or IAM role.
Error: Backend configuration changed
Error: Backend configuration changedFix: Run terraform init -reconfigure to acknowledge the backend change.
Error: Could not retrieve the list of available versions
Error: Failed to query available provider packagesFix: Check network connectivity; corporate proxies may need HTTPS_PROXY set.
Error: Module not found
Error: Module not installedFix: The module source changed or was added. Run terraform init again.
When to Re-run terraform init
| Situation | Action |
|---|---|
| New provider added | terraform init |
| Provider version changed in lock file | terraform init -upgrade |
| New module source added | terraform init |
| Backend configuration changed | terraform init -reconfigure |
| New team member clones the repo | terraform init |
After git pull that adds modules | terraform init |
.terraform/ Directory Structure
.terraform/├── providers/│ └── registry.terraform.io/│ └── hashicorp/│ └── aws/│ └── 5.54.1/│ └── darwin_arm64/ # Platform-specific binary│ └── terraform-provider-aws_v5.54.1_x5├── modules/│ └── modules.json # Module source cache└── terraform.tfstate # Backend state (if local)Add .terraform/ to .gitignore — it contains binaries and should not be committed. The .terraform.lock.hcl file at the project root should always be committed.