Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
485 lines (433 sloc) 18.6 KB
{
"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"
},
"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",
"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": "admin",
"NoEcho": "true",
"Description" : "The Drupal database admin account password",
"Type": "String",
"MinLength": "1",
"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."
}
},
"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" : {
"CfnUser" : {
"Type" : "AWS::IAM::User",
"Properties" : {
"Path": "/",
"Policies": [{
"PolicyName": "root",
"PolicyDocument": { "Statement":[{
"Effect":"Allow",
"Action":"cloudformation:DescribeStackResource",
"Resource":"*"
}]}
}]
}
},
"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/README.txt",
"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" : ["", [
"<?php\n",
"\n",
"$databases = array (\n",
" 'default' =>\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",
"# Update the code on all machines. \n",
"cd ~ec2-user \n",
"~ec2-user/drush/drush self-update --choice=2 --yes \n",
"cd /var/www/html \n",
"~ec2-user/drush/drush pm-updatecode --yes \n",
"# Update the database from the first machine only. \n",
"if [ `hostname` = $first ]\n",
"then\n",
" ~ec2-user/drush/drush updatedb --yes \n",
"fi\n",
"# Add modules. Many more are automatically added to this list. \n",
"# Files are copied to all machines. \n",
"~ec2-user/drush/drush pm-download acl commerce content_access entity rules support --yes \n",
"# Enable modules and rebuild the permissions table. The database holds this. \n",
"if [ `hostname` = $first ]\n",
"then\n",
"~ec2-user/drush/drush pm-enable commerce content_access support --yes \n",
"~ec2-user/drush/drush php-eval 'node_access_rebuild();' \n",
"fi\n",
"# Fix ownership and permissions. \n",
"chown -R root:apache /var/www/html \n",
"chmod 640 /var/www/html/sites/default/settings.php \n",
"# clean up \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" : "0.0.0.0/0"}
]
}
}
},
"Outputs" : {
"WebsiteURL" : {
"Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "ElasticLoadBalancer", "DNSName" ]}]] },
"Description" : "Drupal Website"
}
}
}