{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Sample Template: Launches OpsWorks stack, layer, instances and associated resources to run a PHP application. The application runs inside an Amazon VPC and uses ELB to load balance ** This template creates one or more Amazon EC2 instances. You will be billed for the AWS resources used if you create a stack from this template.",
"Mappings": {
"AWSNATAMI": {
"us-east-1": {
"AMI": "ami-c6699baf"
},
"us-west-2": {
"AMI": "ami-52ff7262"
},
"us-west-1": {
"AMI": "ami-3bcc9e7e"
},
"eu-west-1": {
"AMI": "ami-0b5b6c7f"
},
"ap-southeast-1": {
"AMI": "ami-02eb9350"
},
"ap-northeast-1": {
"AMI": "ami-14d86d15"
},
"sa-east-1": {
"AMI": "ami-0439e619"
}
},
"SubnetConfig": {
"VPC": {
"CIDR": "10.0.0.0/16"
},
"Public": {
"CIDR": "10.0.0.0/24"
},
"Private": {
"CIDR": "10.0.1.0/24"
}
}
},
"Resources": {
"OpsWorksStack": {
"Type": "AWS::OpsWorks::Stack",
"Properties": {
"Name": {
"Ref": "AWS::StackName"
},
"ServiceRoleArn": {
"Fn::GetAtt": [
"OpsWorksServiceRole",
"Arn"
]
},
"DefaultInstanceProfileArn": {
"Fn::GetAtt": [
"OpsWorksInstanceProfile",
"Arn"
]
},
"VpcId": {
"Ref": "VPC"
},
"DefaultSubnetId": {
"Ref": "PrivateSubnet"
}
}
},
"OpsWorksLayer": {
"Type": "AWS::OpsWorks::Layer",
"Metadata" : {
"Comment" : "OpsWorks instances require outbound Internet access. Using DependsOn to make sure outbound Internet Access is estlablished before creating instances in this layer."
},
"DependsOn": [ "NATIPAddress", "PublicRoute", "PublicSubnetRouteTableAssociation", "PrivateRoute", "PrivateSubnetRouteTableAssociation", "OpsWorksApp"],
"Properties": {
"StackId": {
"Ref": "OpsWorksStack"
},
"Name": "MyPHPApp",
"Type": "php-app",
"Shortname": "php-app",
"EnableAutoHealing": "true",
"AutoAssignElasticIps": "false",
"AutoAssignPublicIps": "true",
"CustomSecurityGroupIds": [
{
"Ref": "OpsWorksSecurityGroup"
}
]
}
},
"OpsWorksInstance1": {
"Type": "AWS::OpsWorks::Instance",
"Properties": {
"StackId": {
"Ref": "OpsWorksStack"
},
"LayerIds": [
{
"Ref": "OpsWorksLayer"
}
],
"InstanceType": "m1.small"
}
},
"OpsWorksInstance2": {
"Type": "AWS::OpsWorks::Instance",
"Properties": {
"StackId": {
"Ref": "OpsWorksStack"
},
"LayerIds": [
{
"Ref": "OpsWorksLayer"
}
],
"InstanceType": "m1.small"
}
},
"OpsWorksApp": {
"Type": "AWS::OpsWorks::App",
"Properties": {
"StackId": {
"Ref": "OpsWorksStack"
},
"Name": "MyPHPApp",
"Type": "php",
"AppSource": {
"Type": "git",
"Url": "git://github.com/amazonwebservices/opsworks-demo-php-simple-app.git",
"Revision": "version1"
},
"Attributes": {
"DocumentRoot": " "
}
}
},
"OpsWorksServiceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"opsworks.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "opsworks-service",
"PolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:*",
"iam:PassRole",
"cloudwatch:GetMetricStatistics",
"elasticloadbalancing:*"
],
"Resource": "*"
}
]
}
}
]
}
},
"OpsWorksInstanceRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/"
}
},
"OpsWorksInstanceProfile": {
"Type": "AWS::IAM::InstanceProfile",
"Properties": {
"Path": "/",
"Roles": [
{
"Ref": "OpsWorksInstanceRole"
}
]
}
},
"OpsWorksSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription" : "Allow inbound requests from the ELB to the OpsWorks instances",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"SourceSecurityGroupId": {
"Ref": "ELBSecurityGroup"
}
}
]
}
},
"ELB": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"SecurityGroups": [
{
"Ref": "ELBSecurityGroup"
}
],
"Subnets": [
{
"Ref": "PublicSubnet"
}
],
"Listeners": [
{
"LoadBalancerPort": "80",
"InstancePort": "80",
"Protocol": "HTTP"
}
],
"HealthCheck": {
"Target": "HTTP:80/",
"HealthyThreshold": "3",
"UnhealthyThreshold": "5",
"Interval": "90",
"Timeout": "60"
}
}
},
"ELBAttachment": {
"Type": "AWS::OpsWorks::ElasticLoadBalancerAttachment",
"Properties": {
"ElasticLoadBalancerName": {
"Ref": "ELB"
},
"LayerId": {
"Ref": "OpsWorksLayer"
}
}
},
"ELBSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription" : "Allow inbound access to the ELB",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"VPC": {
"Type": "AWS::EC2::VPC",
"DependsOn": "OpsWorksServiceRole",
"Properties": {
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"VPC",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PublicSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Public",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"VPCGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"InternetGatewayId": {
"Ref": "InternetGateway"
}
}
},
"PublicRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"PublicRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": "VPCGatewayAttachment",
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InternetGateway"
}
}
},
"PublicSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"PublicNetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Public"
}
]
}
},
"InboundHTTPPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "80",
"To": "80"
}
}
},
"InboundHTTPSPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "101",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "443",
"To": "443"
}
}
},
"InboundSSHPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "102",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "22",
"To": "22"
}
}
},
"InboundEmphemeralPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "103",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "1024",
"To": "65535"
}
}
},
"OutboundPublicNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "0",
"To": "65535"
}
}
},
"PublicSubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PublicSubnet"
},
"NetworkAclId": {
"Ref": "PublicNetworkAcl"
}
}
},
"PrivateSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"CidrBlock": {
"Fn::FindInMap": [
"SubnetConfig",
"Private",
"CIDR"
]
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Name",
"Value": "Private"
}
]
}
},
"PrivateRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"PrivateSubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet"
},
"RouteTableId": {
"Ref": "PrivateRouteTable"
}
}
},
"PrivateRoute": {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"InstanceId": {
"Ref": "NATDevice"
}
}
},
"PrivateNetworkAcl": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackName"
}
},
{
"Key": "Network",
"Value": "Private"
}
]
}
},
"InboundPrivateNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "false",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "0",
"To": "65535"
}
}
},
"OutBoundPrivateNetworkAclEntry": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
},
"RuleNumber": "100",
"Protocol": "6",
"RuleAction": "allow",
"Egress": "true",
"CidrBlock": "0.0.0.0/0",
"PortRange": {
"From": "0",
"To": "65535"
}
}
},
"PrivateSubnetNetworkAclAssociation": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivateSubnet"
},
"NetworkAclId": {
"Ref": "PrivateNetworkAcl"
}
}
},
"NATIPAddress": {
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc",
"InstanceId": {
"Ref": "NATDevice"
}
}
},
"NATDevice": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "m1.small",
"SubnetId": {
"Ref": "PublicSubnet"
},
"SourceDestCheck": "false",
"ImageId": {
"Fn::FindInMap": [
"AWSNATAMI",
{
"Ref": "AWS::Region"
},
"AMI"
]
},
"SecurityGroupIds": [
{
"Ref": "NATSecurityGroup"
}
]
}
},
"NATSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription" : "Allow OpsWorks instances to access the NAT Device",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"SourceSecurityGroupId": {
"Ref": "OpsWorksSecurityGroup"
}
},
{
"IpProtocol": "tcp",
"FromPort": "9418",
"ToPort": "9418",
"SourceSecurityGroupId": {
"Ref": "OpsWorksSecurityGroup"
}
},
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"SourceSecurityGroupId": {
"Ref": "OpsWorksSecurityGroup"
}
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "9418",
"ToPort": "9418",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
}
]
}
}
},
"Outputs": {
"StackId": {
"Value": {
"Ref": "OpsWorksStack"
}
},
"AppId": {
"Value": {
"Ref": "OpsWorksApp"
}
},
"VPC": {
"Description": "VPC",
"Value": {
"Ref": "VPC"
}
},
"PublicSubnet": {
"Value": {
"Ref": "PublicSubnet"
}
},
"PrivateSubnet": {
"Value": {
"Ref": "PrivateSubnet"
}
},
"ELB": {
"Value": {
"Ref": "ELB"
}
}
}
}