Overview
This series teaches infrastructure as code through heavily annotated, self-contained examples. Each example focuses on a single IaC concept and includes inline annotations explaining what each directive does, why it matters, and what infrastructure state results from it.
Series Structure
The examples are organized into three levels based on complexity:
- Beginner — Foundational IaC concepts, basic resource provisioning, and single-provider configurations
- Intermediate — Modules, state management, multi-environment patterns, and configuration management
- Advanced — Multi-cloud patterns, policy as code, drift detection, and enterprise-scale IaC architectures
Structure of Each Example
Every example follows a consistent five-part format:
- Brief Explanation — what the IaC pattern addresses and why it matters (2-3 sentences)
- Mermaid Diagram — visual representation of infrastructure topology, provisioning flow, or state transitions (when appropriate)
- Heavily Annotated Code — HCL, YAML, or other IaC configuration with
# =>comments documenting each directive and its effect - Key Takeaway — the core insight to retain from the example (1-2 sentences)
- Why It Matters — production relevance and real-world impact (50-100 words)
How to Use This Series
Each page presents annotated IaC configuration files. Read the annotations alongside the code to understand both the mechanics and the intent. The examples build on each other within each level, so reading sequentially gives the fullest understanding.
Examples by Level
Beginner (Examples 1–28)
- Example 1: HCL Block Syntax
- Example 2: Terraform Provider Block
- Example 3: String, Number, and Boolean Arguments
- Example 4: HCL Comments
- Example 5: Terraform Init and the Lock File
- Example 6: Declaring an AWS EC2 Resource
- Example 7: Resource References and Interpolation
- Example 8: Resource with Multiple Arguments
- Example 9: Input Variables with Type Constraints
- Example 10: Referencing Variables with
var. - Example 11: Variable Validation Rules
- Example 12: The
.tfvarsFile - Example 13: Output Values
- Example 14: Sensitive Outputs
- Example 15: Data Sources
- Example 16: Multiple Data Source Filters
- Example 17: Local Values
- Example 18: String Interpolation
- Example 19:
terraform plan— The Dry-Run - Example 20:
terraform apply— Applying Changes - Example 21:
terraform destroy— Tearing Down Resources - Example 22: Understanding Terraform State
- Example 23: Remote State Backend
- Example 24: Implicit vs Explicit Dependencies
- Example 25: Creating Multiple Resources with
count - Example 26:
for_eachwith a Map - Example 27: Ansible Playbook Structure
- Example 28: Ansible Inventory File
Intermediate (Examples 29–57)
- Example 29: Local Module with Input Variables
- Example 30: Module Output Values and Cross-Module Reference
- Example 31: Registry Module (Terraform Registry)
- Example 32: Remote Backend with S3 and DynamoDB State Locking
- Example 33: Terraform Workspaces for Environment Isolation
- Example 34:
terraform import— Adopting Existing Resources - Example 35: Data Sources for Cross-Stack References
- Example 36:
dynamicBlocks for Repeated Nested Structures - Example 37: Conditional Resources with
count - Example 38: Conditional Resources with
for_each - Example 39:
lifecycleRules —prevent_destroyandignore_changes - Example 40: Variable Validation Rules
- Example 41:
local-execProvisioner - Example 42:
remote-execProvisioner - Example 43:
null_resourcewith Triggers - Example 44:
terraform_remote_stateData Source - Example 45: Role Structure and
ansible-galaxy init - Example 46: Handlers and Notifications
- Example 47: Jinja2 Templates with
ansible.builtin.template - Example 48: Ansible Vault for Secrets Management
- Example 49: Conditionals with
when - Example 50: Loops with
loopandwith_items - Example 51: Directory Layout for Multi-Environment Terraform
- Example 52: Ansible Inventory for Multi-Environment Targets
- Example 53: Ansible Conditionals with Registered Variables
- Example 54:
forExpressions and Collection Transformations - Example 55:
localsfor Expression Reuse and Complexity Management - Example 56:
depends_onfor Explicit Dependency Management - Example 57:
movedBlock for State Refactoring Without Destroy
Advanced (Examples 58–85)
- Example 58: Multi-Cloud Provider Configuration
- Example 59: Terraform Cloud Workspace Configuration
- Example 60: Terraform Cloud Variable Sets
- Example 61: Sentinel Policy Enforcement
- Example 62: OPA (Open Policy Agent) for Terraform
- Example 63: Terraform Drift Detection
- Example 64: Terraform Import for Existing Resources
- Example 65: Blue-Green Infrastructure Deployment
- Example 66: Immutable Infrastructure with AMI Baking
- Example 67: GitOps Workflow with Atlantis
- Example 68: Infrastructure Pipeline with GitHub Actions
- Example 69: Terratest for Infrastructure Testing
- Example 70: Module Contract Testing with Terraform Unit Tests
- Example 71: HashiCorp Vault Integration
- Example 72: Ansible Vault for Ansible Secrets
- Example 73: Pulumi TypeScript Comparison
- Example 74: Terraform CDK (CDKTF) Concept
- Example 75: Infrastructure Cost Estimation with Infracost
- Example 76: Compliance as Code with SOPS
- Example 77: Disaster Recovery Automation
- Example 78: Auto-Scaling Infrastructure Patterns
- Example 79: Infrastructure Dependency Graphs
- Example 80: State Migration Strategies
- Example 81: Large-Scale Module Composition
- Example 82: Terraform Registry Module Versioning
- Example 83: Ansible Dynamic Inventory
- Example 84: Ansible Roles for Configuration Management
- Example 85: IaC Architecture Decision Framework
Last updated March 19, 2026