| description | Comprehensive guidelines for writing, organizing, and maintaining Terraform code in this repository. |
|---|---|
| applyTo | terraform/**/*.tf |
This file is mastered in https://github.com/NHSDigital/eps-copilot-instructions and is automatically synced to all EPS repositories. To suggest changes, please open an issue or pull request in the eps-copilot-instructions repository.
This document provides best practices and conventions for writing, organizing, and maintaining Terraform code. It is intended for use by developers and GitHub Copilot to ensure consistency, reliability, and maintainability across all Terraform files in the project.
- Use Terraform modules to promote code reuse and separation of concerns.
- Keep resource definitions declarative and avoid imperative logic.
- Store environment-specific configuration in separate files (e.g.,
env/folders). - Use variables and outputs to parameterize and expose configuration.
- Document resources, modules, and variables with comments.
- Prefer explicit resource dependencies using
depends_onwhen needed. - Use remote state for shared resources and outputs.
- Group related resources in logical subfolders (e.g.,
archive/,backup-source/). - Use
localsfor computed values and to reduce repetition. - Use data sources to reference existing infrastructure.
- Avoid hardcoding values; use variables and environment files.
- Use
terraform fmtto enforce consistent formatting. - Use
terraform validateandterraform planbefore applying changes. - Use
Makefiletargets for common operations (init, plan, apply, destroy). - Store secrets and sensitive values in secure locations (e.g., AWS SSM, environment variables), not in code.
- Use resource tags for traceability and cost management.
- Prefer resource names that include environment and purpose (e.g.,
archive_prod_bucket).
- Use snake_case for resource, variable, and output names.
- Prefix resource names with their type and purpose (e.g.,
s3_archive_bucket). - Use clear, descriptive names for modules and files.
- Use consistent naming for environments (e.g.,
dev,prod,test).
- Place each environment's configuration in its own file under
env/. - Use a
variables.tffile for input variables. - Use an
outputs.tffile for outputs. - Use a
locals.tffile for local values. - Use a
provider.tffile for provider configuration. - Use a
Makefilefor automation and common tasks. - Organize resources by domain (e.g.,
archive/,infra/,storage/).
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}
resource "aws_s3_bucket" "archive" {
bucket = var.bucket_name
...
}locals {
tags = {
Environment = var.environment
Project = "eps-storage"
}
}
resource "aws_s3_bucket" "archive" {
tags = local.tags
...
}module "archive" {
source = "../modules/aws-archive"
environment = var.environment
...
}resource "aws_s3_bucket" "archive" {
bucket = "my-hardcoded-bucket-name"
...
}- Never commit secrets or credentials to version control.
- Use IAM roles and policies with least privilege.
- Enable encryption for all supported resources (e.g., S3, KMS, DynamoDB).
- Use secure remote state backends (e.g., S3 with encryption and locking).
- Validate input variables for expected values and types.
- Use resource lifecycle rules to manage retention and cleanup.
- Use data sources to avoid duplicating resources.
- Minimize resource drift by keeping code and infrastructure in sync.
- Use
terraform planto preview changes and avoid unnecessary updates.
- Use
terraform validateto check syntax and configuration. - Use
terraform planto preview changes before applying. - Use
tfsecfor static security analysis (tfsec.ymlconfig). - Use automated CI/CD pipelines for deployment and testing.
- Format code:
terraform fmt(run in each Terraform folder) - Validate code:
terraform validate - Security scan:
tfsec . - Plan changes:
terraform plan -var-file=env/dev.tfvars.json - Apply changes:
terraform apply -var-file=env/dev.tfvars.json
- Review and update modules and dependencies regularly.
- Remove unused resources and variables.
- Update environment files as infrastructure evolves.
- Keep documentation up to date.
- Refactor code to improve readability and maintainability.