This commit is contained in:
Toby
2026-01-27 17:35:45 -05:00
commit 2639af6531
176 changed files with 27104 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
---
name: aws-ec2
description: Manage EC2 instances, AMIs, and auto-scaling groups. Configure security groups, key pairs, and instance types. Use when deploying compute resources on AWS.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS EC2
Deploy and manage Amazon EC2 compute instances.
## Launch Instance
```bash
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--key-name my-key \
--security-group-ids sg-12345678 \
--subnet-id subnet-12345678 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-server}]'
```
## Auto Scaling
```bash
# Create launch template
aws ec2 create-launch-template \
--launch-template-name web-template \
--version-description v1 \
--launch-template-data '{
"ImageId": "ami-xxx",
"InstanceType": "t3.micro"
}'
# Create ASG
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name web-asg \
--launch-template LaunchTemplateName=web-template \
--min-size 2 --max-size 10 --desired-capacity 2 \
--vpc-zone-identifier "subnet-xxx,subnet-yyy"
```
## User Data
```bash
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
```
## Instance Management
```bash
# List instances
aws ec2 describe-instances --filters "Name=tag:Name,Values=web*"
# Stop/Start
aws ec2 stop-instances --instance-ids i-xxx
aws ec2 start-instances --instance-ids i-xxx
# Create AMI
aws ec2 create-image --instance-id i-xxx --name "my-ami"
```
## Best Practices
- Use launch templates
- Implement auto-scaling
- Use spot instances for cost savings
- Regular AMI updates
- Instance metadata service v2
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [aws-vpc](../aws-vpc/) - Networking
@@ -0,0 +1,98 @@
# EC2 Operations Reference
## Instance Management
```bash
# Launch instance
aws ec2 run-instances \
--image-id ami-12345678 \
--instance-type t3.micro \
--key-name mykey \
--security-group-ids sg-12345678 \
--subnet-id subnet-12345678
# Start/Stop/Terminate
aws ec2 start-instances --instance-ids i-12345678
aws ec2 stop-instances --instance-ids i-12345678
aws ec2 terminate-instances --instance-ids i-12345678
# Describe instances
aws ec2 describe-instances \
--filters "Name=tag:Environment,Values=prod"
```
## AMI Management
```bash
# Create AMI from instance
aws ec2 create-image \
--instance-id i-12345678 \
--name "MyApp-$(date +%Y%m%d)"
# Copy AMI to another region
aws ec2 copy-image \
--source-image-id ami-12345678 \
--source-region us-east-1 \
--region us-west-2 \
--name "MyApp-copy"
```
## Instance Types
| Type | vCPU | Memory | Use Case |
|------|------|--------|----------|
| t3.micro | 2 | 1 GB | Dev/Test |
| t3.small | 2 | 2 GB | Light apps |
| m5.large | 2 | 8 GB | General |
| c5.large | 2 | 4 GB | Compute |
| r5.large | 2 | 16 GB | Memory |
## User Data
```bash
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello World" > /var/www/html/index.html
```
## Instance Metadata
```bash
# IMDSv2
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
# Common endpoints
/latest/meta-data/instance-id
/latest/meta-data/local-ipv4
/latest/meta-data/public-ipv4
/latest/meta-data/iam/security-credentials/role-name
```
## Terraform
```hcl
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.app.id]
subnet_id = aws_subnet.private.id
iam_instance_profile = aws_iam_instance_profile.app.name
user_data = base64encode(file("userdata.sh"))
root_block_device {
volume_size = 20
encrypted = true
}
tags = {
Name = "app-server"
}
}
```
@@ -0,0 +1,88 @@
---
name: aws-ecs-fargate
description: Deploy containers on ECS and Fargate. Configure task definitions, services, and load balancing. Use when running containerized workloads on AWS.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS ECS & Fargate
Run containerized applications on Amazon ECS with Fargate.
## Task Definition
```json
{
"family": "myapp",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "myapp",
"image": "xxx.dkr.ecr.region.amazonaws.com/myapp:latest",
"portMappings": [{
"containerPort": 8080,
"protocol": "tcp"
}],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}]
}
```
## Create Service
```bash
aws ecs create-service \
--cluster my-cluster \
--service-name myapp \
--task-definition myapp:1 \
--desired-count 2 \
--launch-type FARGATE \
--network-configuration '{
"awsvpcConfiguration": {
"subnets": ["subnet-xxx"],
"securityGroups": ["sg-xxx"],
"assignPublicIp": "ENABLED"
}
}' \
--load-balancers '[{
"targetGroupArn": "arn:aws:elasticloadbalancing:...",
"containerName": "myapp",
"containerPort": 8080
}]'
```
## Deployment
```bash
# Update service
aws ecs update-service \
--cluster my-cluster \
--service myapp \
--task-definition myapp:2 \
--force-new-deployment
```
## Best Practices
- Use ECR for images
- Implement service discovery
- Configure health checks
- Use secrets manager for secrets
- Enable container insights
## Related Skills
- [docker-management](../../../devops/containers/docker-management/) - Container basics
- [container-registries](../../../devops/containers/container-registries/) - ECR
+97
View File
@@ -0,0 +1,97 @@
---
name: aws-iam
description: Manage IAM users, roles, and policies. Implement least-privilege access and security best practices. Use when configuring AWS identity and access management.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS IAM
Manage identity and access in AWS.
## IAM Policies
```json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
```
## Create Role
```bash
# Create role with trust policy
aws iam create-role \
--role-name EC2AppRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
# Attach policy
aws iam attach-role-policy \
--role-name EC2AppRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
```
## Service-Linked Roles
```bash
# For services like ECS, RDS
aws iam create-service-linked-role \
--aws-service-name ecs.amazonaws.com
```
## Best Practices
```yaml
security_practices:
- Use roles, not long-term credentials
- Implement least privilege
- Enable MFA
- Regular access reviews
- Use IAM Access Analyzer
- Implement SCPs for organizations
```
## Policy Conditions
```json
{
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1"
},
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
```
## Best Practices
- Follow least privilege
- Use IAM roles for applications
- Enable CloudTrail for auditing
- Regular credential rotation
- Use permission boundaries
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [access-review](../../../compliance/governance/access-review/) - Access auditing
@@ -0,0 +1,84 @@
---
name: aws-lambda
description: Build and deploy serverless functions on AWS Lambda. Configure triggers, manage permissions, and optimize performance. Use when implementing serverless applications.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS Lambda
Build serverless applications with AWS Lambda.
## Create Function
```bash
# Create function
aws lambda create-function \
--function-name myfunction \
--runtime python3.11 \
--handler app.handler \
--role arn:aws:iam::xxx:role/lambda-role \
--zip-file fileb://function.zip
# Update code
aws lambda update-function-code \
--function-name myfunction \
--zip-file fileb://function.zip
```
## Function Code
```python
# app.py
import json
def handler(event, context):
return {
'statusCode': 200,
'body': json.dumps({'message': 'Hello!'})
}
```
## API Gateway Integration
```bash
# Create REST API
aws apigateway create-rest-api --name myapi
# Add Lambda permission
aws lambda add-permission \
--function-name myfunction \
--statement-id apigateway \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com
```
## Environment & Configuration
```bash
# Set environment variables
aws lambda update-function-configuration \
--function-name myfunction \
--environment "Variables={DB_HOST=xxx,API_KEY=yyy}"
# Set memory and timeout
aws lambda update-function-configuration \
--function-name myfunction \
--memory-size 256 \
--timeout 30
```
## Best Practices
- Minimize cold starts
- Use layers for dependencies
- Implement proper error handling
- Use provisioned concurrency for latency-sensitive functions
- Monitor with CloudWatch
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [aws-iam](../aws-iam/) - Execution roles
+78
View File
@@ -0,0 +1,78 @@
---
name: aws-rds
description: Provision and manage RDS databases. Configure backups, replication, and security. Use when deploying managed relational databases on AWS.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS RDS
Deploy managed relational databases with Amazon RDS.
## Create Database
```bash
aws rds create-db-instance \
--db-instance-identifier mydb \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 15 \
--master-username admin \
--master-user-password secretpassword \
--allocated-storage 20 \
--storage-encrypted \
--vpc-security-group-ids sg-xxx \
--db-subnet-group-name my-subnet-group \
--backup-retention-period 7 \
--multi-az
```
## Parameter Groups
```bash
aws rds create-db-parameter-group \
--db-parameter-group-name custom-pg \
--db-parameter-group-family postgres15 \
--description "Custom PostgreSQL parameters"
aws rds modify-db-parameter-group \
--db-parameter-group-name custom-pg \
--parameters "ParameterName=max_connections,ParameterValue=200,ApplyMethod=pending-reboot"
```
## Snapshots & Recovery
```bash
# Create snapshot
aws rds create-db-snapshot \
--db-instance-identifier mydb \
--db-snapshot-identifier mydb-snapshot
# Restore from snapshot
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier mydb-restored \
--db-snapshot-identifier mydb-snapshot
```
## Read Replicas
```bash
aws rds create-db-instance-read-replica \
--db-instance-identifier mydb-replica \
--source-db-instance-identifier mydb
```
## Best Practices
- Enable Multi-AZ for production
- Use encryption at rest
- Implement automated backups
- Use read replicas for read scaling
- Store credentials in Secrets Manager
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [aws-secrets-manager](../../../security/secrets/aws-secrets-manager/) - Credentials
+88
View File
@@ -0,0 +1,88 @@
---
name: aws-s3
description: Configure S3 buckets, policies, and lifecycle rules. Implement versioning, replication, and security. Use when managing object storage on AWS.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS S3
Manage object storage with Amazon S3.
## Create Bucket
```bash
aws s3api create-bucket \
--bucket my-bucket \
--region us-east-1
# Enable versioning
aws s3api put-bucket-versioning \
--bucket my-bucket \
--versioning-configuration Status=Enabled
# Block public access
aws s3api put-public-access-block \
--bucket my-bucket \
--public-access-block-configuration '{
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}'
```
## Bucket Policy
```json
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "EnforceHTTPS",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
],
"Condition": {
"Bool": {"aws:SecureTransport": "false"}
}
}]
}
```
## Lifecycle Rules
```bash
aws s3api put-bucket-lifecycle-configuration \
--bucket my-bucket \
--lifecycle-configuration '{
"Rules": [{
"ID": "Archive old objects",
"Status": "Enabled",
"Filter": {"Prefix": "logs/"},
"Transitions": [{
"Days": 30,
"StorageClass": "GLACIER"
}],
"Expiration": {"Days": 365}
}]
}'
```
## Best Practices
- Enable versioning
- Block public access
- Use encryption (SSE-S3 or SSE-KMS)
- Implement lifecycle policies
- Enable access logging
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [aws-iam](../aws-iam/) - Access policies
+84
View File
@@ -0,0 +1,84 @@
---
name: aws-vpc
description: Design and implement VPCs and networking. Configure subnets, route tables, and security groups. Use when setting up AWS network infrastructure.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# AWS VPC
Design and manage Virtual Private Cloud networking.
## Create VPC
```bash
# Create VPC
aws ec2 create-vpc --cidr-block 10.0.0.0/16
# Create subnets
aws ec2 create-subnet \
--vpc-id vpc-xxx \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a
# Create internet gateway
aws ec2 create-internet-gateway
aws ec2 attach-internet-gateway --vpc-id vpc-xxx --internet-gateway-id igw-xxx
```
## Network Architecture
```
VPC (10.0.0.0/16)
├── Public Subnets
│ ├── 10.0.1.0/24 (us-east-1a)
│ └── 10.0.2.0/24 (us-east-1b)
├── Private Subnets
│ ├── 10.0.11.0/24 (us-east-1a)
│ └── 10.0.12.0/24 (us-east-1b)
├── Internet Gateway
├── NAT Gateway (in public subnet)
└── Route Tables
```
## Security Groups
```bash
aws ec2 create-security-group \
--group-name web-sg \
--description "Web server security group" \
--vpc-id vpc-xxx
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
```
## NAT Gateway
```bash
# Allocate EIP
aws ec2 allocate-address --domain vpc
# Create NAT Gateway
aws ec2 create-nat-gateway \
--subnet-id subnet-public \
--allocation-id eipalloc-xxx
```
## Best Practices
- Use multiple AZs
- Separate public/private subnets
- Implement VPC Flow Logs
- Use security groups effectively
- Plan CIDR ranges carefully
## Related Skills
- [terraform-aws](../terraform-aws/) - IaC deployment
- [firewall-config](../../../security/network/firewall-config/) - Security
@@ -0,0 +1,93 @@
---
name: cloudformation
description: Deploy AWS resources with CloudFormation templates. Create stacks, use nested stacks, and implement drift detection. Use when deploying AWS-native IaC.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# CloudFormation
Deploy AWS infrastructure with native CloudFormation templates.
## Template Structure
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Web application stack
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
Resources:
WebServer:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AMI
InstanceType: t3.micro
Tags:
- Key: Name
Value: !Sub '${Environment}-web'
Outputs:
InstanceId:
Value: !Ref WebServer
Export:
Name: !Sub '${Environment}-WebServerId'
```
## Stack Operations
```bash
# Create stack
aws cloudformation create-stack \
--stack-name myapp \
--template-body file://template.yaml \
--parameters ParameterKey=Environment,ParameterValue=prod
# Update stack
aws cloudformation update-stack \
--stack-name myapp \
--template-body file://template.yaml
# Delete stack
aws cloudformation delete-stack --stack-name myapp
# Detect drift
aws cloudformation detect-stack-drift --stack-name myapp
```
## Intrinsic Functions
```yaml
# Reference
!Ref MyResource
# Get attribute
!GetAtt MyResource.Arn
# Substitute
!Sub 'arn:aws:s3:::${BucketName}/*'
# Conditional
!If [CreateProdResources, 't3.large', 't3.micro']
# Join
!Join ['-', [!Ref Environment, 'app', 'bucket']]
```
## Best Practices
- Use change sets before updates
- Implement stack policies
- Use nested stacks for modularity
- Enable termination protection
- Use cfn-lint for validation
## Related Skills
- [terraform-aws](../terraform-aws/) - Alternative IaC
- [aws-iam](../aws-iam/) - IAM resources
@@ -0,0 +1,123 @@
# CloudFormation Syntax Reference
## Template Structure
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: My CloudFormation Template
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
Mappings:
RegionMap:
us-east-1:
AMI: ami-12345678
Conditions:
IsProd: !Equals [!Ref Environment, prod]
Resources:
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${AWS::StackName}-bucket'
Outputs:
BucketName:
Value: !Ref MyBucket
Export:
Name: !Sub '${AWS::StackName}-bucket'
```
## Intrinsic Functions
```yaml
# Reference
!Ref MyResource
# GetAtt
!GetAtt MyResource.Arn
# Sub (string substitution)
!Sub '${AWS::StackName}-resource'
!Sub
- 'arn:aws:s3:::${Bucket}/*'
- Bucket: !Ref MyBucket
# Join
!Join ['-', [!Ref Environment, app]]
# Select
!Select [0, !GetAZs '']
# Split
!Split [',', 'a,b,c']
# If
!If [IsProd, 3, 1]
# ImportValue
!ImportValue ExportedValue
```
## Common Patterns
### Cross-Stack References
```yaml
# Stack A - Export
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: SharedVPC
# Stack B - Import
Resources:
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !ImportValue SharedVPC
```
### Nested Stacks
```yaml
Resources:
VPCStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/vpc.yaml
Parameters:
Environment: !Ref Environment
```
### DependsOn
```yaml
Resources:
MyInstance:
Type: AWS::EC2::Instance
DependsOn: MySecurityGroup
```
## CLI Commands
```bash
# Create stack
aws cloudformation create-stack \
--stack-name mystack \
--template-body file://template.yaml \
--parameters ParameterKey=Environment,ParameterValue=prod
# Update stack
aws cloudformation update-stack \
--stack-name mystack \
--template-body file://template.yaml
# Delete stack
aws cloudformation delete-stack --stack-name mystack
# Validate template
aws cloudformation validate-template --template-body file://template.yaml
```
@@ -0,0 +1,100 @@
---
name: terraform-aws
description: Provision AWS infrastructure with Terraform. Create modules, manage state, and implement IaC best practices. Use when deploying AWS resources declaratively.
license: MIT
metadata:
author: devops-skills
version: "1.0"
---
# Terraform AWS
Provision and manage AWS infrastructure with Terraform.
## Provider Configuration
```hcl
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
provider "aws" {
region = var.region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "terraform"
}
}
}
```
## Example Resources
```hcl
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = { Name = "main-vpc" }
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
tags = { Name = "web-server" }
}
```
## Modules
```hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "my-vpc"
cidr = "10.0.0.0/16"
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"]
enable_nat_gateway = true
}
```
## Commands
```bash
terraform init
terraform plan -out=plan.tfplan
terraform apply plan.tfplan
terraform destroy
```
## Best Practices
- Use remote state with locking
- Implement module structure
- Use workspaces or separate states per environment
- Pin provider versions
- Use data sources for AMIs
## Related Skills
- [aws-vpc](../aws-vpc/) - VPC networking
- [aws-iam](../aws-iam/) - IAM policies
@@ -0,0 +1,152 @@
# AWS VPC Module Template
# Production-ready VPC with public and private subnets
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "Availability zones"
type = list(string)
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
variable "enable_nat_gateway" {
description = "Enable NAT Gateway for private subnets"
type = bool
default = true
}
locals {
public_subnets = [for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i)]
private_subnets = [for i, az in var.availability_zones : cidrsubnet(var.vpc_cidr, 8, i + 10)]
}
# VPC
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.project_name}-vpc"
}
}
# Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.project_name}-igw"
}
}
# Public Subnets
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = local.public_subnets[count.index]
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-public-${var.availability_zones[count.index]}"
"kubernetes.io/role/elb" = "1"
}
}
# Private Subnets
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = local.private_subnets[count.index]
availability_zone = var.availability_zones[count.index]
tags = {
Name = "${var.project_name}-private-${var.availability_zones[count.index]}"
"kubernetes.io/role/internal-elb" = "1"
}
}
# Elastic IP for NAT Gateway
resource "aws_eip" "nat" {
count = var.enable_nat_gateway ? 1 : 0
domain = "vpc"
tags = {
Name = "${var.project_name}-nat-eip"
}
}
# NAT Gateway
resource "aws_nat_gateway" "main" {
count = var.enable_nat_gateway ? 1 : 0
allocation_id = aws_eip.nat[0].id
subnet_id = aws_subnet.public[0].id
tags = {
Name = "${var.project_name}-nat"
}
depends_on = [aws_internet_gateway.main]
}
# Public Route Table
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${var.project_name}-public-rt"
}
}
# Private Route Table
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
dynamic "route" {
for_each = var.enable_nat_gateway ? [1] : []
content {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main[0].id
}
}
tags = {
Name = "${var.project_name}-private-rt"
}
}
# Route Table Associations
resource "aws_route_table_association" "public" {
count = length(var.availability_zones)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "private" {
count = length(var.availability_zones)
subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.private.id
}
# Outputs
output "vpc_id" {
value = aws_vpc.main.id
}
output "public_subnet_ids" {
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
@@ -0,0 +1,185 @@
# Terraform AWS Best Practices
## Project Structure
```
project/
├── main.tf # Main configuration
├── variables.tf # Input variables
├── outputs.tf # Output values
├── locals.tf # Local values
├── data.tf # Data sources
├── versions.tf # Provider versions
├── terraform.tfvars # Variable values (git-ignored)
├── modules/ # Local modules
│ └── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── environments/ # Environment configs
├── dev/
├── staging/
└── prod/
```
## State Management
### Remote State with S3
```hcl
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "project/env/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
```
### State Locking
```hcl
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
```
## Security Best Practices
### Use IAM Roles, Not Credentials
```hcl
provider "aws" {
region = "us-east-1"
# No access_key or secret_key - use IAM role or env vars
}
```
### Enable Encryption Everywhere
```hcl
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.example.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.example.arn
}
}
}
```
### Use Sensitive Variables
```hcl
variable "database_password" {
type = string
sensitive = true
}
```
## Tagging Strategy
```hcl
locals {
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
Owner = var.team
CostCenter = var.cost_center
}
}
resource "aws_instance" "example" {
# ... configuration ...
tags = merge(local.common_tags, {
Name = "example-instance"
Role = "web"
})
}
```
## Module Best Practices
### Version Pinning
```hcl
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0" # Pin specific version
# ... configuration ...
}
```
### Variable Validation
```hcl
variable "environment" {
type = string
description = "Environment name"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
```
## Workflow
### Plan Before Apply
```bash
terraform plan -out=tfplan
terraform apply tfplan
```
### Use Workspaces or Directories for Environments
```bash
# Workspaces
terraform workspace new prod
terraform workspace select prod
# Or separate directories (recommended)
cd environments/prod
terraform apply
```
## Common Patterns
### Data Sources for Existing Resources
```hcl
data "aws_vpc" "existing" {
filter {
name = "tag:Name"
values = ["main-vpc"]
}
}
resource "aws_subnet" "new" {
vpc_id = data.aws_vpc.existing.id
# ...
}
```
### Dynamic Blocks
```hcl
resource "aws_security_group" "example" {
# ...
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
```
@@ -0,0 +1,134 @@
#!/bin/bash
# Terraform AWS Project Initialization Script
# Usage: ./tf-init.sh <project-name> [region]
set -euo pipefail
PROJECT_NAME="${1:-}"
REGION="${2:-us-east-1}"
if [ -z "$PROJECT_NAME" ]; then
echo "Usage: $0 <project-name> [region]"
exit 1
fi
echo "========================================="
echo "Terraform AWS Project Setup"
echo "Project: $PROJECT_NAME"
echo "Region: $REGION"
echo "========================================="
echo ""
mkdir -p "$PROJECT_NAME"
cd "$PROJECT_NAME"
# Create main.tf
cat > main.tf << EOF
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
# Uncomment for remote state
# backend "s3" {
# bucket = "${PROJECT_NAME}-tfstate"
# key = "terraform.tfstate"
# region = "${REGION}"
# encrypt = true
# dynamodb_table = "${PROJECT_NAME}-tflock"
# }
}
provider "aws" {
region = var.region
default_tags {
tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
}
EOF
# Create variables.tf
cat > variables.tf << EOF
variable "project_name" {
description = "Project name for tagging"
type = string
default = "${PROJECT_NAME}"
}
variable "environment" {
description = "Environment (dev, staging, prod)"
type = string
default = "dev"
}
variable "region" {
description = "AWS region"
type = string
default = "${REGION}"
}
EOF
# Create outputs.tf
cat > outputs.tf << EOF
output "region" {
description = "AWS region"
value = var.region
}
EOF
# Create terraform.tfvars
cat > terraform.tfvars << EOF
project_name = "${PROJECT_NAME}"
environment = "dev"
region = "${REGION}"
EOF
# Create .gitignore
cat > .gitignore << EOF
# Terraform
.terraform/
*.tfstate
*.tfstate.*
*.tfvars.json
crash.log
*.tfplan
# Keep tfvars template
!terraform.tfvars.example
# IDE
.idea/
*.swp
*.swo
.vscode/
EOF
# Initialize Terraform
echo ""
echo "Initializing Terraform..."
terraform init
echo ""
echo "========================================="
echo "Project created successfully!"
echo ""
echo "Files created:"
ls -la
echo ""
echo "Next steps:"
echo " 1. cd $PROJECT_NAME"
echo " 2. Edit terraform.tfvars"
echo " 3. Add resources to main.tf"
echo " 4. terraform plan"
echo " 5. terraform apply"
echo "========================================="