Skip to content

Instantly share code, notes, and snippets.

@jeffersfp
Created February 10, 2025 11:59
Show Gist options
  • Save jeffersfp/475fcb9dacce43606066f93eeff955dc to your computer and use it in GitHub Desktop.
Save jeffersfp/475fcb9dacce43606066f93eeff955dc to your computer and use it in GitHub Desktop.
Terraform 101

Terraform 101

main.tf

# Configure Terraform and required providers
terraform {
  required_version = ">= 1.0.0"

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

  # Optional: Backend configuration for state file
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "dev/terraform.tfstate"
    region         = "us-west-2"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}

# Provider configuration
provider "aws" {
  region = var.aws_region

  # Optional: Assume role for cross-account deployment
  assume_role {
    role_arn = "arn:aws:iam::123456789012:role/DeploymentRole"
  }

  default_tags {
    tags = {
      Environment = var.environment
      Terraform   = "true"
    }
  }
}

# Variables
variable "aws_region" {
  type        = string
  description = "AWS region to deploy resources"
  default     = "us-west-2"
}

variable "environment" {
  type    = string
  default = "dev"
}

variable "vpc_cidr" {
  type    = string
  default = "10.0.0.0/16"
}

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

  tags = {
    Name = "${var.environment}-main-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, 1)
  availability_zone = "${var.aws_region}a"

  tags = {
    Name = "${var.environment}-public-subnet"
  }
}

# Data source example
data "aws_ami" "ubuntu" {
  most_recent = true

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

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

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

output "subnet_id" {
  description = "ID of the public subnet"
  value       = aws_subnet.public.id
}

output "ubuntu_ami_id" {
  description = "Latest Ubuntu AMI ID"
  value       = data.aws_ami.ubuntu.id
}

Workflow

TL;DR:

  • terraform init
  • terraform plan
  • terraform apply
  • terraform destroy

Extra commands

  • terraform fmt
  • terraform validate
  • terraform import
  • terraform state
  • terraform console
  • terraform output
  • terraform workspace

For more info: terraform --help

Project folder structure example

project-root/
├── environments/
│   ├── dev/
│   │   ├── main.tf          # Environment-specific resources
│   │   ├── variables.tf     # Variable definitions
│   │   ├── outputs.tf       # Output definitions
│   │   ├── versions.tf      # Terraform and provider versions
│   │   ├── backend.tf       # State backend configuration
│   │   └── terraform.tfvars # Variable values for dev
│   │
│   └── prod/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf
│       ├── versions.tf
│       ├── backend.tf
│       └── terraform.tfvars
│
├── modules/
│   ├── vpc/
│   │   ├── main.tf          # VPC resource definitions
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── versions.tf
│   │
│   ├── ecs/
│   │   ├── main.tf          # ECS resource definitions
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── versions.tf
│   │
│   └── rds/
│       ├── main.tf          # RDS resource definitions
│       ├── variables.tf
│       ├── outputs.tf
│       └── versions.tf
│
├── .gitignore
├── .terraform-version       # tfenv version file
└── README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment