Skip to content
JBRichardson.comIT Cloud Solutions

Infrastructure as code with Terraform: a starter structure

Cloud & Edge 6 min readUpdated October 7, 2026

A folder layout, remote state setup and a few working rules that keep Terraform manageable as it grows.

All guides

Clicking through a console works for the first server and fails for the tenth. Infrastructure as code (IaC) turns your environment into reviewed, versioned files so you can rebuild it, compare changes and answer the question 'what changed?' with a pull request.

A layout that scales

infra/
  modules/
    network/      # VPC, subnets, routing
    app/          # compute, load balancer, IAM
  envs/
    staging/
      main.tf     # calls the modules with staging values
    production/
      main.tf     # same modules, production values

Modules hold the reusable pattern, and each environment is a thin file that passes in sizes, names and settings. Staging and production then differ only in values, not in structure.

Remote state with locking

Never keep state on a laptop. Store it in a private, versioned, encrypted bucket with locking so two people cannot apply at once. Recent Terraform versions can lock directly in S3; older ones use a DynamoDB table.

terraform {
  required_version = ">= 1.10"

  backend "s3" {
    bucket       = "example-tfstate"
    key          = "production/network.tfstate"
    region       = "us-east-1"
    encrypt      = true
    use_lockfile = true
  }
}

Working rules

  • Keep state files small: split by layer (network, data, apps) so a mistake has a small blast radius.
  • Pin Terraform and provider versions and commit the lock file.
  • Run plan on every pull request and apply only from the pipeline, never from a laptop.
  • Keep secrets out of variables and state where possible. Reference AWS Secrets Manager or SSM Parameter Store instead.
  • Tag every resource with owner, environment and cost centre.
  • Schedule a plan that reports drift, so manual console changes do not hide.