{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template Rails_Single_Instance: Create a Ruby on Rails stack using a single EC2 instance with a local MySQL database for storage. This template demonstrates using the AWS CloudFormation bootstrap scripts to install the packages and files necessary to deploy the packages and files at instance launch time. **WARNING** This template creates an Amazon EC2 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 MySQL database access", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "must contain only alphanumeric characters." }, "DBRootPassword": { "NoEcho": "true", "Description" : "Root password for MySQL", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "must contain only alphanumeric characters." }, "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "m1.small", "AllowedValues" : [ "t1.micro","m1.small","m1.medium","m1.large","m1.xlarge","m2.xlarge","m2.2xlarge","m2.4xlarge","c1.medium","c1.xlarge","cc1.4xlarge","cc2.8xlarge","cg1.4xlarge"], "ConstraintDescription" : "must be a valid EC2 instance type." } }, "Mappings" : { "AWSInstanceType2Arch" : { "t1.micro" : { "Arch" : "64" }, "m1.small" : { "Arch" : "64" }, "m1.medium" : { "Arch" : "64" }, "m1.large" : { "Arch" : "64" }, "m1.xlarge" : { "Arch" : "64" }, "m2.xlarge" : { "Arch" : "64" }, "m2.2xlarge" : { "Arch" : "64" }, "m2.4xlarge" : { "Arch" : "64" }, "c1.medium" : { "Arch" : "64" }, "c1.xlarge" : { "Arch" : "64" }, "cc1.4xlarge" : { "Arch" : "64HVM" }, "cc2.8xlarge" : { "Arch" : "64HVM" }, "cg1.4xlarge" : { "Arch" : "64HVM" } }, "AWSRegionArch2AMI" : { "us-east-1" : { "32" : "ami-31814f58", "64" : "ami-1b814f72", "64HVM" : "ami-0da96764" }, "us-west-2" : { "32" : "ami-38fe7308", "64" : "ami-30fe7300", "64HVM" : "NOT_YET_SUPPORTED" }, "us-west-1" : { "32" : "ami-11d68a54", "64" : "ami-1bd68a5e", "64HVM" : "NOT_YET_SUPPORTED" }, "eu-west-1" : { "32" : "ami-973b06e3", "64" : "ami-953b06e1", "64HVM" : "NOT_YET_SUPPORTED" }, "ap-southeast-1" : { "32" : "ami-b4b0cae6", "64" : "F16-x86_64-cfntools", "64HVM" : "NOT_YET_SUPPORTED" }, "ap-northeast-1" : { "32" : "ami-0644f007", "64" : "ami-0a44f00b", "64HVM" : "NOT_YET_SUPPORTED" }, "sa-east-1" : { "32" : "ami-3e3be423", "64" : "ami-3c3be421", "64HVM" : "NOT_YET_SUPPORTED" } } }, "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" : { "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "gcc-c++" : [], "make" : [], "ruby-devel" : [], "rubygems" : [], "mysql" : [], "mysql-server" : [], "mysql-devel" : [], "mysql-libs" : [] }, "rubygems" : { "rack" : ["1.3.6"], "execjs" : [], "therubyracer" : [], "rails" : [] } }, "sources" : { "/home/ec2-user/sample" : "https://s3.amazonaws.com/cloudformation-examples/CloudFormationRailsSample.zip" }, "files" : { "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n", "GRANT ALL PRIVILEGES ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@'localhost'\n", "IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n", "FLUSH PRIVILEGES;\n", "EXIT\n" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" }, "/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", " socket: /var/lib/mysql/mysql.sock\n" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" } }, "services" : { "sysvinit" : { "mysqld" : { "enabled" : "true", "ensureRunning" : "true" } } } } } }, "Properties": { "ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, { "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }, "InstanceType" : { "Ref" : "InstanceType" }, "SecurityGroups" : [ {"Ref" : "FrontendGroup"} ], "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", "# Setup MySQL root password and create a user\n", "mysqladmin -u root password '", { "Ref" : "DBRootPassword" }, "' || error_exit 'Failed to initialize root password'\n", "mysql -u root --password='", { "Ref" : "DBRootPassword" }, "' < /tmp/setup.mysql || error_exit 'Failed to create database user'\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:create || error_exit 'Failed to create database'\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" : "1500" } }, "FrontendGroup" : { "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"} ] } } }, "Outputs" : { "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicIp" ]}, ":3000" ]] }, "Description" : "URL for newly created Rails application" } } }