# Terraform

> Use when writing Terraform.

- Skill: `tomevault-io/terraform-10` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/terraform-10`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/terraform-10/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/terraform-10

---


# Modern Terraform (v1.11+) best practices

- Use `try()` for fail-safe defaults; prefer over `element(concat())` for robust error handling.
- Set `nullable = false` in variables to prevent null assignments and reduce misconfiguration.
- Use `moved` blocks to refactor resources/modules efficiently, avoiding destroy/recreate cycles.
- Apply `optional()` with defaults for flexible object field handling.
- Use Terraform's native test framework to improve module reliability.
- Run unit tests with mock providers to avoid impacting real infrastructure.
- Apply provider-defined functions for resource configuration as needed.
- Validate relationships between variables for input correctness.
- Use write-only arguments for secrets, when supported, to avoid persisting them in state files.

# Naming conventions

## Resources

```hcl
# Use descriptive, contextual names:
resource "aws_instance" "web_server" {}
resource "aws_s3_bucket" "application_logs" {}

# Avoid generic names:
resource "aws_instance" "main" {}
resource "aws_s3_bucket" "bucket" {}

# Use "this" only for primary resources inside reusable modules (singletons):
resource "aws_vpc" "this" {}
resource "aws_security_group" "this" {}
```

## Variables

```hcl
# Prefer context-rich, specific names:
var.vpc_cidr_block
var.database_instance_class
```

## File structure

- `main.tf`: Core resources.
- `variables.tf`: Input variables.
- `outputs.tf`: Output values.
- `versions.tf`: Provider versions.
- `data.tf`: (Optional) Data sources.

# Directory structure

- Separate environment configs from modules.
- Use `examples/` for usage docs and test fixtures.

```
envs/            # Environment configs
├── prod/
├── staging/
└── dev/
modules/         # Reusable modules
├── networking/
├── compute/
└── data/
examples/        # Usage/test examples
├── complete/
└── minimal/
```

# Module hierarchy

**Resource → Resource Module → Infrastructure Module → Composition**

| Type                | Use Case                            | Scope                                |
| ------------------- | ----------------------------------- | ------------------------------------ |
| **Resource Module** | Group related resources             | VPC + subnets, SG + rules            |
| **Infra Module**    | Combine resource modules for a goal | Multiple modules, one region/account |
| **Composition**     | Full infrastructure deployment      | Across regions/accounts              |

# Patterns

Follow these for conditionals and stable resource addressing:

**Boolean condition:**

```hcl
# Boolean condition using for_each (stable addressing, no [0] index):
resource "aws_nat_gateway" "this" {
  for_each = var.create_nat_gateway ? { this = true } : {}

  # example fields:
  allocation_id = aws_eip.nat[each.key].id
  subnet_id     = aws_subnet.public[each.key].id
}
```

**Stable referencing with for_each:**

```hcl
# Safer when removing AZs:
resource "aws_subnet" "private" {
  for_each = toset(var.availability_zones)
  availability_zone = each.key
}

# count risks larger changes (don't do this):
resource "aws_subnet" "private" {
  count = length(var.availability_zones)
  availability_zone = var.availability_zones[count.index]
}
```

# Security guidelines

- Do not hardcode secrets in `.tf` or `.tfvars`; avoid committing secrets to version control.
- Mark secret variables as `sensitive = true` for UI redaction.
- Enable encryption for supported resources.
- Avoid wide-open rules in security groups (e.g., `0.0.0.0/0`).
- Enforce least privilege for security group rules.

## AWS-specific

- Store secrets in AWS Secrets Manager or Parameter Store.
- Avoid deploying resources in the default VPC; create dedicated VPCs.

## Azure-specific

- Use dedicated VNets and segmented subnets; control egress explicitly.
- Avoid public access on Storage Accounts, Key Vault, SQL, etc., unless required.
- Prefer Private Endpoints (Private Link) and service endpoints.
- Store secrets in Azure Key Vault.

---
> Source: [bkircher/skills](https://github.com/bkircher/skills) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-05-22 -->

