Get started - AWS CloudFormation

Get started

With the right template, you can deploy at once all the AWS resources you need for an application. In this section, you'll examine a template that declares the resources for a WordPress blog, creates a WordPress blog as a stack, monitors the stack creation process, examines the resources on the stack, and then deletes the stack. You use the AWS Management Console to complete these tasks.

Step 1: Pick a template

First, you'll need a template that specifies the resources that you want in your stack. For this step, you use a sample template that's already prepared. The sample template creates a basic WordPress blog that uses a single Amazon EC2 instance with a local MySQL database for storage. The template also creates an Amazon EC2 security group to control firewall settings for the Amazon EC2 instance.


AWS CloudFormation is free, but the AWS resources that CloudFormation creates are live (and not running in a sandbox). You will incur the standard usage fees for these resources until you terminate them in the last task in this tutorial. The total charges will be minimal. For information about how you might minimize any charges, go to

To view the template
  • You can view the JSON or YAML WordPress sample template. You don't need to download it because you will use the template URL later in this guide. For more information about the template formats, see AWS CloudFormation template formats.

A template is a JSON or YAML text file that contains the configuration information about the AWS resources you want to create in the stack. For this walkthrough, the sample template includes six top-level sections: AWSTemplateFormatVersion, Description, Parameters, Mappings, Resources, and Outputs; however, only the Resources section is required.

The Resources section contains the definitions of the AWS resources you want to create with the template. Each resource is listed separately and specifies the properties that are necessary for creating that particular resource. The following resource declaration is the configuration for the EC2 instance, which in this example has the logical name WebServer:

Example JSON
"Resources" : { ... "WebServer": { "Type" : "AWS::EC2::Instance", "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], "KeyName" : { "Ref" : "KeyName" }, "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [ "#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap\n", "/opt/aws/bin/cfn-init -v ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServer ", " --configsets wordpress_install ", " --region ", { "Ref" : "AWS::Region" }, "\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", { "Ref" : "AWS::StackName" }, " --resource WebServer ", " --region ", { "Ref" : "AWS::Region" }, "\n" ]]}} }, ... }, ... "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80 locked down to the load balancer + SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : 80, "ToPort" : 80, "CidrIp" : ""}, {"IpProtocol" : "tcp", "FromPort" : 22, "ToPort" : 22, "CidrIp" : { "Ref" : "SSHLocation"}} ] } }, ... },
Example YAML
Resources: ... WebServer: Type: AWS::EC2::Instance Properties: ImageId: !FindInMap [AWSRegionArch2AMI, !Ref 'AWS::Region', !FindInMap [AWSInstanceType2Arch, !Ref InstanceType, Arch]] InstanceType: Ref: InstanceType KeyName: Ref: KeyName SecurityGroups: - Ref: WebServerSecurityGroup UserData: Fn::Base64: !Sub | #!/bin/bash -xe yum update -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource WebServer --configsets wordpress_install --region ${AWS::Region} /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource WebServer --region ${AWS::Region} ... ... WebServerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: "Enable HTTP access via port 80 locked down to the load balancer + SSH access" SecurityGroupIngress: - CidrIp: FromPort: 80 IpProtocol: tcp ToPort: 80 - CidrIp: !Ref SSHLocation FromPort: 22 IpProtocol: tcp ToPort: 22 ...

If you have created EC2 instances before, you can recognize properties, such as ImageId, InstanceType, and KeyName, that determine the configuration of the instance. Resource declarations are an efficient way to specify all these configuration settings at once. When you put resource declarations in a template, you can create and configure all the declared resources by using the template to create a stack. Create a new stack that uses the same template to launch the same configuration of resources.

The resource declaration begins with a string that specifies the logical name for the resource. As you'll see, the logical name can be used to refer to resources within the template.

You use the Parameters section to declare values that can be passed to the template when you create the stack. A parameter is an effective way to specify sensitive information, such as user names and passwords, that you don't want to store in the template itself. It's also a way to specify information that might be unique to the specific application or configuration you are deploying, for example, a domain name or instance type. When you create the WordPress stack later in this section, you'll see the set of parameters declared in the template appear on the Specify Details page of the Create Stack wizard, where you can specify the parameters before you create the stack.

The following parameters are used in the template to specify values that are used in properties of the EC2 instance:

