A simple and practical template for managing AWS infrastructure with Terraform and GitHub Actions. This project demonstrates multi-environment deployment workflows, automated CI/CD pipelines, and Infrastructure as Code (IaC) patterns. This repository serves as a learning resource and starting point for teams looking to implement Terraform workflows.
- Multi-Environment Support: Isolated workspaces for dev, staging, and production
- GitHub Actions Integration: Manual deployments and automatic PR validation
- AWS SNS/SQS Example: Complete messaging infrastructure with FIFO queues and DLQs
- Environment-Specific Configs: Different retention policies and timeouts per environment
- State Management: S3 backend with encryption and workspace isolation
- Code Quality: Automated formatting checks and validation
Before running Terraform commands locally, you need to install the Terraform CLI.
macOS (Homebrew):
brew tap hashicorp/tap
brew install hashicorp/tap/terraformLinux (Ubuntu/Debian):
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraformVerify installation:
terraform versionFor other installation methods and operating systems, see the official Terraform installation guide.
dev- Developmentstaging- Stagingprod- Production
iac/terraform/
├── providers.tf # AWS configuration and S3 backend
├── variables.tf # Variable declarations
├── locals.tf # Local values (naming, tags, environment configs)
├── sns.tf # SNS Topic FIFO
├── sqs.tf # SQS Queue FIFO + DLQ
├── subscriptions.tf # SNS -> SQS subscriptions
├── iam.tf # IAM/SQS policies
└── outputs.tf # Outputs (ARNs, URLs)
We don't recommend running terraform commands on your local machine, but these commands can be useful at times. Always prefer using GitHub Actions to interact with terraform resources.
This project uses Terraform Workspaces to manage multiple environments with isolated states.
# Initialize
terraform init
# Select or create workspace
terraform workspace select dev # or create: terraform workspace new dev
# List available workspaces
terraform workspace list
# View current workspace
terraform workspace show
# Plan
terraform plan
# Apply
terraform apply
# Destroy (careful!)
terraform destroyComplete example:
cd iac/terraform
terraform init
terraform workspace select dev
terraform plan
terraform applyThe GitHub Actions workflow supports two methods for AWS authentication:
Uses OpenID Connect to assume an IAM role without storing long-term credentials.
Setup:
- Create an IAM OIDC identity provider in AWS for GitHub Actions
- Create an IAM role with trust policy for your GitHub repository
- Add the role ARN as a GitHub secret:
AWS_ROLE
GitHub Secret Required:
AWS_ROLE- IAM Role ARN (e.g.,arn:aws:iam::123456789012:role/GitHubActionsRole)
References:
Uses static AWS access keys (less secure, not recommended for production).
Setup:
- Create an IAM user with programmatic access
- Generate access keys for the user
- Add the keys as GitHub secrets
GitHub Secrets Required:
AWS_ACCESS_KEY_ID- Your AWS access key IDAWS_SECRET_ACCESS_KEY- Your AWS secret access key
Note: If AWS_ROLE is configured, the workflow will use OIDC (Option 1). Otherwise, it will fall back to access keys (Option 2).
- Access Actions → Terraform
- Click Run workflow
- Select:
- Environment: dev, staging, prod
- Action: plan, apply
- Check logs and outputs
When opening a Pull Request with changes to iac/terraform/**, the workflow automatically:
- Checks Terraform file formatting
- Validates file syntax
- Runs
terraform planfor thedevenvironment - Comments the result on the PR
- Allows reviewing changes before merge
GitHub Actions automatically checks if Terraform files are properly formatted. If the check fails, you'll see a message indicating which files need formatting.
How to fix formatting issues:
# Navigate to the Terraform directory
cd iac/terraform
# Format all files automatically
terraform fmt -recursive
# Check formatting without changing files (useful to validate before committing)
terraform fmt -check -recursiveThe terraform fmt command automatically formats all .tf files following Terraform's standard conventions.
- Backend: S3 with Workspaces
- Bucket:
my-terraform-state-bucket(change to your bucket) - Key Base:
sample-app/terraform.tfstate - Workspace Prefix:
env - Region: us-east-1
- Encryption: Enabled
- Organization: Each workspace (environment) has its own isolated state file
env/dev/terraform.tfstateenv/staging/terraform.tfstateenv/prod/terraform.tfstate
This project uses Terraform Workspaces to manage environments. The active workspace determines which environment is being managed.
Available workspaces:
dev- Developmentstaging- Stagingprod- Production
How it works:
- Each workspace has its own isolated state file in S3
- The workspace name is automatically used via
terraform.workspace - Resources are named with prefix:
{workspace}_sample_* - Example:
dev_sample_events.fifo(SNS),prod_sample_processor.fifo(SQS)
| Variable | Description | Default |
|---|---|---|
aws_region |
AWS Region | us-east-1 |
SQS configurations are automatically defined based on the active workspace (environment):
| Environment | Message Retention | Visibility Timeout | DLQ Retention | Max Receive Count |
|---|---|---|---|---|
dev |
1 day (86400s) | 30s | 4 days (345600s) | 3 |
staging |
3 days (259200s) | 45s | 7 days (604800s) | 3 |
prod |
7 days (604800s) | 60s | 14 days (1209600s) | 3 |
To add specific configurations for other environments, edit the sqs_config map in iac/terraform/locals.tf.
- Add environment to workflow options in
.github/workflows/terraform.yml(environment.optionsfield) - Create workspace locally or via GitHub Actions (automatically created on first use)
- Update this documentation in the "Workspaces" section
This example provisions:
SNS (Simple Notification Service):
- 1 SNS Topic FIFO:
{workspace}_sample_events.fifo - Content-based deduplication enabled
SQS (Simple Queue Service):
- 1 Main FIFO Queue:
{workspace}_sample_processor.fifo - 1 Dead Letter Queue (DLQ):
{workspace}_sample_processor_dlq.fifo - Redrive policy configured (max 3 attempts)
Integration:
- 1 Subscription SNS → SQS (fanout pattern)
- IAM Policy allowing SNS to send to SQS
To add new AWS resources:
- Create a new
.tffile following the modular pattern (e.g.,rds.tf,ec2.tf,lambda.tf) - Update
outputs.tfwith the necessary outputs (ARNs, URLs, IDs) - If applicable, update
iam.tfwith required permissions - Add environment-specific configurations in
locals.tfif needed - Run
terraform fmt -recursiveto format the code