Single Server

Updated at 2016-02-23 10:59

Save the following JSON object to a local single-server.json file.

    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Single server setup",
    "Parameters": {
        "KeyPairName": {
            "Description":  "Key Pair name",
            "Type":         "AWS::EC2::KeyPair::KeyName"
        "VPC": {
            "Description":  "Just select the one and only default VPC",
            "Type":         "AWS::EC2::VPC::Id"
        "Subnet": {
            "Description":  "Just select one of the available subnets",
            "Type":         "AWS::EC2::Subnet::Id"
        "InstanceType": {
            "Description":   "Select one of the possible instance types",
            "Type":          "String",
            "Default":       "t2.micro",
            "AllowedValues": ["t2.micro", "t2.small", "t2.medium"]
    "Mappings": {
        "EC2RegionMap": {
            "ap-northeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-cbf90ecb"},
            "ap-southeast-1": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-68d8e93a"},
            "ap-southeast-2": {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-fd9cecc7"},
            "eu-central-1":   {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a8221fb5"},
            "eu-west-1":      {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-a10897d6"},
            "sa-east-1":      {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-b52890a8"},
            "us-east-1":      {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-1ecae776"},
            "us-west-1":      {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-d114f295"},
            "us-west-2":      {"AmazonLinuxAMIHVMEBSBacked64bit": "ami-e7527ed7"}
    "Resources": {
        "SecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Security group",
                "VpcId": {"Ref": "VPC"},
                "SecurityGroupIngress": [{
                    "CidrIp":       "",
                    "FromPort":     22,
                    "IpProtocol":   "tcp",
                    "ToPort":       22
        "Server": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": {"Fn::FindInMap": [
                    {"Ref": "AWS::Region"},
                "InstanceType":     {"Ref": "InstanceType"},
                "KeyName":          {"Ref": "KeyPairName"},
                "SecurityGroupIds": [{"Ref": "SecurityGroup"}],
                "SubnetId":         {"Ref": "Subnet"}
    "Outputs": {
        "PublicName": {
            "Value": {"Fn::GetAtt": ["Server", "PublicDnsName"]},
            "Description": "Public name (connect via SSH as user ec2-user)"
  1. Go to
  2. Press "Create Stack"
  3. Select "Upload a template to Amazon S3" and upload "single-server.json"
  • This will create a bucket similar to cf-templates-22uxeltuma77-region where it uploads the template.
  1. Name the stack "DeleteMe", fill other values whatever you have.

EC2 instance will have:

Name                                (none)
aws:cloudformation:logical-id       Server
aws:cloudformation:stack-id         arn:<ARN>:stack/DeleteMe/<ID>
aws:cloudformation:stack-name       DeleteMe

Security Group will have:

Name                                DeleteMe-SecurityGroup-1QK7UKVT2CHFI
aws:cloudformation:logical-id       SecurityGroup
aws:cloudformation:stack-id         arn:<ARN>:stack/DeleteMe/<ID>
aws:cloudformation:stack-name       DeleteMe

Stack details will show public name as output that you can use to SSH in:

# PublicName =
ssh -i ~/.ssh/aws-skeleton-key.pem ec2-user@<PUBLIC_NAME>

Updating a Stack

You can easily change the instance type because you defined it with a template.

  1. Select the stack.
  2. Select "Actions > Update Stack"
  3. Select "Use current template"
  4. Change "Instance Type", and any of the other values.
  5. Instance will be stopped, instance type is swapped and it will boot up again.

Deleting a Stack

  1. Select the stack.
  2. Select "Actions > Delete Stack > Yes"
  3. This will tear down all related resources.

Command Line Templating

You can also do this totally from command line, which is easier to automate.

aws s3 mb s3://cf-temps
aws s3 cp ./single-server.json s3://cf-temps
aws s3 ls s3://cf-temps

Now you have template defined you can use.

aws cloudformation create-stack \
    --stack-name DeleteMe \
    --template-url \
    # But template needs values: [VPC, KeyPairName, Subnet] which
    # are annoying to lookup/script, easier to just use the web interface.
    --parameters ParameterKey=KeyPairName,ParameterValue=MyKey \