{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template Rails_Single_Instance_With_RDS: Create a Ruby on Rails stack using a single EC2 instance for the web server and a MySQL Amazon RDS database instance for the backend data store. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files at instance launch time. **WARNING** This template creates an Amazon EC2 instance and an Amazon RDS DB instance. You will be billed for the AWS resources used if you create a stack from this template.", "Parameters" : { "KeyName" : { "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type" : "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : "[-_ a-zA-Z0-9]*", "ConstraintDescription" : "can contain only alphanumeric characters, spaces, dashes and underscores." }, "DBName": { "Default": "MyDatabase", "Description" : "MySQL database name", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." }, "DBUsername": { "NoEcho": "true", "Description" : "Username for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters." }, "DBPassword": { "NoEcho": "true", "Description" : "Password for MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "must contain only alphanumeric characters." }, "DBAllocatedStorage": { "Default": "5", "Description" : "The size of the database (Gb)", "Type": "Number", "MinValue": "5", "MaxValue": "1024", "ConstraintDescription" : "must be between 5 and 1024Gb." }, "DBInstanceClass": { "Default": "db.m1.small", "Description" : "The database instance type", "Type": "String", "AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ], "ConstraintDescription" : "must select a valid database instance type." }, "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "m1.small", "AllowedValues" : [ "t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium", "c1.xlarge", "cc1.4xlarge" ], "ConstraintDescription" : "must be a valid EC2 instance type." } }, "Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "32" }, "m1.small" : { "Arch" : "32" }, "m1.large" : { "Arch" : "64" }, "m1.xlarge" : { "Arch" : "64" }, "m2.xlarge" : { "Arch" : "64" }, "m2.2xlarge" : { "Arch" : "64" }, "m2.4xlarge" : { "Arch" : "64" }, "c1.medium" : { "Arch" : "32" }, "c1.xlarge" : { "Arch" : "64" }, "cc1.4xlarge" : { "Arch" : "64" } }, "AWSRegionArch2AMI" : { "us-east-1" : { "32" : "ami-7f418316", "64" : "ami-7341831a" }, "us-west-1" : { "32" : "ami-951945d0", "64" : "ami-971945d2" }, "us-west-2" : { "32" : "ami-16fd7026", "64" : "ami-10fd7020" }, "eu-west-1" : { "32" : "ami-24506250", "64" : "ami-20506254" }, "ap-southeast-1" : { "32" : "ami-74dda626", "64" : "ami-7edda62c" }, "ap-northeast-1" : { "32" : "ami-dcfa4edd", "64" : "ami-e8fa4ee9" } } }, "Resources" : { "CfnUser" : { "Type" : "AWS::IAM::User", "Properties" : { "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Statement":[{ "Effect":"Allow", "Action":"cloudformation:DescribeStackResource", "Resource":"*" }]} }] } }, "HostKeys" : { "Type" : "AWS::IAM::AccessKey", "Properties" : { "UserName" : {"Ref": "CfnUser"} } }, "WebServer": { "Type": "AWS::EC2::Instance", "Metadata" : { "Comment1" : "Configure the bootstrap helpers to install the Rails", "Comment2" : "The application is downloaded from the CloudFormationRailsSample.zip file", "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "gcc-c++" : [], "make" : [], "ruby-devel" : [], "rubygems" : [], "mysql" : [], "mysql-devel" : [], "mysql-libs" : [] }, "rubygems" : { "execjs" : [], "therubyracer" : [], "rails" : [] } }, "sources" : { "/home/ec2-user/sample" : "https://s3.amazonaws.com/cloudformation-examples/CloudFormationRailsSample.zip" }, "files" : { "/home/ec2-user/sample/config/database.yml" : { "content" : { "Fn::Join" : ["", [ "development:\n", " adapter: mysql2\n", " encoding: utf8\n", " reconnect: false\n", " pool: 5\n", " database: ", { "Ref" : "DBName" }, "\n", " username: ", { "Ref" : "DBUsername" }, "\n", " password: ", { "Ref" : "DBPassword" }, "\n", " host: ", { "Fn::GetAtt": [ "MySQLDatabase", "Endpoint.Address" ] }, "\n", " port: ", { "Fn::GetAtt": [ "MySQLDatabase", "Endpoint.Port" ] }, "\n" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" } } } } }, "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 -v\n", "yum update -y aws-cfn-bootstrap\n", "# Helper function\n", "function error_exit\n", "{\n", " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandle" }, "'\n", " exit 1\n", "}\n", "# Install Rails packages\n", "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackName" }, " -r WebServer ", " --access-key ", { "Ref" : "HostKeys" }, " --secret-key ", {"Fn::GetAtt": ["HostKeys", "SecretAccessKey"]}, " --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n", "# Install anu other Gems, create the database and run a migration\n", "cd /home/ec2-user/sample\n", "bundle install || error_exit 'Failed to install bundle'\n", "rake db:migrate || error_exit 'Failed to execute database migration'\n", "# Startup the rails server\n", "rails server -d\n", "echo \"cd /home/ec2-user/sample\" >> /etc/rc.local\n", "echo \"rails server -d\" >> /etc/rc.local\n", "# All is well so signal success\n", "/opt/aws/bin/cfn-signal -e 0 -r \"Rails application setup complete\" '", { "Ref" : "WaitHandle" }, "'\n" ]]}} } }, "WaitHandle" : { "Type" : "AWS::CloudFormation::WaitConditionHandle" }, "WaitCondition" : { "Type" : "AWS::CloudFormation::WaitCondition", "DependsOn" : "WebServer", "Properties" : { "Handle" : {"Ref" : "WaitHandle"}, "Timeout" : "900" } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 3000 plus SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "3000", "ToPort" : "3000", "CidrIp" : "0.0.0.0/0"}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : "0.0.0.0/0"} ] } }, "DBSecurityGroup": { "Type": "AWS::RDS::DBSecurityGroup", "Properties": { "GroupDescription": "Grant database access to web server", "DBSecurityGroupIngress": { "EC2SecurityGroupName": { "Ref": "WebServerSecurityGroup" } } } }, "MySQLDatabase": { "Type": "AWS::RDS::DBInstance", "Properties": { "Engine" : "MySQL", "DBName" : { "Ref": "DBName" }, "MultiAZ" : "false", "MasterUsername": { "Ref": "DBUsername" }, "MasterUserPassword": { "Ref" : "DBPassword" }, "DBInstanceClass": { "Ref" : "DBInstanceClass" }, "DBSecurityGroups": [ { "Ref": "DBSecurityGroup" } ], "AllocatedStorage": { "Ref" : "DBAllocatedStorage" } } } }, "Outputs" : { "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicDnsName" ]}, ":3000" ]] }, "Description" : "URL for newly created Rails application" } } }