Use this skill for all infrastructure and DevOps tasks: Terraform/OpenTofu IaC, Pulumi, AWS CDK, Bicep/ARM, Ansible playbooks, GitHub Actions CI/CD, GitLab CI, Jenkins pipelines, ArgoCD/Flux GitOps, Tekton pipelines, AWS/GCP/Azure architecture, multi-cloud cost optimisation, FinOps tagging standards, and disaster recovery runbooks. Triggers: "infrastructure", "IaC", "Terraform", "Pulumi", "CDK", "Ansible", "CI/CD", "GitHub Actions", "GitLab CI", "ArgoCD", "GitOps", "AWS", "GCP", "Azure", "cloud", "FinOps", "cost optimisation", "disaster recovery", "DR runbook".
Infrastructure errors are expensive and often irreversible. This skill provides tool-backed, production-grade IaC scaffolding and CI/CD pipeline generation with security best practices, cost controls, and disaster recovery built-in from the start — not added later.
Always read existing IaC files before generating new ones to match naming conventions, variable style, and module structure.
# Detect what IaC tools are in use
find . -name "*.tf" -o -name "*.tfvars" | head -5 && echo "Terraform found"
find . -name "Pulumi.yaml" -o -name "Pulumi.*.yaml" | head -3 && echo "Pulumi found"
find . -name "cdk.json" -o -name "cdk.out" -type d | head -3 && echo "CDK found"
find . -name "*.bicep" | head -3 && echo "Bicep found"
find . -name "*.yml" -path "*/.github/workflows/*" | head -5 && echo "GitHub Actions found"
find . -name ".gitlab-ci.yml" && echo "GitLab CI found"
find . -name "Jenkinsfile*" | head -3 && echo "Jenkins found"
find . -name "application.yaml" -path "*/argocd/*" | head -3 && echo "ArgoCD found"
# Terraform state backend
grep -rn "backend\s*\"" --include="*.tf" . | head -5
# Cloud provider detection
grep -rn "provider\s*\"aws\"\|provider\s*\"google\"\|provider\s*\"azurerm\"" \
--include="*.tf" . | head -5
infra/
├── environments/
│ ├── dev/
│ │ ├── main.tf # calls modules
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── prod/
│
├── modules/
│ ├── networking/ # VPC, subnets, security groups
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/ # ECS/EKS/EC2
│ ├── database/ # RDS, ElastiCache
│ ├── storage/ # S3, EFS
│ ├── iam/ # roles, policies
│ └── monitoring/ # CloudWatch, alarms
│
├── shared/
│ ├── backend.tf # remote state config
│ └── providers.tf
│
└── scripts/
├── plan.sh
└── apply.sh
# infra/shared/backend.tf
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
backend "s3" {
bucket = "myapp-terraform-state-prod"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
kms_key_id = "arn:aws:kms:us-east-1:ACCOUNT:key/KEY-ID"
}
}
# infra/modules/networking/main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(var.common_tags, {
Name = "${var.environment}-vpc"
})
}
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 4, count.index)
availability_zone = var.availability_zones[count.index]
tags = merge(var.common_tags, {
Name = "${var.environment}-private-${count.index + 1}"
Tier = "private"
})
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 4, count.index + 10)
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(var.common_tags, {
Name = "${var.environment}-public-${count.index + 1}"
Tier = "public"
})
}
# infra/modules/tagging/variables.tf
variable "common_tags" {
description = "Standard tags applied to all resources"
type = object({
Environment = string # dev | staging | prod
Project = string # e.g. "payments-api"
Team = string # e.g. "platform"
CostCenter = string # e.g. "eng-platform-001"
Owner = string # e.g. "[email protected]"
ManagedBy = string # terraform | pulumi | manual
DataClass = string # public | internal | confidential | restricted
})
}
# Usage in all modules
tags = merge(var.common_tags, { Name = "specific-resource-name" })
# tfsec — security scanner for Terraform
tfsec . --format json 2>/dev/null \
| python3 -c "
import json, sys
d = json.load(sys.stdin)
results = d.get('results', [])
for r in sorted(results, key=lambda x: x.get('severity',''), reverse=True):
print(f\"{r.get('severity','?'):8} {r.get('rule_id','?')} {r.get('location',{}).get('filename','?')}:{r.get('location',{}).get('start_line','?')}\")
print(f\" {r.get('description','')[:80]}\")
print(f'Total: {len(results)}')
"
# checkov — broader IaC scanner
checkov -d . --framework terraform --quiet 2>/dev/null | tail -20
# terraform validate
terraform validate 2>/dev/null
# terraform plan with cost estimate (Infracost)
infracost breakdown --path . 2>/dev/null | tail -20
// infra/index.ts
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
const config = new pulumi.Config();
const env = config.require("environment");
const commonTags = {
Environment: env,
ManagedBy: "pulumi",
Project: "myapp",
};
// VPC with public/private subnets
const vpc = new awsx.ec2.Vpc(`${env}-vpc`, {
numberOfAvailabilityZones: 2,
natGateways: { strategy: env === "prod" ? "OnePerAz" : "Single" },
tags: commonTags,
});
// ECS Fargate cluster
const cluster = new aws.ecs.Cluster(`${env}-cluster`, {
settings: [{ name: "containerInsights", value: "enabled" }],
tags: commonTags,
});
// RDS PostgreSQL
const db = new aws.rds.Instance(`${env}-postgres`, {
engine: "postgres",
engineVersion: "15.4",
instanceClass: env === "prod" ? "db.t3.medium" : "db.t3.micro",
allocatedStorage: env === "prod" ? 100 : 20,
storageEncrypted: true,
multiAz: env === "prod",
deletionProtection: env === "prod",
skipFinalSnapshot: env !== "prod",
tags: commonTags,
});
export const vpcId = vpc.vpcId;
export const dbEndpoint = db.endpoint;
// lib/stacks/AppStack.ts
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as rds from "aws-cdk-lib/aws-rds";
import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager";
export class AppStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props: AppStackProps) {
super(scope, id, props);
// VPC
const vpc = new ec2.Vpc(this, "VPC", {
maxAzs: props.isProd ? 3 : 2,
natGateways: props.isProd ? 3 : 1,
});
// RDS (credentials auto-rotated via Secrets Manager)
const dbSecret = new secretsmanager.Secret(this, "DBSecret", {
generateSecretString: {
secretStringTemplate: JSON.stringify({ username: "appuser" }),
generateStringKey: "password",
excludeCharacters: "/@\"",
},
});
const db = new rds.DatabaseInstance(this, "Database", {
engine: rds.DatabaseInstanceEngine.postgres({ version: rds.PostgresEngineVersion.VER_15 }),
vpc,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
credentials: rds.Credentials.fromSecret(dbSecret),
multiAz: props.isProd,
storageEncrypted: true,
deletionProtection: props.isProd,
});
// ECS Fargate service
const cluster = new ecs.Cluster(this, "Cluster", { vpc, containerInsights: true });
const taskDef = new ecs.FargateTaskDefinition(this, "TaskDef", {
memoryLimitMiB: 512,
cpu: 256,
});
taskDef.addContainer("App", {
image: ecs.ContainerImage.fromRegistry("myapp:latest"),
portMappings: [{ containerPort: 3000 }],
secrets: {
DATABASE_URL: ecs.Secret.fromSecretsManager(dbSecret, "password"),
},
logging: ecs.LogDrivers.awsLogs({ streamPrefix: "app" }),
});
// Tag everything
cdk.Tags.of(this).add("Environment", props.environment);
cdk.Tags.of(this).add("ManagedBy", "cdk");
}
}
# .github/workflows/ci-cd.yml