---
id: sm-terraform-style-guide
name: "terraform-style-guide"
url: https://skills.yangsir.net/skill/sm-terraform-style-guide
author: hashicorp
domain: cloud-infra
tags: ["terraform", "infrastructure-as-code-(iac)", "cloud-provisioning", "aws", "azure"]
install_count: 5000
rating: 4.40 (200 reviews)
github: https://github.com/hashicorp/agent-skills
---

# terraform-style-guide

> 遵循HashiCorp官方规范，生成并维护符合最佳实践的Terraform代码，确保风格一致性。

**Stats**: 5,000 installs · 4.4/5 (200 reviews)

## Before / After 对比

### 遵循Terraform规范，维护代码一致性

## Readme

# terraform-style-guide

# Terraform Style Guide

Generate and maintain Terraform code following HashiCorp's official style conventions and best practices.

**Reference:** [HashiCorp Terraform Style Guide](https://developer.hashicorp.com/terraform/language/style)

## Code Generation Strategy

When generating Terraform code:

- Start with provider configuration and version constraints

- Create data sources before dependent resources

- Build resources in dependency order

- Add outputs for key resource attributes

- Use variables for all configurable values

## File Organization

File
Purpose

`terraform.tf`
Terraform and provider version requirements

`providers.tf`
Provider configurations

`main.tf`
Primary resources and data sources

`variables.tf`
Input variable declarations (alphabetical)

`outputs.tf`
Output value declarations (alphabetical)

`locals.tf`
Local value declarations

### Example Structure

```
# terraform.tf
terraform {
  required_version = ">= 1.7"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# variables.tf
variable "environment" {
  description = "Target deployment environment"
  type        = string

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

# locals.tf
locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
  }
}

# main.tf
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true

  tags = merge(local.common_tags, {
    Name = "${var.project_name}-${var.environment}-vpc"
  })
}

# outputs.tf
output "vpc_id" {
  description = "ID of the created VPC"
  value       = aws_vpc.main.id
}

```

## Code Formatting

### Indentation and Alignment

- Use **two spaces** per nesting level (no tabs)

- Align equals signs for consecutive arguments

```
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = "subnet-12345678"

  tags = {
    Name        = "web-server"
    Environment = "production"
  }
}

```

### Block Organization

Arguments precede blocks, with meta-arguments first:

```
resource "aws_instance" "example" {
  # Meta-arguments
  count = 3

  # Arguments
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  # Blocks
  root_block_device {
    volume_size = 20
  }

  # Lifecycle last
  lifecycle {
    create_before_destroy = true
  }
}

```

## Naming Conventions

- Use **lowercase with underscores** for all names

- Use **descriptive nouns** excluding the resource type

- Be specific and meaningful

- Resource names must be singular, not plural

- Default to `main` for resources where a specific descriptive name is redundant or unavailable, provided only one instance exists

```
# Bad
resource "aws_instance" "webAPI-aws-instance" {}
resource "aws_instance" "web_apis" {}
variable "name" {}

# Good
resource "aws_instance" "web_api" {}
resource "aws_vpc" "main" {}
variable "application_name" {}

```

## Variables

Every variable must include `type` and `description`:

```
variable "instance_type" {
  description = "EC2 instance type for the web server"
  type        = string
  default     = "t2.micro"

  validation {
    condition     = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
    error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
  }
}

variable "database_password" {
  description = "Password for the database admin user"
  type        = string
  sensitive   = true
}

```

## Outputs

Every output must include `description`:

```
output "instance_id" {
  description = "ID of the EC2 instance"
  value       = aws_instance.web.id
}

output "database_password" {
  description = "Database administrator password"
  value       = aws_db_instance.main.password
  sensitive   = true
}

```

## Dynamic Resource Creation

### Prefer for_each over count

```
# Bad - count for multiple resources
resource "aws_instance" "web" {
  count = var.instance_count
  tags  = { Name = "web-${count.index}" }
}

# Good - for_each with named instances
variable "instance_names" {
  type    = set(string)
  default = ["web-1", "web-2", "web-3"]
}

resource "aws_instance" "web" {
  for_each = var.instance_names
  tags     = { Name = each.key }
}

```

### count for Conditional Creation

```
resource "aws_cloudwatch_metric_alarm" "cpu" {
  count = var.enable_monitoring ? 1 : 0

  alarm_name = "high-cpu-usage"
  threshold  = 80
}

```

## Security Best Practices

When generating code, apply security hardening:

- Enable encryption at rest by default

- Configure private networking where applicable

- Apply principle of least privilege for security groups

- Enable logging and monitoring

- Never hardcode credentials or secrets

- Mark sensitive outputs with `sensitive = true`

### Example: Secure S3 Bucket

```
resource "aws_s3_bucket" "data" {
  bucket = "${var.project}-${var.environment}-data"
  tags   = local.common_tags
}

resource "aws_s3_bucket_versioning" "data" {
  bucket = aws_s3_bucket.data.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
  bucket = aws_s3_bucket.data.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.s3.arn
    }
  }
}

resource "aws_s3_bucket_public_access_block" "data" {
  bucket = aws_s3_bucket.data.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

```

## Version Pinning

```
terraform {
  required_version = ">= 1.7"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"  # Allow minor updates
    }
  }
}

```

**Version constraint operators:**

- `= 1.0.0` - Exact version

- `>= 1.0.0` - Greater than or equal

- `~> 1.0` - Allow rightmost component to increment

- `>= 1.0, < 2.0` - Version range

## Provider Configuration

```
provider "aws" {
  region = "us-west-2"

  default_tags {
    tags = {
      ManagedBy = "Terraform"
      Project   = var.project_name
    }
  }
}

# Aliased provider for multi-region
provider "aws" {
  alias  = "east"
  region = "us-east-1"
}

```

## Version Control

**Never commit:**

- `terraform.tfstate`, `terraform.tfstate.backup`

- `.terraform/` directory

- `*.tfplan`

- `.tfvars` files with sensitive data

**Always commit:**

- All `.tf` configuration files

- `.terraform.lock.hcl` (dependency lock file)

## Validation Tools

Run before committing:

```
terraform fmt -recursive
terraform validate

```

Additional tools:

- `tflint` - Linting and best practices

- `checkov` / `tfsec` - Security scanning

## Code Review Checklist

-  Code formatted with `terraform fmt`

-  Configuration validated with `terraform validate`

-  Files organized according to standard structure

-  All variables have type and description

-  All outputs have descriptions

-  Resource names use descriptive nouns with underscores

-  Version constraints pinned explicitly

-  Sensitive values marked with `sensitive = true`

-  No hardcoded credentials or secrets

-  Security best practices applied

*Based on: [HashiCorp Terraform Style Guide](https://developer.hashicorp.com/terraform/language/style)*
Weekly Installs1.9KRepository[hashicorp/agent-skills](https://github.com/hashicorp/agent-skills)GitHub Stars470First SeenJan 26, 2026Security Audits[Gen Agent Trust HubPass](/hashicorp/agent-skills/terraform-style-guide/security/agent-trust-hub)[SocketPass](/hashicorp/agent-skills/terraform-style-guide/security/socket)[SnykPass](/hashicorp/agent-skills/terraform-style-guide/security/snyk)Installed onopencode1.5Kgithub-copilot1.5Kcodex1.5Kgemini-cli1.5Kamp1.3Kkimi-cli1.3K

---
*Source: https://skills.yangsir.net/skill/sm-terraform-style-guide*
*Markdown mirror: https://skills.yangsir.net/api/skill/sm-terraform-style-guide/markdown*