opentofu-coder

⚠️ SIMPLICITY FIRST - Default to Flat Files

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "opentofu-coder" with this command: npx skills add majesticlabs-dev/majestic-marketplace/majesticlabs-dev-majestic-marketplace-opentofu-coder

OpenTofu Coder

⚠️ SIMPLICITY FIRST - Default to Flat Files

ALWAYS start with the simplest approach. Only add complexity when explicitly requested.

Simple (DEFAULT) vs Overengineered

Aspect ✅ Simple (Default) ❌ Overengineered

Structure Flat .tf files in one directory Nested modules/ + environments/ directories

Modules None or only remote registry modules Custom local modules for simple resources

Environments Workspaces OR single tfvars Duplicate directory per environment

Variables Inline defaults, minimal tfvars Complex variable hierarchies

File count 3-5 .tf files total 15+ files across nested directories

When to Use Simple Approach (90% of cases)

  • Managing 1-5 resources of each type

  • Single provider, single region

  • Small team or solo developer

  • Standard infrastructure patterns

When Complexity is Justified (10% of cases)

  • Enterprise multi-region, multi-account

  • Reusable modules shared across teams

  • Complex dependency chains

  • User explicitly requests modular structure

Rule: If you can define everything in 5 flat .tf files, DO IT.

Simple Project Structure (DEFAULT)

infra/ ├── main.tf # All resources ├── variables.tf # Input variables ├── outputs.tf # Outputs ├── versions.tf # Provider versions └── terraform.tfvars # Variable values (gitignored)

Overview

OpenTofu is a community-driven, open-source fork of Terraform under MPL-2.0 license, maintained by the Linux Foundation. It uses HashiCorp Configuration Language (HCL) for declarative infrastructure management across cloud providers.

Core Philosophy

Prioritize:

  • Declarative over imperative: Describe desired state, not steps

  • Idempotency: Apply safely multiple times with same result

  • Modularity: Compose infrastructure from reusable modules

  • State as truth: State file is the source of truth for managed resources

  • Immutable infrastructure: Replace resources rather than mutate in place

HCL Syntax Essentials

Resource Blocks

resource "aws_instance" "web" { ami = var.ami_id instance_type = var.instance_type

tags = { Name = "${var.project}-web" Environment = var.environment } }

Data Sources

data "aws_ami" "ubuntu" { most_recent = true

filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] }

owners = ["099720109477"] # Canonical }

Variables