Example JSON
"Parameters" : { ... "KeyName": { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type": "AWS::EC2::KeyPair::KeyName", "ConstraintDescription" : "must be the name of an existing EC2 KeyPair." }, "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "t2.small", "AllowedValues" : [ "t1.micro", "t2.nano", "t2.micro", "t2.small", "t2.medium", "t2.large", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "g2.8xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"], "ConstraintDescription" : "must be a valid EC2 instance type." }, ...
Example YAML
Parameters: ... KeyName: ConstraintDescription: must be the name of an existing EC2 KeyPair. Description: Name of an existing EC2 KeyPair to enable SSH access to the instances Type: AWS::EC2::KeyPair::KeyName InstanceType: AllowedValues: - t1.micro - t2.nano - t2.micro - t2.small - t2.medium - t2.large - m1.small - m1.medium - m1.large - m1.xlarge - m2.xlarge - m2.2xlarge - m2.4xlarge - m3.medium - m3.large - m3.xlarge - m3.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - c1.medium - c1.xlarge - c3.large - c3.xlarge - c3.2xlarge - c3.4xlarge - c3.8xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - g2.2xlarge - g2.8xlarge - r3.large - r3.xlarge - r3.2xlarge - r3.4xlarge - r3.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - i2.8xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - hi1.4xlarge - hs1.8xlarge - cr1.8xlarge - cc2.8xlarge - cg1.4xlarge ConstraintDescription: must be a valid EC2 instance type. Default: t2.small Description: WebServer EC2 instance type Type: String ...

In the WebServer resource declaration, you see the KeyName property specified with the KeyName parameter:

Example JSON
"WebServer" : { "Type": "AWS::EC2::Instance", "Properties": { "KeyName" : { "Ref" : "KeyName" }, ... } },
Example YAML
WebServer: Type: AWS::EC2::Instance Properties: KeyName: Ref: KeyName ...

The braces contain a call to the Ref function with KeyName as its input. The Ref function returns the value of the object it refers to. In this case, the Ref function sets the KeyName property to the value that was specified for KeyName when the stack was created.

The Ref function can also set a resource's property to the value of another resource. For example, the resource declaration WebServer contains the following property declaration:

Example JSON
"WebServer" : { "Type": "AWS::EC2::Instance", "Properties": { ... "SecurityGroups" : [ {"Ref" : "WebServerSecurityGroup"} ], ... } },
Example YAML
WebServer: Type: AWS::EC2::Instance Properties: SecurityGroups: - Ref: WebServerSecurityGroup ...

The SecurityGroups property takes a list of EC2 security groups. The Ref function has an input of WebServerSecurityGroup, which is the logical name of a security group in the template, and adds the name of WebServerSecurityGroup to the SecurityGroups property.

In the template, you'll also find a Mappings section. You use mappings to declare conditional values that are evaluated in a similar manner as a look up table statement. The template uses mappings to select the correct Amazon Machine Image (AMI) for the region and the architecture type for the instance type. Outputs define custom values that are returned by the aws cloudformation describe-stacks command and in the CloudFormation console Outputs tab after the stack creation. You can use output values to return information from the resources in the stack, such as the URL for a website that was created in the template. We cover mappings, outputs, and other things about templates in more detail in Learn template basics.

That's enough about templates for now. Let's start creating a stack.

Step 2: Make sure you have prepared any required items for the stack

Before you create a stack from a template, you must ensure that all dependent resources that the template requires are available. A template can use or refer to both existing AWS resources and resources declared in the template itself. CloudFormation takes care of checking references to resources in the template and also checks references to existing resources to ensure that they exist in the region where you are creating the stack. If your template refers to a dependent resource that doesn't exist, stack creation fails.

The example WordPress template contains an input parameter, KeyName, that specifies the key pair used for the Amazon EC2 instance that's declared in the template. The template depends on the user who creates a stack from the template to supply a valid Amazon EC2 key pair for the KeyName parameter. If you supply a valid key pair name, the stack creates successfully. If you don't supply a valid key pair name, the stack is rolled back.

Make sure you have a valid Amazon EC2 key pair and record the key pair name before you create the stack.

To see your key pairs, open the Amazon EC2 console, then choose Key Pairs in the navigation pane.


If you don't have an Amazon EC2 key pair, you must create the key pair in the same region where you are creating the stack. For information about creating a key pair, see Getting an SSH key pair in the Amazon EC2 User Guide for Linux Instances.

Now that you have a valid key pair, let's use the WordPress template to create a stack.

Step 3: Create the stack

You will create your stack based on the WordPress-1.0.0 file discussed earlier. The template contains several AWS resources, such as an EC2 instance.

To create the WordPress stack
  1. Sign in to the AWS Management Console and open the AWS CloudFormation console at

  2. If this is a new CloudFormation account, choose Create New Stack. Otherwise, choose Create Stack.

  3. In the Template section, select Specify an Amazon S3 Template URL to type or paste the URL for the sample WordPress template, and then choose Next:


    AWS CloudFormation templates that are stored in an S3 bucket must be accessible to the user who is creating the stack, and must be located in the same region as the stack that is being created. Therefore, if the S3 bucket is located in the us-east-2 Region, the stack must also be created in us-east-2.

  4. In the Specify Details section, enter a stack name in the Name field. For this example, use MyWPTestStack. The stack name can't contain spaces.

  5. On the Specify Parameters page, you'll recognize the parameters from the Parameters section of the template. You must provide values for all parameters that don't have default values, including DBUser, DBPassword, DBRootPassword, and KeyName. In the KeyName field, enter the name of a valid Amazon EC2 pair in the same region you are creating the stack.

  6. Choose Next.

  7. In this scenario, we won't add any tags. Choose Next. Tags, which are key-value pairs, can help you identify your stacks. For more information, see Adding tags to your CloudFormation stack.

  8. Review the information for the stack. When you're satisfied with the settings, choose Create.

Your stack might take several minutes to create – but you probably don't want to just sit around waiting. If you're like us, you'll want to know how the stack creation is going.

Step 4: Monitor the progress of stack creation

After you complete the Create Stack wizard, CloudFormation begins creating the resources that are specified in the template. Your new stack, MyWPTestStack, appears in the list at the top portion of the CloudFormation console. Its status should be CREATE_IN_PROGRESS. You can see detailed status for a stack by viewing its events.

To view the events for the stack
  1. On the CloudFormation console, select the stack MyWPTestStack in the list.

  2. In the stack details pane, choose the Events tab.

    The console automatically refreshes the event list with the most recent events every 60 seconds.

The Events tab displays each major step in the creation of the stack sorted by the time of each event, with latest events on top.

The first event (at the bottom of the event list) is the start of the stack creation process:

2013-04-24 18:54 UTC-7 CREATE_IN_PROGRESS AWS::CloudFormation::Stack MyWPTestStack User initiated

Next are events that mark the beginning and completion of the creation of each resource. For example, creation of the EC2 instance results in the following entries:

2013-04-24 18:59 UTC-7 CREATE_COMPLETE AWS::EC2::Instance...

2013-04-24 18:54 UTC-7 CREATE_IN_PROGRESS AWS::EC2::Instance...

The CREATE_IN_PROGRESS event is logged when CloudFormation reports that it has begun to create the resource. The CREATE_COMPLETE event is logged when the resource is successfully created.

When CloudFormation has successfully created the stack, you will see the following event at the top of the Events tab:

2013-04-24 19:17 UTC-7 CREATE_COMPLETE AWS::CloudFormation::Stack MyWPTestStack

If CloudFormation can't create a resource, it reports a CREATE_FAILED event and, by default, rolls back the stack and deletes any resources that have been created. The Status Reason column displays the issue that caused the failure.

Step 5: Use your stack resources

When the stack MyWPTestStack has a status of CREATE_COMPLETE, CloudFormation has finished creating the stack, and you can start using its resources.

The sample WordPress stack creates a WordPress website. You can continue with the WordPress setup by running the WordPress installation script.

To complete the WordPress installation
  1. On the Outputs tab, in the WebsiteURL row, choose the link in the Value column.

    The WebsiteURL output value is the URL of the installation script for the WordPress website that you created with the stack.

  2. On the web page for the WordPress installation, follow the on-screen instructions to complete the WordPress installation. For more information about installing WordPress, see

    After you complete the installation and log in, you are directed to the dashboard where you can set additional options for your WordPress blog. Then, you can start writing posts for your blog that you successfully created by using a CloudFormation template.

Step 6: Clean up

You have completed the CloudFormation getting started tasks. To make sure you aren't charged for any unwanted services, you can clean up by deleting the stack and its resources.

To delete the stack and its resources
  1. From the CloudFormation console, select the MyWPTestStack stack.

  2. Choose Delete Stack.

  3. In the confirmation message that appears, choose Yes, Delete.

The status for MyWPTestStack changes to DELETE_IN_PROGRESS. In the same way you monitored the creation of the stack, you can monitor its deletion by using the Event tab. When CloudFormation completes the deletion of the stack, it removes the stack from the list.

Congratulations! You successfully picked a template, created a stack, viewed, and used its resources, and deleted the stack and its resources. Not only that, you were able to set up a WordPress blog using a CloudFormation template. You can find other templates in the AWS CloudFormation sample template library.

Now it's time to learn more about templates so that you can modify existing templates or create your own: Learn template basics.