Runbook: Initialize a New Terraform Project
1 · Prerequisites
Confirm every item is in place before any state change.
- Terraform CLI 1.9.x installed
- A remote backend (e.g. S3 bucket + DynamoDB table)
- A Git repository
2 · Pre-checks
Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.
- · The remote backend exists and is reachable.
- · The state lock table exists.
- · The credentials for the backend are reachable.
- · The Terraform version is 1.9.x or later.
3 · Procedure
Execute each step in order. Verify the expected output of a step before moving to the next.
- 1Create the working directory.
- 2Write the
terraformblock withrequired_versionandrequired_providers. - 3Write the
backendblock in theterraformblock. - 4Write the first resource block.
- 5Run
terraform init. - 6Verify the
.terraform.lock.hclfile is created. - 7Run
terraform validate. - 8Run
terraform planand verify the plan matches the expectation. - 9Commit the configuration to Git (do NOT commit state, plan, or
.terraform/). - 10Set up CI:
fmt -check,validate,tflint,tfsec,plan.
4 · Verification
Confirm the procedure actually fixed the problem.
- ✓
terraform initsucceeds. - ✓
terraform validatesucceeds. - ✓
terraform planproduces the expected plan. - ✓
.terraform.lock.hclis in Git. - ✓CI gate is operational.
5 · Rollback
If verification fails, undo the procedure in reverse order.
- ↶If the init fails, delete
.terraform/and.terraform.lock.hcland retry. - ↶If the backend is misconfigured, fix the
backendblock and re-init withterraform init -migrate-state. - ↶If the state is corrupted, restore from the most recent backup.
6 · Escalation
When the runbook isn't enough, contact:
- · If the backend is unreachable, escalate to the platform team.
- · If the credentials are invalid, escalate to the security team.
Purpose
This runbook walks through the initialisation of a new Terraform project. The procedure is the same regardless of the cloud provider; the only project-specific elements are the backend configuration and the resource blocks.
When to use this runbook
Use this runbook when:
- A new Terraform project is being created.
- An existing project is being migrated from local state to a remote backend.
- The teams standard project layout is being applied to a new project.
Procedure
Step 1: Create the working directory
mkdir -p ~/projects/new-terraform-project
cd ~/projects/new-terraform-project
git init
The directory becomes the Git repository for the project.
Step 2: Write the terraform block
Create versions.tf:
terraform {
required_version = ">= 1.9.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "mycompany-terraform-state"
key = "new-project/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
The required_version is the floor for the Terraform version.
The required_providers pins the provider versions. The
backend block specifies the remote backend.
Step 3: Write the first resource
Create main.tf:
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "new-project"
Environment = "production"
ManagedBy = "terraform"
}
}
Step 4: Initialise
terraform init
The init:
- Downloads the
hashicorp/awsprovider. - Negotiates with the remote backend.
- Creates the
.terraform/directory. - Creates the
.terraform.lock.hclfile.
Step 5: Validate
terraform validate
Expected:
Success! The configuration is valid.
Step 6: Plan
terraform plan -out=initial.tfplan
The plan is saved to initial.tfplan. The plan proposes to
create one resource.
Step 7: Review the plan
terraform show initial.tfplan
Verify the plan matches the expectation.
Step 8: Apply
terraform apply initial.tfplan
The apply creates the VPC.
Step 9: Verify the state
terraform state list
terraform state show aws_vpc.main
Step 10: Commit to Git
git add .
git commit -m "Initial commit: new Terraform project"
git push
The .gitignore should exclude:
.terraform/.terraform.lock.hcl(for some teams; the recommendation is to commit it)terraform.tfstateterraform.tfstate.backup*.tfplan
The recommended .gitignore:
.terraform/
terraform.tfstate
terraform.tfstate.backup
*.tfplan
crash.log
crash.*.log
Step 11: Set up CI
Create a CI workflow that runs:
terraform fmt -check -recursive
terraform init -backend=false
terraform validate
tflint
tfsec .
terraform plan
The plan is uploaded as a build artefact. The PR is reviewed.
Verification
The runbook is successful if:
- The project is initialised with a remote backend.
- The state is in the remote backend, not the local disk.
- The configuration is in Git.
- The CI gate is operational.
- The plan output matches the expectation.
Rollback
If the procedure fails at any step:
- Init fails. Delete
.terraform/and.terraform.lock.hcl. Re-runterraform init. - Backend is misconfigured. Fix the
backendblock. Re-runterraform init -migrate-state. - State is corrupted. Restore from the most recent backup.
- Apply fails. Investigate the failure. The state records what succeeded. Re-apply to recover.
Escalation
Escalate to:
- Platform team if the backend is unreachable.
- Security team if the credentials are invalid.
- Engineering manager if the procedure fails repeatedly.