Skip to content

Instantly share code, notes, and snippets.

@thimslugga
Created December 5, 2025 02:42
Show Gist options
  • Select an option

  • Save thimslugga/2c23965af311ddbbc69cbb4503440fa7 to your computer and use it in GitHub Desktop.

Select an option

Save thimslugga/2c23965af311ddbbc69cbb4503440fa7 to your computer and use it in GitHub Desktop.
Terraform

πŸ“˜ Terraform - Infrastructure as Code (IaC)


🧩 What is Terraform?

Terraform is an open-source Infrastructure as Code (IaC) tool developed by HashiCorp that allows you to define, provision, and manage cloud infrastructure using a declarative configuration language known as HCL (HashiCorp Configuration Language).

Instead of manually creating AWS resources (like EC2 instances, S3 buckets, Lambda functions, etc.) through the AWS console, Terraform allows you to write .tf files and version control your infrastructure just like application code.

βœ… Key Features:

  • Cloud-Agnostic: Supports AWS, Azure, GCP, Oracle, and more.
  • Declarative Language: Define desired state; Terraform figures out how to achieve it.
  • Dependency Management: Handles dependencies between resources automatically.
  • Modular: Promote reuse with modules.
  • State Management: Keeps track of infrastructure in a terraform.tfstate file.

πŸ” Terraform vs. AWS SAM vs. Serverless Framework

Feature / Tool Terraform AWS SAM Serverless Framework
Type Infrastructure as Code (IaC) Serverless-specific IaC Serverless Framework (multi-cloud, plugin-rich)
Language HCL (Hashicorp Configuration Language) YAML YAML + JavaScript plugins
Scope Broad: EC2, S3, RDS, Lambda, VPC, etc. Narrow: AWS Lambda & related services Serverless focus (multi-cloud)
State Management Yes (remote or local state) No built-in; relies on CloudFormation No state file (uses CloudFormation for AWS)
Multi-cloud Support Yes No Yes (AWS, Azure, GCP)
CLI Experience terraform apply, plan, etc. sam build, sam deploy sls deploy, sls invoke
Extensibility Modules & providers Limited Plugin system

πŸ”§ Terraform Example: Creating an AWS S3 Bucket and Lambda

provider "aws" {
  region = "us-east-1"
}

resource "random_id" "bucket_suffix" {
  byte_length = 4
}

resource "aws_s3_bucket" "upload_bucket" {
  bucket = "example-app-bucket-${random_id.bucket_suffix.hex}"
  force_destroy = true
}

resource "aws_iam_role" "lambda_execution" {
  name = "lambda-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [{
      Action = "sts:AssumeRole",
      Effect = "Allow",
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

resource "aws_lambda_function" "my_lambda" {
  filename         = "${path.module}/function.zip"
  function_name    = "myLambdaFunction"
  role             = aws_iam_role.lambda_execution.arn
  handler          = "index.handler"
  runtime          = "nodejs20.x"
  source_code_hash = filebase64sha256("${path.module}/function.zip")
}

resource "aws_lambda_permission" "apigw" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.my_lambda.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_apigatewayv2_api.http_api.execution_arn}/*/*"
}

πŸ§ͺ Equivalent in AWS SAM

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda with S3 and API Gateway

Globals:
  Function:
    Timeout: 10
    Runtime: nodejs20.x
    Handler: index.handler

Resources:
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: myLambdaFunction
      CodeUri: function/
      Role: !GetAtt LambdaExecutionRole.Arn
      Events:
        HttpApiEvent:
          Type: HttpApi
          Properties:
            Path: /{proxy+}
            Method: ANY

  UploadBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub example-app-bucket-${AWS::StackName}
      # Note: Random suffix is not natively supported like in Terraform

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: lambda-execution-role
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

πŸ§ͺ Equivalent in Serverless Framework

service: lambda-s3-api-demo
frameworkVersion: '3'

provider:
  name: aws
  region: ap-south-1
  runtime: nodejs20.x
  iam:
    role:
      name: lambda-execution-role
      statements:
        - Effect: Allow
          Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
          Resource: arn:aws:logs:*:*:*

functions:
  myLambdaFunction:
    handler: handler.handler
    name: myLambdaFunction
    events:
      - httpApi:
          path: /{proxy+}
          method: ANY

resources:
  Resources:
    UploadBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: !Sub example-app-bucket-${AWS::StackName}

πŸ” Notes for above 3 IaC tools

Feature Terraform AWS SAM Serverless Framework
Lambda code zip function.zip manually built CodeUri with auto packaging Auto-packaged via handler.js
Bucket suffix (random) random_id Not directly supported Can be scripted in custom vars
Permissions Explicit IAM Role + Permission Automatic unless overridden Auto-generated or custom IAM
API Gateway integration Manual with permissions Auto-created via Events Auto-created via httpApi

βœ… When to Use Which?

Scenario Best Tool
Full cloud infrastructure (VPC, EC2, RDS, etc) Terraform
Pure AWS Lambda apps (simpler projects) AWS SAM
Multi-cloud or plugin-rich serverless app Serverless Framework
CI/CD ready IaC with state tracking Terraform

πŸ“Œ Things to Consider When Working with Terraform

πŸ”’ State Management

  • Use remote state (e.g., S3 + DynamoDB) for team collaboration.
  • Protect terraform.tfstate from version control.

πŸ” Resource Naming Conventions

  • Use environment prefixes (dev, prod, etc.)
  • Use terraform.workspace for environment isolation.

πŸ“¦ Module Usage

  • Break your infrastructure into reusable modules.
  • Example: ec2_instance, vpc, lambda_function modules.

πŸ” Security Best Practices

  • Use IAM roles over access keys.
  • Encrypt S3 state files with SSE.
  • Use kms_key_id for sensitive resources.

⚠️ Planning Before Applying

  • Always run terraform plan to see proposed changes.
  • Use -target flag only in emergencies (can lead to drift).

βœ… Version Locking

terraform {
  required_version = ">= 1.5.0"

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

πŸ”„ Lifecycle Customization

resource "aws_lambda_function" "example" {
  lifecycle {
    create_before_destroy = true
    ignore_changes        = [last_modified]
  }
}

πŸ› οΈ Useful Terraform Commands

terraform init       # Initialize the project
terraform plan       # Preview changes
terraform apply      # Apply changes
terraform destroy    # Destroy infrastructure
terraform fmt        # Format code
terraform validate   # Validate syntax
terraform state list # See all managed resources

🌐 Real-World Terraform Structure

infra/
β”œβ”€β”€ main.tf
β”œβ”€β”€ variables.tf
β”œβ”€β”€ outputs.tf
β”œβ”€β”€ terraform.tfvars
β”œβ”€β”€ modules/
β”‚   β”œβ”€β”€ ec2-instance/
β”‚   └── s3-bucket/
└── environments/
    β”œβ”€β”€ dev/
    └── prod/

🧠 Pro Tips

  • Use Terragrunt for DRY, hierarchical config and environment management.
  • Use pre-commit hooks to run terraform fmt and validate.
  • Document resource links and purpose in comments.
  • Use data sources to fetch existing resources safely.
  • Use local-exec/null_resource with care – avoid if possible.
  • Tag all resources for cost tracking & auditing.

🧾 References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment