Skip to content

Terraform

Terraform should own all long-lived AWS resources: S3 buckets, CloudFront distributions, Lambda functions, IAM roles, Secrets Manager references, and optionally WAF associations. Keep modules small enough to review and environments isolated by workspace or directory—match whatever the Rendorix infra repository standardizes on.

A typical split (names vary by repo):

Module or layerOwns
Network / DNS (optional)Route 53 records, ACM certs in us-east-1 for CloudFront.
StorageS3 bucket for originals, encryption, lifecycle, bucket policies.
ComputeLambda for image transform, layers, env vars, concurrency settings.
EdgeCloudFront distribution, origins, behaviors, OAC, cache and query policies; CloudFront Function or Lambda@Edge attachments.
SecretsIAM for reading signing keys; sometimes the secret resource if created by Terraform (avoid storing raw HMAC in .tfvars in VCS).

Smaller teams sometimes use one root module first; split when plan output becomes hard to audit.

Define explicitly (examples only):

  • Environment name (dev, staging, prod).
  • AWS region for regional resources (S3/Lambda); CloudFront is global but ACM for CloudFront must be in us-east-1 in standard setups.
  • Domain / hosted zone id for DNS if Terraform manages records.
  • Reference to signing secret (e.g. Secrets Manager ARN), not the secret value in plain text.
  • Image Lambda zip or container uri if your pipeline builds artifacts outside Terraform.

Use validation blocks and descriptions on variables so misconfiguration fails early.

  1. Format and validate: terraform fmt, terraform validate.
  2. Plan in CI for every merge to main and for production applies: terraform plan -out=tfplan with read-only credentials where possible for PR plans.
  3. Apply with the saved plan: terraform apply tfplan so what runs matches what was reviewed.
  4. Review plans for destroy operations on stateful resources (buckets, distributions).

For drift: run terraform plan periodically; detect manual console changes and import or revert them.

  • Remote state in S3 with DynamoDB locking is a common default; encrypt the state bucket and restrict IAM to CI and break-glass roles.
  • Separate state per environment to limit blast radius of a bad apply.
  • Never commit terraform.tfstate to git for real environments.

Document who may run apply in prod and how break-glass unlocks work if lock sticks.

  • PR pipeline: fmt check, validate, plan (non-interactive), post plan as a comment or artifact.
  • Main / release pipeline: gated apply to staging first, then prod with manual approval if required.
  • OIDC from GitHub Actions (or similar) to AWS without long-lived static keys on runners when possible.

Pin Terraform and provider versions in required_version and required_providers for reproducible plans.