variable "environment" { description = "Deployment environment (dev, staging, prod)" type = string default = "dev"

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

variable "instance_types" { description = "Map of environment to instance type" type = map(string) default = { dev = "t3.micro" staging = "t3.small" prod = "t3.medium" } }

Outputs

output "instance_ip" { description = "Public IP of the web instance" value = aws_instance.web.public_ip sensitive = false }

output "database_password" { description = "Generated database password" value = random_password.db.result sensitive = true }

Locals

locals { common_tags = { Project = var.project Environment = var.environment ManagedBy = "OpenTofu" }

name_prefix = "${var.project}-${var.environment}" }

Meta-Arguments

count - Create Multiple Instances

resource "aws_instance" "server" { count = var.server_count

ami = var.ami_id instance_type = var.instance_type

tags = { Name = "${local.name_prefix}-server-${count.index}" } }

for_each - Create from Map/Set

resource "aws_iam_user" "users" { for_each = toset(var.user_names)

name = each.value path = "/users/" }

resource "aws_security_group_rule" "ingress" { for_each = var.ingress_rules

type = "ingress" from_port = each.value.port to_port = each.value.port protocol = each.value.protocol cidr_blocks = each.value.cidr_blocks security_group_id = aws_security_group.main.id }

depends_on - Explicit Dependencies

resource "aws_instance" "app" { ami = var.ami_id instance_type = var.instance_type

depends_on = [ aws_db_instance.database, aws_elasticache_cluster.cache ] }

lifecycle - Control Resource Behavior

resource "aws_instance" "critical" { ami = var.ami_id instance_type = var.instance_type

lifecycle { prevent_destroy = true create_before_destroy = true ignore_changes = [ tags["LastUpdated"], user_data ] } }

Replace when AMI changes

resource "aws_instance" "immutable" { ami = var.ami_id instance_type = var.instance_type

lifecycle { replace_triggered_by = [ null_resource.ami_trigger ] } }

Module Design

Module Structure

modules/ └── vpc/ ├── main.tf # Primary resources ├── variables.tf # Input variables ├── outputs.tf # Output values ├── versions.tf # Required providers └── README.md # Documentation

Calling Modules

module "vpc" { source = "./modules/vpc"

cidr_block = "10.0.0.0/16" environment = var.environment

azs = ["us-east-1a", "us-east-1b"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24"] public_subnets = ["10.0.101.0/24", "10.0.102.0/24"] }

Remote module with version

module "eks" { source = "terraform-aws-modules/eks/aws" version = "~> 20.0"

cluster_name = local.cluster_name cluster_version = "1.29"

vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnet_ids }

Module Best Practices

  • Expose minimal, clear interface of variables

  • Use sensible defaults where possible

  • Document all variables and outputs

  • Avoid over-generic "god" modules

  • Prefer composition over configuration flags

  • Version pin remote modules

State Management

Remote Backend (S3)

terraform { backend "s3" { bucket = "my-terraform-state" key = "prod/network/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" } }

OpenTofu State Encryption (Unique Feature)

terraform { encryption { key_provider "pbkdf2" "main" { passphrase = var.state_encryption_passphrase }

method "aes_gcm" "encrypt" {
  keys = key_provider.pbkdf2.main
}

state {
  method   = method.aes_gcm.encrypt
  enforced = true
}

plan {
  method   = method.aes_gcm.encrypt
  enforced = true
}

} }

State Commands

List resources in state

tofu state list

Show specific resource

tofu state show aws_instance.web

Move resource (refactoring)

tofu state mv aws_instance.old aws_instance.new

Remove from state (without destroying)

tofu state rm aws_instance.imported

Import existing resource

tofu import aws_instance.web i-1234567890abcdef0

See Provider Configuration for AWS provider setup, authentication methods, and multi-provider patterns.

See Environment Strategies for workspaces and directory-based environment management.

CLI Workflow

Initialize working directory

tofu init

Validate configuration

tofu validate

Format code

tofu fmt -recursive

Preview changes

tofu plan -out=plan.tfplan

Apply changes

tofu apply plan.tfplan

Destroy infrastructure

tofu destroy

Show current state

tofu show

Refresh state from actual infrastructure

tofu refresh

Best Practices Checklist

When writing OpenTofu/Terraform code:

  • Use remote backend with locking for team use

  • Enable state encryption (OpenTofu feature)

  • Never commit .tfstate or .tfvars with secrets to VCS

  • Pin provider and module versions

  • Use tofu plan before every apply

  • Use lifecycle.prevent_destroy for critical resources

  • Document all variables and outputs

  • Use locals for computed values and tags

  • Prefer for_each over count for named resources

  • Use validation blocks for variable constraints

  • Store secrets in secret managers, not in code

Common Patterns

Conditional Resources

resource "aws_eip" "static" { count = var.create_elastic_ip ? 1 : 0

instance = aws_instance.web.id }

Dynamic Blocks

resource "aws_security_group" "main" { name = "${local.name_prefix}-sg"

dynamic "ingress" { for_each = var.ingress_rules content { from_port = ingress.value.port to_port = ingress.value.port protocol = ingress.value.protocol cidr_blocks = ingress.value.cidr_blocks } } }

References

For detailed patterns and examples:

  • references/hcl-patterns.md - Advanced HCL patterns

  • references/project-scaffolding.md - Directory structure, .gitignore, next_steps output, security-first variables

  • references/post-provisioning.md - bin/setup-server scripts for post-infra, pre-deployment setup

  • references/state-management.md - State operations and encryption

  • references/provider-examples.md - Multi-cloud provider configs

  • references/makefile-automation.md - Makefile workflows for plan/apply/destroy

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

google-ads-strategy

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

viral-content

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

market-research

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

free-tool-arsenal

No summary provided by upstream source.

Repository SourceNeeds Review