How to Run Terraform Init From a Different Directory
By default, Terraform operates on the configuration in your current directory. But sometimes you need to run Terraform commands against configurations in other directories - like managing multiple environments from a central location, running Terraform in CI/CD pipelines, or automating multi-project deployments.
Terraform provides the -chdir flag specifically for this purpose, though there are other approaches depending on your use case.
TLDR: Use terraform -chdir=/path/to/config init to run Terraform against a configuration in a different directory. The -chdir flag must come before the subcommand (init, plan, apply). Alternatively, use shell commands like cd /path && terraform init for simple cases, or terraform -chdir=path plan -out=path/tfplan to save output files in the target directory. The -chdir flag is the recommended modern approach over older methods.
Using the -chdir Flag
The -chdir flag changes Terraform's working directory before executing the command:
# Initialize Terraform in another directory
terraform -chdir=./environments/production init
This is equivalent to:
cd ./environments/production
terraform init
But with -chdir, your shell's working directory doesn't change, which can be useful in scripts.
The flag must come before the subcommand:
# Correct
terraform -chdir=./prod init
terraform -chdir=./prod plan
terraform -chdir=./prod apply
# Incorrect - won't work
terraform init -chdir=./prod
Running Multiple Commands
When running multiple Terraform commands, specify -chdir for each one:
# Initialize, plan, and apply
terraform -chdir=./environments/staging init
terraform -chdir=./environments/staging plan -out=tfplan
terraform -chdir=./environments/staging apply tfplan
Or create a shell function to reduce repetition:
# Add to your shell profile
tf() {
local dir=$1
shift
terraform -chdir="$dir" "$@"
}
# Use it
tf ./environments/staging init
tf ./environments/staging plan
tf ./environments/staging apply
Absolute vs Relative Paths
You can use both absolute and relative paths:
# Relative path (from current directory)
terraform -chdir=./terraform/prod init
# Absolute path
terraform -chdir=/home/user/infrastructure/terraform/prod init
# Using environment variable
export TF_DIR="/home/user/infrastructure/terraform/prod"
terraform -chdir="${TF_DIR}" init
Relative paths are resolved from your current working directory, not from where the terraform binary is located.
Managing Multiple Environments
For projects with multiple environments, use -chdir to operate on each:
infrastructure/
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ └── terraform.tfvars
│ └── prod/
│ ├── main.tf
│ └── terraform.tfvars
└── modules/
└── vpc/
└── main.tf
Initialize all environments from the root:
#!/bin/bash
# init-all-envs.sh
for env in dev staging prod; do
echo "Initializing $env environment..."
terraform -chdir="environments/$env" init
done
Plan all environments:
#!/bin/bash
# plan-all-envs.sh
for env in dev staging prod; do
echo "Planning $env environment..."
terraform -chdir="environments/$env" plan -out="tfplan-$env"
done
File Paths and -chdir
When using -chdir, file paths in the output are relative to the target directory:
terraform -chdir=./environments/prod plan -out=tfplan
The tfplan file is created in ./environments/prod/tfplan, not in your current directory.
To save files in your current directory, use absolute paths or path references:
# Save plan in current directory
terraform -chdir=./environments/prod plan -out="$(pwd)/prod-tfplan"
Or use relative paths from the target directory:
# Save plan one level up
terraform -chdir=./environments/prod plan -out=../prod-tfplan
Using cd vs -chdir in Scripts
Both approaches work, but have different characteristics:
Using cd:
#!/bin/bash
# Approach 1: Using cd
cd /path/to/terraform/config || exit 1
terraform init
terraform plan
terraform apply
Pros:
- Simple and familiar
- All subsequent commands operate in the target directory
- Easier to read for simple scripts
Cons:
- Changes your script's working directory
- Need error handling (
|| exit) if directory doesn't exist - Can cause issues if script continues after Terraform commands
Using -chdir:
#!/bin/bash
# Approach 2: Using -chdir
terraform -chdir=/path/to/terraform/config init
terraform -chdir=/path/to/terraform/config plan
terraform -chdir=/path/to/terraform/config apply
Pros:
- Doesn't change the script's working directory
- More explicit about which directory is targeted
- Safer in complex scripts
Cons:
- More verbose
- Need to repeat the flag for each command
Best of both worlds:
#!/bin/bash
# Approach 3: Subshell with cd
(
cd /path/to/terraform/config || exit 1
terraform init
terraform plan
terraform apply
)
# Script continues here in the original directory
echo "Deployment complete"
The subshell () isolates the cd command, so when it exits, you're back in your original directory.
CI/CD Pipeline Patterns
In CI/CD, you often need to run Terraform from different directories:
# GitHub Actions
name: Terraform
on:
push:
branches: [main]
jobs:
terraform-prod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Init
run: terraform -chdir=environments/prod init
- name: Terraform Plan
run: terraform -chdir=environments/prod plan
- name: Terraform Apply
run: terraform -chdir=environments/prod apply -auto-approve
For multiple environments:
jobs:
terraform:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
- name: Terraform Init
run: terraform -chdir=environments/${{ matrix.environment }} init
- name: Terraform Plan
run: terraform -chdir=environments/${{ matrix.environment }} plan
Working With Modules
When your configuration uses local modules, -chdir affects how module paths are resolved:
# environments/prod/main.tf
module "vpc" {
source = "../../modules/vpc" # Relative to this file's location
cidr_block = "10.0.0.0/16"
}
Running from the root directory:
terraform -chdir=environments/prod init
Terraform resolves the module path ../../modules/vpc relative to environments/prod, which correctly points to modules/vpc.
Handling Backend Configuration
Backend configuration files are also resolved relative to the target directory:
# Backend config in the target directory
terraform -chdir=./environments/prod init -backend-config=backend.hcl
This looks for ./environments/prod/backend.hcl.
To use a backend config from your current directory:
# Backend config in current directory
terraform -chdir=./environments/prod init -backend-config="$(pwd)/backend.hcl"
Or with a relative path from the target:
# Backend config one level up
terraform -chdir=./environments/prod init -backend-config=../backend.hcl
Automating Multi-Directory Operations
Here's a script that initializes and plans multiple Terraform directories:
#!/bin/bash
# terraform-multi-init.sh
set -e
TERRAFORM_DIRS=(
"infrastructure/networking"
"infrastructure/compute"
"infrastructure/database"
"infrastructure/monitoring"
)
for dir in "${TERRAFORM_DIRS[@]}"; do
echo "========================================="
echo "Processing: $dir"
echo "========================================="
if [ ! -d "$dir" ]; then
echo "Warning: Directory $dir does not exist, skipping..."
continue
fi
echo "Running terraform init..."
terraform -chdir="$dir" init
echo "Running terraform validate..."
terraform -chdir="$dir" validate
echo "Running terraform plan..."
terraform -chdir="$dir" plan -out="tfplan"
echo ""
done
echo "All directories processed successfully!"
Make it executable and run:
chmod +x terraform-multi-init.sh
./terraform-multi-init.sh
Using -chdir With Terraform Workspaces
When working with Terraform workspaces:
# Initialize in a specific directory
terraform -chdir=./infrastructure init
# List workspaces in that directory
terraform -chdir=./infrastructure workspace list
# Select a workspace
terraform -chdir=./infrastructure workspace select production
# Run plan for that workspace
terraform -chdir=./infrastructure plan
The workspace is scoped to the configuration directory, so -chdir must be consistent across commands.
Debugging Path Issues
If you encounter path-related errors, verify what Terraform sees:
# Show the current working directory from Terraform's perspective
terraform -chdir=./environments/prod version
# Show detailed output including paths
terraform -chdir=./environments/prod init -upgrade
Add debugging to your scripts:
#!/bin/bash
TARGET_DIR="./environments/prod"
echo "Current directory: $(pwd)"
echo "Target directory: $TARGET_DIR"
echo "Resolved path: $(cd "$TARGET_DIR" && pwd)"
terraform -chdir="$TARGET_DIR" init
Alternative: Using -c Flag (Older Versions)
In very old Terraform versions (pre-0.14), there was no -chdir flag. The workaround was always using cd:
# Old approach (before Terraform 0.14)
(cd /path/to/config && terraform init)
If you're on Terraform 0.14 or later (you should be), always use -chdir instead.
Environment Variables and -chdir
Environment variables like TF_DATA_DIR are still relative to the target directory:
# .terraform directory will be created inside target dir
terraform -chdir=./environments/prod init
# Override the data directory location
TF_DATA_DIR="$(pwd)/.terraform-prod" \
terraform -chdir=./environments/prod init
This creates the .terraform directory in your current directory rather than the target.
Using Make for Multi-Directory Management
For complex setups, use Make to manage Terraform commands:
# Makefile
.PHONY: init-all plan-all apply-all
ENVS := dev staging prod
init-all:
@for env in $(ENVS); do \
echo "Initializing $$env..."; \
terraform -chdir=environments/$$env init; \
done
plan-all:
@for env in $(ENVS); do \
echo "Planning $$env..."; \
terraform -chdir=environments/$$env plan -out=tfplan; \
done
apply-all:
@for env in $(ENVS); do \
echo "Applying $$env..."; \
terraform -chdir=environments/$$env apply tfplan; \
done
# Target specific environment
init-%:
terraform -chdir=environments/$* init
plan-%:
terraform -chdir=environments/$* plan
apply-%:
terraform -chdir=environments/$* apply
Use it:
# Initialize all environments
make init-all
# Plan specific environment
make plan-prod
# Apply specific environment
make apply-staging
The -chdir flag is the cleanest way to run Terraform commands against configurations in other directories. It keeps your scripts simple and explicit about which configuration is being operated on, without changing your shell's working directory or creating complex path resolution logic.
Found an issue?