Skip to main content
RunBook Academy

← All runbooks in Terraform

low riskinformational~20 min

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.

  1. 1Create the working directory.
  2. 2Write the terraform block with required_version and required_providers.
  3. 3Write the backend block in the terraform block.
  4. 4Write the first resource block.
  5. 5Run terraform init.
  6. 6Verify the .terraform.lock.hcl file is created.
  7. 7Run terraform validate.
  8. 8Run terraform plan and verify the plan matches the expectation.
  9. 9Commit the configuration to Git (do NOT commit state, plan, or .terraform/).
  10. 10Set up CI: fmt -check, validate, tflint, tfsec, plan.

4 · Verification

Confirm the procedure actually fixed the problem.

  • terraform init succeeds.
  • terraform validate succeeds.
  • terraform plan produces the expected plan.
  • .terraform.lock.hcl is 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.hcl and retry.
  • If the backend is misconfigured, fix the backend block and re-init with terraform 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/aws provider.
  • Negotiates with the remote backend.
  • Creates the .terraform/ directory.
  • Creates the .terraform.lock.hcl file.

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.tfstate
  • terraform.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-run terraform init.
  • Backend is misconfigured. Fix the backend block. Re-run terraform 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.

References

  1. Terraform init
  2. Backend configuration