Skip to main content

Command Palette

Search for a command to run...

Managing Multiple Environments in Terraform with a Single Repository

Updated
2 min read

Terraform is a powerful tool for defining infrastructure as code (IaC). When managing multiple environments like dev, staging, and prod, organizing your Terraform code effectively is key.

In this article, I’ll share how I manage multiple environments using a single Git repository with environment-specific folders. This approach is simple, scalable, and keeps everything in one place.

Why a Single Repository?

Using one repository for all environments simplifies maintenance and ensures consistency. It allows you to:

  • Reuse shared modules across environments.

  • Centralize version control and code reviews.

  • Streamline CI/CD pipelines.

Each environment has its own configuration and state file, ensuring isolation while keeping the codebase unified.

NOTE: This is just one method. Of course, many organizations may have different ways of managing different environments such as this or having separate repos for the environments altogether for better isolation.

Folder Structure

terraform/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   └── prod/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf
│       ├── terraform.tfvars
│       └── backend.tf
├── modules/
│   ├── ec2/
│   ├── sqs/
│   └── s3/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
├── .gitignore
└── README.md

How It Works

  1. Environment-Specific Configurations: Each environment folder contains:

    • main.tf: Defines resources, referencing modules.

    • variables.tf: Defines input variables.

    • outputs.tf: Specifies output values.

    • terraform.tfvars: Sets environment-specific variable values (e.g., region, instance size).

    • backend.tf: Configures the state file storage.

  2. State File Management: Terraform stores the state of each environment in a separate state file. I use an AWS S3 bucket to store state files remotely, with different keys for each environment (e.g., dev/terraform.tfstate, prod/terraform.tfstate). S3 now supports native state locking, thus dynamodb will not be used.

  3. Modules for Reusability: Shared infrastructure (e.g., VPCs) is defined in the modules/ folder. Each environment’s main.tf references these modules with environment-specific inputs:

Best Practices

  • Version Control: Store the repository in Git (e.g., GitHub). Use pull requests for code reviews.

  • State Security: Enable S3 bucket versioning and encryption and restrict access with bucket policies.

  • CI/CD Integration: Use a pipeline (e.g., GitHub Actions) to run terraform plan and apply for each environment. Require manual approval for prod.

  • Consistency: Use terraform fmt for formatting and terraform validate for syntax checks.

  • Documentation: Add a README.md in each module and environment folder.

Concepts and Fundamentals

Part 1 of 1

Deep dives into fundamental topics like TCB HTTPS networking, cloud computing, DevOps principles, etc.