Describe best Terraform pratices
# Terraform Coding Best Practices
## 1. General Principles
- **Idempotency**: Write code that produces the same result every time it is applied.
- **Declarative, not imperative**: Let Terraform handle the "how." Describe the desired state.
- **Environment agnostic**: Make code reusable across environments via variables and workspaces.
---
## 2. File and Project Structure
```
/terraform
/modules
/<module_name>
- main.tf
- variables.tf
- outputs.tf
/envs
/dev
/prod
- main.tf
- backend.tf
- variables.tf
- terraform.tfvars
- versions.tf
- provider.tf
- README.md
```
- Use **logical separation** (e.g., environments vs modules).
- Use **backend.tf** for remote state configuration.
- Use **terraform.tfvars** files for environment-specific values.
---
## 3. Naming Conventions
- Use snake_case for resources and variables.
- Prefix resources with their context (e.g., `vpc_prod_main`).
- Name modules descriptively: `network`, `compute`, `iam`.
Example:
```hcl
resource "aws_instance" "web_prod_app1" {
...
}
```
---
## 4. Modules
- Write **small, focused modules** (single purpose).
- Always use **versioned modules** when using external sources.
- Include:
- `main.tf` (resources)
- `variables.tf` (inputs)
- `outputs.tf` (exposed values)
- Do not hardcode values; always use variables.
---
## 5. Variables and Outputs
### Variables
- Provide type, description, and defaults.
- Use validation blocks where applicable.
```hcl
variable "region" {
type = string
description = "AWS region"
default = "us-east-1"
}
```
### Outputs
- Only expose necessary values.
- Name outputs clearly.
```hcl
output "vpc_id" {
value = aws_vpc.main.id
description = "The ID of the main VPC"
}
```
---
## 6. Version Pinning
```hcl
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
```
- Pin Terraform and provider versions to avoid drift and breakage.
---
## 7. Security Best Practices
- Use **remote backends** with locking (e.g., S3 + DynamoDB for AWS).
- Use **data sources** to fetch existing values instead of hardcoding.
- Never commit secrets or state files to Git.
- Use environment variables or secret managers for sensitive data.
---
## 8. State Management
- Use **remote state** with proper locking and encryption.
- Use **state file separation** per environment.
- Use **`terraform state`** commands to move or inspect resources.
---
## 9. Linting, Validation, and Testing
- Use `terraform fmt` to standardize formatting.
- Use `terraform validate` before applying.
- Integrate `tflint`, `checkov`, and `terrascan` for static analysis.
- Use automated tests with tools like `terratest` or `kitchen-terraform`.
---
## 10. CI/CD Integration
- Use pipelines to:
- Lint and validate
- Plan with `-out` option
- Enforce manual approval before `apply`
- Store `terraform plan` output as artifacts.
---
## 11. Documentation
- Include README in each module with:
- Purpose
- Inputs/Outputs
- Usage examples
- Document resource changes and module versions.
---
## 12. Git Best Practices
- Use feature branches and pull requests.
- Include plan output in PR description.
- Tag releases for module versions.
- Use `.terraform.lock.hcl` to ensure deterministic builds.
---
## 13. Clean Code Tips for LLMs
- Use clear, consistent indentation and spacing.
- Comment **why**, not just what.
- Break large resource definitions into logical parts.
- Favor readability over cleverness.
---
## 14. Bonus: AI-Friendly Formatting
- Use consistent patterns that make code easily parseable.
- Avoid dynamic code generation unless well-justified.
- Use descriptive variable and output names.
---
## Example: Clean, Modular Terraform Usage
```hcl
module "vpc" {
source = "../modules/vpc"
name = "prod-vpc"
cidr = "10.0.0.0/16"
region = var.region
}
output "vpc_id" {
value = module.vpc.vpc_id
description = "The ID of the VPC"
}
```
---
## Summary
These best practices aim to ensure:
- Readable, maintainable code
- Safe and secure deployments
- AI-generatable, modular, and robust infrastructure
Always test your code. Always document your intent.