A Pulumi package for creating and managing Amazon Web Services (AWS) cloud resources with infrastructure-as-code.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Get productive with Pulumi AWS in 5 minutes.
npm install @pulumi/aws @pulumi/pulumiimport * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";For specific services:
import { s3, ec2, lambda, iam, rds, dynamodb } from "@pulumi/aws";Pulumi uses AWS credentials from your environment. Set up using one of:
aws configureexport AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-west-2"const provider = new aws.Provider("provider", {
region: "us-west-2",
profile: "my-profile", // AWS CLI profile
});import * as aws from "@pulumi/aws";
// Create a bucket
const bucket = new aws.s3.BucketV2("my-bucket", {
tags: {
Environment: "dev",
Purpose: "data-storage",
},
});
// Enable versioning
const versioning = new aws.s3.BucketVersioningV2("bucket-versioning", {
bucket: bucket.id,
versioningConfiguration: {
status: "Enabled",
},
});
// Block public access
const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("bucket-pab", {
bucket: bucket.id,
blockPublicAcls: true,
blockPublicPolicy: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
});
// Export bucket name and ARN
export const bucketName = bucket.id;
export const bucketArn = bucket.arn;import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
// Create IAM role for Lambda
const lambdaRole = new aws.iam.Role("lambda-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Action: "sts:AssumeRole",
Effect: "Allow",
Principal: {
Service: "lambda.amazonaws.com",
},
}],
}),
});
// Attach basic execution policy
const lambdaPolicy = new aws.iam.RolePolicyAttachment("lambda-policy", {
role: lambdaRole.name,
policyArn: aws.iam.ManagedPolicy.AWSLambdaBasicExecutionRole,
});
// Create Lambda function
const lambdaFunction = new aws.lambda.Function("my-function", {
runtime: aws.lambda.Runtime.NodeJS20dX,
handler: "index.handler",
role: lambdaRole.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./lambda"),
}),
environment: {
variables: {
LOG_LEVEL: "info",
},
},
});
// Export function ARN
export const functionArn = lambdaFunction.arn;
export const functionName = lambdaFunction.name;import * as aws from "@pulumi/aws";
// Create VPC
const vpc = new aws.ec2.Vpc("my-vpc", {
cidrBlock: "10.0.0.0/16",
enableDnsHostnames: true,
enableDnsSupport: true,
tags: { Name: "my-vpc" },
});
// Create public subnet
const publicSubnet = new aws.ec2.Subnet("public-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-west-2a",
mapPublicIpOnLaunch: true,
tags: { Name: "public-subnet" },
});
// Create private subnet
const privateSubnet = new aws.ec2.Subnet("private-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.2.0/24",
availabilityZone: "us-west-2b",
tags: { Name: "private-subnet" },
});
// Create Internet Gateway
const igw = new aws.ec2.InternetGateway("igw", {
vpcId: vpc.id,
tags: { Name: "my-igw" },
});
// Create route table for public subnet
const publicRouteTable = new aws.ec2.RouteTable("public-rt", {
vpcId: vpc.id,
routes: [{
cidrBlock: "0.0.0.0/0",
gatewayId: igw.id,
}],
tags: { Name: "public-rt" },
});
// Associate route table with public subnet
const publicRtAssociation = new aws.ec2.RouteTableAssociation("public-rt-assoc", {
subnetId: publicSubnet.id,
routeTableId: publicRouteTable.id,
});
// Export VPC and subnet IDs
export const vpcId = vpc.id;
export const publicSubnetId = publicSubnet.id;
export const privateSubnetId = privateSubnet.id;import * as aws from "@pulumi/aws";
// Create DynamoDB table
const table = new aws.dynamodb.Table("my-table", {
attributes: [
{ name: "id", type: "S" },
{ name: "timestamp", type: "N" },
],
hashKey: "id",
rangeKey: "timestamp",
billingMode: "PAY_PER_REQUEST",
streamEnabled: true,
streamViewType: "NEW_AND_OLD_IMAGES",
pointInTimeRecovery: {
enabled: true,
},
tags: {
Environment: "production",
},
});
// Export table name and ARN
export const tableName = table.name;
export const tableArn = table.arn;
export const streamArn = table.streamArn;import * as aws from "@pulumi/aws";
// Create DB subnet group
const dbSubnetGroup = new aws.rds.SubnetGroup("db-subnet-group", {
subnetIds: [privateSubnet1.id, privateSubnet2.id],
tags: { Name: "my-db-subnet-group" },
});
// Create security group for RDS
const dbSecurityGroup = new aws.ec2.SecurityGroup("db-sg", {
vpcId: vpc.id,
description: "Allow PostgreSQL access",
ingress: [{
protocol: "tcp",
fromPort: 5432,
toPort: 5432,
cidrBlocks: ["10.0.0.0/16"],
}],
tags: { Name: "db-security-group" },
});
// Create RDS instance
const db = new aws.rds.Instance("my-db", {
engine: "postgres",
engineVersion: "15.4",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
dbName: "myapp",
username: "admin",
password: dbPassword, // Use Pulumi config or Secrets Manager
dbSubnetGroupName: dbSubnetGroup.name,
vpcSecurityGroupIds: [dbSecurityGroup.id],
skipFinalSnapshot: false,
finalSnapshotIdentifier: "my-db-final-snapshot",
backupRetentionPeriod: 7,
storageEncrypted: true,
tags: { Name: "my-database" },
});
// Export connection info
export const dbEndpoint = db.endpoint;
export const dbAddress = db.address;
export const dbPort = db.port;Outputs represent values that may not be known until after deployment:
// Get output values
const bucket = new aws.s3.BucketV2("bucket");
// Export directly
export const bucketName = bucket.id; // Output<string>
// Transform outputs
export const bucketDomain = bucket.bucket.apply(name =>
`${name}.s3.amazonaws.com`
);
// Use outputs as inputs
const policy = new aws.s3.BucketPolicy("policy", {
bucket: bucket.id, // Output used as input
policy: bucket.arn.apply(arn => JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: "*",
Action: "s3:GetObject",
Resource: `${arn}/*`,
}],
})),
});Use data sources to reference existing AWS resources:
// Get default VPC
const defaultVpc = await aws.ec2.getVpc({ default: true });
// Get latest Amazon Linux AMI
const ami = await aws.ec2.getAmi({
mostRecent: true,
owners: ["amazon"],
filters: [{
name: "name",
values: ["amzn2-ami-hvm-*-x86_64-gp2"],
}],
});
// Get current AWS region
const current = await aws.getRegion();
// Get caller identity
const caller = await aws.getCallerIdentity();# Preview changes
pulumi preview
# Deploy changes
pulumi up
# View outputs
pulumi stack output
# Destroy resources
pulumi destroyData source functions are async - use await or .apply():
// ❌ Wrong
const vpcId = aws.ec2.getVpc({ default: true }).id;
// ✅ Correct
const defaultVpc = await aws.ec2.getVpc({ default: true });
const vpcId = defaultVpc.id;Resource names must be unique within your Pulumi program:
// ❌ Wrong - duplicate names
const bucket1 = new aws.s3.BucketV2("bucket");
const bucket2 = new aws.s3.BucketV2("bucket"); // Error!
// ✅ Correct
const bucket1 = new aws.s3.BucketV2("bucket-1");
const bucket2 = new aws.s3.BucketV2("bucket-2");Pulumi tracks most dependencies automatically, but explicit dependencies may be needed:
const cluster = new aws.ecs.Cluster("cluster");
const service = new aws.ecs.Service("service", {
cluster: cluster.arn,
}, {
dependsOn: [clusterCapacityProvider], // Explicit dependency
});Install with Tessl CLI
npx tessl i tessl/npm-pulumi--aws