You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
As Terraform projects grow, adopting best practices for code organisation, collaboration, security, and CI/CD becomes essential. This lesson consolidates recommendations for running Terraform in production teams.
| File | Purpose |
|---|---|
main.tf | Primary resource definitions |
variables.tf | Input variable declarations |
outputs.tf | Output value declarations |
providers.tf | Provider configuration and requirements |
backend.tf | Backend configuration |
locals.tf | Local value definitions |
data.tf | Data source definitions |
versions.tf | Version constraints (sometimes combined with providers.tf) |
infrastructure/
├── modules/ # Reusable modules
│ ├── network/
│ ├── compute/
│ ├── database/
│ └── monitoring/
├── environments/ # Environment configurations
│ ├── development/
│ ├── staging/
│ └── production/
├── .gitignore # Ignore state files, .terraform/
├── .terraform.lock.hcl # Committed — pins provider versions
└── README.md
# Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfvars # May contain secrets
crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json
Always pin provider versions to avoid unexpected changes:
terraform {
required_version = ">= 1.5, < 2.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
| Constraint | Meaning |
|---|---|
= 5.0.0 | Exact version |
>= 5.0 | 5.0 or newer |
~> 5.0 | >= 5.0 and < 6.0 (pessimistic) |
>= 5.0, < 5.5 | Range |
name: Terraform
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Format Check
run: terraform fmt -check
- name: Terraform Validate
run: terraform validate
- name: Terraform Plan
run: terraform plan -no-color
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
apply:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: plan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Apply
run: terraform apply -auto-approve
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
| Practice | Reason |
|---|---|
Run terraform fmt -check | Enforce consistent formatting |
Run terraform validate | Catch syntax errors early |
| Post plan output to PR comments | Enable code review of infrastructure changes |
Only apply on merge to main | Prevent accidental deployments from branches |
| Use OIDC authentication | Avoid storing long-lived credentials in CI |
| Store plan as artifact | Ensure apply uses the exact reviewed plan |
HashiCorp's managed platform for Terraform collaboration:
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.