{ "AWSTemplateFormatVersion" : "2010-09-09", "Description" : "AWS CloudFormation Sample Template Drupal_Multi_AZ. Drupal is an open source content management platform powering millions of websites and applications. This template installs a highly-available, scalable Drupal deployment using a multi-az Amazon RDS database instance for storage. It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time. **WARNING** This template creates one or more Amazon EC2 instances, an Elastic Load Balancer and an Amazon RDS database. 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": "255", "AllowedPattern" : "[\\x20-\\x7E]*", "ConstraintDescription" : "can contain only ASCII characters." }, "InstanceType" : { "Description" : "WebServer EC2 instance type", "Type" : "String", "Default" : "m1.small", "ConstraintDescription" : "must be a valid EC2 instance type." }, "SiteName": { "Default": "My Site", "Description" : "The name of the Drupal Site", "Type": "String" }, "SiteEMail": { "Description" : "EMail for site adminitrator", "Type": "String" }, "SiteAdmin": { "Description" : "The Drupal site admin account username", "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." }, "SitePassword": { "NoEcho": "true", "Description" : "The Drupal site admin account password", "Type": "String", "MinLength": "1", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "must contain only alphanumeric characters." }, "DBName": { "Default": "drupaldb", "Description" : "The Drupal 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": { "Default": "admin", "NoEcho": "true", "Description" : "The Drupal database admin account username", "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": { "Default": "password", "NoEcho": "true", "Description" : "The Drupal database admin account password", "Type": "String", "MinLength": "8", "MaxLength": "41", "AllowedPattern" : "[a-zA-Z0-9]*", "ConstraintDescription" : "must contain only alphanumeric characters." }, "DBClass" : { "Default" : "db.m1.small", "Description" : "Database instance class", "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." }, "DBAllocatedStorage" : { "Default": "5", "Description" : "The size of the database (Gb)", "Type": "Number", "MinValue": "5", "MaxValue": "1024", "ConstraintDescription" : "must be between 5 and 1024Gb." }, "MultiAZDatabase": { "Default": "true", "Description" : "Create a multi-AZ MySQL Amazon RDS database instance", "Type": "String", "AllowedValues" : [ "true", "false" ], "ConstraintDescription" : "must be either true or false." }, "WebServerCapacity": { "Default": "2", "Description" : "The initial number of WebServer instances", "Type": "Number", "MinValue": "1", "MaxValue": "5", "ConstraintDescription" : "must be between 1 and 5 EC2 instances." }, "SSHLocation" : { "Description" : "The IP address range that can be used to SSH to the EC2 instances", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." } }, "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" }, "m3.xlarge" : { "Arch" : "64" }, "m3.2xlarge" : { "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-a0cd60c9", "64" : "ami-aecd60c7", "64HVM" : "ami-a8cd60c1" }, "us-west-2" : { "32" : "ami-46da5576", "64" : "ami-48da5578", "64HVM" : "NOT_YET_SUPPORTED" }, "us-west-1" : { "32" : "ami-7d4c6938", "64" : "ami-734c6936", "64HVM" : "NOT_YET_SUPPORTED" }, "eu-west-1" : { "32" : "ami-61555115", "64" : "ami-6d555119", "64HVM" : "ami-67555113" }, "ap-southeast-1" : { "32" : "ami-220b4a70", "64" : "ami-3c0b4a6e", "64HVM" : "NOT_YET_SUPPORTED" }, "ap-southeast-2" : { "32" : "ami-8f990eb5", "64" : "ami-95990eaf", "64HVM" : "NOT_YET_SUPPORTED" }, "ap-northeast-1" : { "32" : "ami-2a19aa2b", "64" : "ami-2819aa29", "64HVM" : "NOT_YET_SUPPORTED" }, "sa-east-1" : { "32" : "ami-f836e8e5", "64" : "ami-fe36e8e3", "64HVM" : "NOT_YET_SUPPORTED" } } }, "Resources" : { "S3Bucket" : { "Type" : "AWS::S3::Bucket", "DeletionPolicy" : "Retain" }, "BucketPolicy" : { "Type" : "AWS::S3::BucketPolicy", "Properties" : { "PolicyDocument": { "Version" : "2008-10-17", "Id" : "UploadPolicy", "Statement" : [{ "Sid" : "EnableReadWrite", "Action" : ["s3:GetObject", "s3:PutObject", "s3:PutObjectACL" ], "Effect" : "Allow", "Resource" : { "Fn::Join" : ["", ["arn:aws:s3:::", {"Ref" : "S3Bucket"} , "/*"]]}, "Principal" : { "AWS": {"Fn::GetAtt" : ["S3User", "Arn"]} } }] }, "Bucket" : {"Ref" : "S3Bucket"} } }, "S3User" : { "Type" : "AWS::IAM::User", "Properties" : { "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Statement":[{ "Effect":"Allow", "Action":"s3:*", "Resource":"*" }]} }] } }, "S3Keys" : { "Type" : "AWS::IAM::AccessKey", "Properties" : { "UserName" : {"Ref": "S3User"} } }, "ElasticLoadBalancer" : { "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", "Metadata" : { "Comment" : "Configure the Load Balancer with a simple health check and cookie-based stickiness" }, "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LBCookieStickinessPolicy" : [ { "PolicyName" : "CookieBasedPolicy", "CookieExpirationPeriod" : "30" } ], "Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "80", "Protocol" : "HTTP", "PolicyNames" : [ "CookieBasedPolicy" ] } ], "HealthCheck" : { "Target" : "HTTP:80/", "HealthyThreshold" : "2", "UnhealthyThreshold" : "5", "Interval" : "10", "Timeout" : "5" } } }, "WebServerGroup" : { "Type" : "AWS::AutoScaling::AutoScalingGroup", "Properties" : { "AvailabilityZones" : { "Fn::GetAZs" : "" }, "LaunchConfigurationName" : { "Ref" : "LaunchConfig" }, "MinSize" : "1", "MaxSize" : "5", "DesiredCapacity" : { "Ref" : "WebServerCapacity" }, "LoadBalancerNames" : [ { "Ref" : "ElasticLoadBalancer" } ] } }, "LaunchConfig": { "Type" : "AWS::AutoScaling::LaunchConfiguration", "Metadata" : { "AWS::CloudFormation::Init" : { "config" : { "packages" : { "yum" : { "httpd" : [], "php" : [], "php-mysql" : [], "php-gd" : [], "php-xml" : [], "php-mbstring" : [], "mysql" : [], "gcc" : [], "make" : [], "libstdc++-devel" : [], "gcc-c++" : [], "fuse" : [], "fuse-devel" : [], "libcurl-devel" : [], "libxml2-devel" : [], "openssl-devel" : [], "mailcap" : [] } }, "sources" : { "/var/www/html" : "http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz", "/home/ec2-user" : "http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz", "/home/ec2-user/s3fs" : "http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz" }, "files" : { "/etc/passwd-s3fs" : { "content" : { "Fn::Join" : ["", [ { "Ref" : "S3Keys" }, ":", {"Fn::GetAtt": ["S3Keys", "SecretAccessKey"]}, "\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" }, "/home/ec2-user/settings.php" : { "content" : { "Fn::Join" : ["", [ "\n", " array (\n", " 'default' =>\n", " array (\n", " 'database' => '", { "Ref" : "DBName" }, "',\n", " 'username' => '", { "Ref" : "DBUsername" }, "',\n", " 'password' => '", { "Ref" : "DBPassword" }, "',\n", " 'host' => '", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Address"]}, "',\n", " 'port' => '", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Port"]}, "',\n", " 'driver' => 'mysql',\n", " 'prefix' => 'drupal_',\n", " ),\n", " ),\n", ");\n", "\n", "$update_free_access = FALSE;\n", "\n", "$drupal_hash_salt = '0c3R8noNALe3shsioQr5hK1dMHdwRfikLoSfqn0_xpA';\n", "\n", "ini_set('session.gc_probability', 1);\n", "ini_set('session.gc_divisor', 100);\n", "ini_set('session.gc_maxlifetime', 200000);\n", "ini_set('session.cookie_lifetime', 2000000);\n" ]]}, "mode" : "000400", "owner" : "root", "group" : "root" } }, "services" : { "sysvinit" : { "httpd" : { "enabled" : "true", "ensureRunning" : "true" }, "sendmail" : { "enabled" : "false", "ensureRunning" : "false" } } } } } }, "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 Apache Web Server, MySQL and Drupal\n", "/opt/aws/bin/cfn-init -s ", { "Ref" : "AWS::StackId" }, " -r LaunchConfig ", " --region ", { "Ref" : "AWS::Region" }, " || error_exit 'Failed to run cfn-init'\n", "# Install s3fs\n", "cd /home/ec2-user/s3fs/s3fs-1.61\n", "./configure --prefix=/usr\n", "make\n", "make install\n", "# Move the website files to the top level\n", "mv /var/www/html/drupal-7.8/* /var/www/html\n", "mv /var/www/html/drupal-7.8/.htaccess /var/www/html\n", "rm -Rf /var/www/html/drupal-7.8\n", "# Mount the S3 bucket\n", "mv /var/www/html/sites/default/files /var/www/html/sites/default/files_original\n", "mkdir -p /var/www/html/sites/default/files\n", "s3fs -o allow_other -o use_cache=/tmp ", { "Ref" : "S3Bucket" } ," /var/www/html/sites/default/files || error_exit 'Failed to mount the S3 bucket'\n", "echo `hostname` >> /var/www/html/sites/default/files/hosts\n", "# Make changes to Apache Web Server configuration\n", "sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf\n", "service httpd restart\n", "# Only execute the site install if we are the first host up - otherwise we'll end up losing all the data\n", "read first < /var/www/html/sites/default/files/hosts\n", "if [ `hostname` = $first ]\n", "then\n", " # Create the site in Drupal\n", " cd /var/www/html\n", " ~ec2-user/drush/drush site-install standard --yes", " --site-name='", { "Ref" : "SiteName" }, "' --site-mail=", { "Ref" : "SiteEMail" }, " --account-name=", { "Ref" : "SiteAdmin" }, " --account-pass=", { "Ref" : "SitePassword" }, " --db-url=mysql://", { "Ref" : "DBUsername" }, ":", { "Ref" : "DBPassword" }, "@", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Address"]}, ":", {"Fn::GetAtt" : ["DBInstance", "Endpoint.Port"]}, "/", { "Ref" : "DBName" }, " --db-prefix=drupal_\n", " # use the S3 bucket for shared file storage\n", " cp -R sites/default/files_original/* sites/default/files\n", " cp -R sites/default/files_original/.htaccess sites/default/files\n", "else\n", " # Copy settings.php file since everything else is configured\n", " cp /home/ec2-user/settings.php /var/www/html/sites/default\n", "fi\n", "rm /home/ec2-user/settings.php\n", "# All is well so signal success\n", "/opt/aws/bin/cfn-signal -e 0 -r \"Drupal setup complete\" '", { "Ref" : "WaitHandle" }, "'\n" ]]}} } }, "WaitHandle" : { "Type" : "AWS::CloudFormation::WaitConditionHandle" }, "WaitCondition" : { "Type" : "AWS::CloudFormation::WaitCondition", "DependsOn" : "WebServerGroup", "Properties" : { "Handle" : {"Ref" : "WaitHandle"}, "Timeout" : "600" } }, "DBInstance" : { "Type": "AWS::RDS::DBInstance", "Properties": { "DBName" : { "Ref" : "DBName" }, "Engine" : "MySQL", "MultiAZ" : { "Ref": "MultiAZDatabase" }, "MasterUsername" : { "Ref" : "DBUsername" }, "DBInstanceClass" : { "Ref" : "DBClass" }, "DBSecurityGroups" : [{ "Ref" : "DBSecurityGroup" }], "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" }, "MasterUserPassword": { "Ref" : "DBPassword" } } }, "DBSecurityGroup": { "Type": "AWS::RDS::DBSecurityGroup", "Properties": { "DBSecurityGroupIngress": { "EC2SecurityGroupName": { "Ref": "WebServerSecurityGroup"} }, "GroupDescription" : "Frontend Access" } }, "WebServerSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "Enable HTTP access via port 80, locked down to requests from the load balancer only and SSH access", "SecurityGroupIngress" : [ {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupOwnerId" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"]},"SourceSecurityGroupName" : {"Fn::GetAtt" : ["ElasticLoadBalancer", "SourceSecurityGroup.GroupName"]}}, {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}} ] } } }, "Outputs" : { "WebsiteURL" : { "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]] }, "Description" : "Drupal Website" } } }