{"id":1236,"date":"2018-03-04T17:29:16","date_gmt":"2018-03-04T17:29:16","guid":{"rendered":"http:\/\/wiki.thomasandsofia.com\/?p=1236"},"modified":"2018-03-08T01:26:15","modified_gmt":"2018-03-08T01:26:15","slug":"cloudformation-examples","status":"publish","type":"post","link":"https:\/\/wiki.thomasandsofia.com\/?p=1236","title":{"rendered":"CloudFormation Examples"},"content":{"rendered":"<h1>Main Menu<\/h1>\n<ul>\n<li><a href=\"http:\/\/awsdocs.s3.amazonaws.com\/AWSCloudFormation\/latest\/cfn-ug.pdf\" target=\"_blank\" rel=\"noopener\">The Ultimate Cloud Formation Guide<\/a><\/li>\n<li><a href=\"#Overview\">Overview<\/a><\/li>\n<li><a href=\"#SecurityGroups\">Security Groups<\/a><\/li>\n<li><a href=\"#EC2Instances\">EC2 Instances<\/a>\n<ul>\n<li>EC2 Bare Minimum<\/li>\n<li>Security Group and Key Name Parameter<\/li>\n<li>UserData to install Apache and PHP<\/li>\n<\/ul>\n<\/li>\n<li>AWS::CloudFormation::Init\n<ul>\n<li>config: packages to install Apache<\/li>\n<li>config: files to create a basic web page<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a name=\"Overview\"><\/a><\/p>\n<h2>Overview<\/h2>\n<p>These examples build on each other, but are mostly designed to demonstrate the minimum requirements to make each resource and function work.<\/p>\n<p>Syntax:<\/p>\n<ul>\n<li><span style=\"color: #008080;\">Text<\/span>\n<ul>\n<li>Enter your own text here. If written as a single &#8216;word&#8217;, you must use a word and not a string of words.<\/li>\n<\/ul>\n<\/li>\n<li><span style=\"color: #999999;\"># comment<\/span>\n<ul>\n<li>A comment that let&#8217;s you know what the next line or section is about.\u00a0 These can be safely deleted and will not affect the code.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a name=\"SecurityGroups\"><\/a><\/p>\n<h3>Security Groups<\/h3>\n<p>&nbsp;<\/p>\n<pre>Resources:\r\n   <span style=\"color: #008080;\">MySecurityGroupId<\/span>:\r\n      Type: AWS::EC2::SecurityGroup\r\n      Properties:\r\n         GroupName: <span style=\"color: #008080;\">My Security Group Name<\/span>\r\n         GroupDescription: <span style=\"color: #008080;\">My Security Group Description<\/span>\r\n         <span style=\"color: #999999;\"># Set rules for incoming traffic<\/span>\r\n         SecurityGroupIngress:\r\n         <span style=\"color: #999999;\"># Enable PING from anywhere to any port<\/span>\r\n         -  IpProtocol: icmp\r\n            FromPort: -1\r\n            ToPort: -1\r\n            CidrIp: 0.0.0.0\/0\r\n         <span style=\"color: #999999;\"># Enable SSH<\/span>\r\n         -  IpProtocol: tcp\r\n            FromPort: 22\r\n            ToPort: 22\r\n            CidrIp: 0.0.0.0\/0\r\n         <span style=\"color: #999999;\"># Enable Web traffic<\/span>\r\n         -  IpProtocol: tcp\r\n            FromPort: 80\r\n            ToPort: 80\r\n            CidrIp: 0.0.0.0\/0\r\n         <span style=\"color: #999999;\"># These are optional, but helpful!<\/span>\r\n         Tags:\r\n         -  Key: <span style=\"color: #008080;\">Name<\/span>\r\n            Value: <span style=\"color: #008080;\">My CF Security Group<\/span><\/pre>\n<p><a name=\"EC2Instances\"><\/a><\/p>\n<h2>EC2 Instances<\/h2>\n<h3>EC2 Bare Minimum<\/h3>\n<p>Download: <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/ec2-minimum.yaml_.txt\" target=\"_blank\" rel=\"noopener\">ec2-minimum.yaml<\/a><\/p>\n<pre>Resources:\r\n   <span style=\"color: #008080;\">MyEc2Instance<\/span>:\r\n      Type: AWS::EC2::Instance\r\n      Properties:\r\n         ImageId: <span style=\"color: #008080;\">ami-710e2414<\/span>\r\n         InstanceType: <span style=\"color: #008080;\">t2.micro<\/span>\r\n         <span style=\"color: #999999;\"># Optional, but required if you want to actually access it.<\/span>\r\n         KeyName: <span style=\"color: #008080;\">MyKeyPair<\/span><\/pre>\n<h3>Security Group and Key Name Parameter<\/h3>\n<p>This example will be used as the base script for the rest of the EC2 Section<\/p>\n<p>Download Source:\u00a0 <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/Ec2-SecuityGroup-Parameters.txt\" target=\"_blank\" rel=\"noopener\">Ec2-SecuityGroup-Parameters<\/a><\/p>\n<p>This example includes:<\/p>\n<ul>\n<li>A Security Group (Same as above)<\/li>\n<li>A Parameter to allow you to enter your Key-Pair name.<\/li>\n<\/ul>\n<pre><span style=\"color: #999999;\"># This section allows you to select an existing Key-Pair from the region you are creating the stack in.<\/span>\r\nParameters:\r\n   <span style=\"color: #008080;\">MyKeyPair<\/span>:\r\n      Description: <span style=\"color: #008080;\">Select the Key Pair you wish to use for these instances.<\/span>\r\n      Type: AWS::EC2::KeyPair::KeyName\r\n      <span style=\"color: #999999;\"># Optional, but handy<\/span>\r\n      Default: <span style=\"color: #008080;\">MyDefaultKeyPair<\/span>\r\nResources:\r\n   <span style=\"color: #999999;\"># Define the Security Group<\/span>\r\n   <span style=\"color: #008080;\">MySecurityGroupId<\/span>:\r\n      Type: AWS::EC2::SecurityGroup\r\n      Properties:\r\n         GroupName: <span style=\"color: #008080;\">My Security Group Name<\/span>\r\n         GroupDescription: <span style=\"color: #008080;\">My Security Group Description<\/span>\r\n         SecurityGroupIngress:\r\n         -  IpProtocol: icmp\r\n            FromPort: -1\r\n            ToPort: -1\r\n            CidrIp: 0.0.0.0\/0\r\n         -  IpProtocol: tcp\r\n            FromPort: 22\r\n            ToPort: 22\r\n            CidrIp: 0.0.0.0\/0\r\n         -  IpProtocol: tcp\r\n            FromPort: 80\r\n            ToPort: 80\r\n            CidrIp: 0.0.0.0\/0\r\n         Tags:\r\n         -  Key: <span style=\"color: #008080;\">Name<\/span>\r\n            Value: <span style=\"color: #008080;\">My CF Security Group<\/span>\r\n\r\n   # Define the EC2 Instance\r\n   <span style=\"color: #008080;\">MyEc2Instance<\/span>:\r\n      Type: AWS::EC2::Instance\r\n      Properties:\r\n         ImageId: <span style=\"color: #008080;\">ami-710e2414<\/span>\r\n         InstanceType: <span style=\"color: #008080;\">t2.micro<\/span>\r\n         <span style=\"color: #999999;\"># Optional, but required if you want to actually access it.<\/span>\r\n         KeyName: !Ref <span style=\"color: #008080;\">MyKeyPair<\/span>\r\n         <span style=\"color: #999999;\"># Use the Security Group created above<\/span>\r\n         SecurityGroups:\r\n            -  !Ref <span style=\"color: #008080;\">MySecurityGroupId<\/span>\r\n         Tags:\r\n            -  Key: <span style=\"color: #008080;\">Name<\/span>\r\n               Value: <span style=\"color: #008080;\">My EC2 Instance\r\n<\/span><\/pre>\n<h3>Using UserData to install Apache and PHP<\/h3>\n<p>Download Source: <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/Ec2-SecuityGroup-Parameters-UserData.txt\" target=\"_blank\" rel=\"noopener\">Ec2-SecuityGroup-Parameters-UserData<\/a><\/p>\n<p>Using the script above, add the following lines within the &#8216;Properties&#8217; section.<br \/>\n* Hint: You can safely append this data to the end of the previous file!<\/p>\n<pre>         UserData:\r\n            Fn::Base64: |\r\n               #!\/bin\/bash\r\n               <span style=\"color: #999999;\"># Update Yum<\/span>\r\n               yum update\r\n               <span style=\"color: #999999;\"># Install Apache (-y installs without requiring confirmation)<\/span>\r\n               yum install -y httpd\r\n               <span style=\"color: #999999;\"># Start Apache<\/span>\r\n               service httpd start\r\n               <span style=\"color: #999999;\"># Set Apache to start at reboot<\/span>\r\n               chkconfig httpd on\r\n               <span style=\"color: #999999;\"># Install PHP<\/span>\r\n               yum install -y php<\/pre>\n<h2>AWS::CloudFormation::Init<\/h2>\n<h3>Example 1: Using config and services<\/h3>\n<p>Download Source: <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/CloudFormation-Init-1.txt\">CloudFormation-Init-1<\/a><\/p>\n<p>The previous example can can also be accomplished using special AWS::CloudFormation::Init scripts. To use these, replace the previously added UserData section with the following:<\/p>\n<pre><span style=\"color: #999999;\">         # These lines initialize the use of ::Init.  Init will not function without them.<\/span>\r\n         UserData:\r\n            Fn::Base64: !Sub |\r\n               #!\/bin\/bash -xe\r\n               \/opt\/aws\/bin\/cfn-init -s ${AWS::StackId} -r MyEc2Instance --region ${AWS::Region} || error_exit 'Failed to run cfn-init'\r\n\r\n      <span style=\"color: #999999;\"># Add the Metadata commands to install Apache and PHP<\/span>\r\n      Metadata:\r\n         AWS::CloudFormation::Init:\r\n            config:\r\n               <span style=\"color: #999999;\"># Install Apache and PHP at their current versions<\/span>\r\n               packages:\r\n                  yum:\r\n                     httpd: []\r\n                     php: []\r\n               <span style=\"color: #999999;\"># Start Apache and configure to restart at reboot<\/span>\r\n               services:\r\n                  sysvinit:\r\n                     httpd:\r\n                        enabled: true\r\n                        ensureRunning: true<\/pre>\n<h3>Example 2: Using files<\/h3>\n<p>Download Source: <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/CloudFormation-Init-2.txt\" target=\"_blank\" rel=\"noopener\">CloudFormation-Init-2<\/a><br \/>\nWe can use &#8216;files:&#8217; to create files. In this example, we&#8217;ll create a basic phpinfo page to show the website is both working and that PHP is functioning. The following example can be directly appended to the end of the previous example.<\/p>\n<pre>               files:\r\n                  \"\/var\/www\/html\/index.php\":\r\n                     content: !Sub |\r\n                        &lt;h1&gt;Hello&lt;\/h1&gt;\r\n                        I'm glad you made it!&lt;br\/&gt;\r\n                        You just created a Cloud Formation stack called: ${AWS::StackName}!&lt;br\/&gt;\r\n                        &lt;?php phpinfo(); ?&gt;\r\n                     mode: '000400'\r\n                     owner: apache\r\n                     group: apache<\/pre>\n<p>Browse to the IP address for the instance to view the results.<br \/>\nExample: http:IP.ADD.RE.SS\/index.php<\/p>\n<h3>Example 3: Install WordPress and Configure<\/h3>\n<p>Download Source: <a href=\"http:\/\/wiki.thomasandsofia.com\/wp-content\/uploads\/2018\/03\/CloudFormation-Init-3.txt\">CloudFormation-Init-3<\/a><\/p>\n<p>There are several steps required to get WordPress running, so before we dive in, let&#8217;s outline those steps so it&#8217;s easier to follow along.<\/p>\n<ul>\n<li>Download and Install the WordPress files using &#8216;sources&#8217;<\/li>\n<li>Install the database software and supporting modules using &#8216;packages&#8217;<\/li>\n<li>Start the database and configure it to start on reboot using &#8216;services&#8217;<\/li>\n<li>Update the database with the information required by WordPress\n<ul>\n<li>These will be manually entered in the Parameters<\/li>\n<li>We&#8217;ll use &#8216;files&#8217; and &#8216;commands&#8217; to apply them<\/li>\n<li>Since the config files need to be executed in a specific order (commands after services), we need to create &#8216;confSets&#8217;<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>Download and Install the WordPress files using &#8216;sources&#8217;<\/h4>\n<p>We&#8217;ll continue working from the last script.\u00a0 To download and extract WordPress, append the following code to the bottom of our previous script:<\/p>\n<pre>               sources:\r\n                  \/var\/www\/html: https:\/\/wordpress.org\/latest.tar.gz<\/pre>\n<h4>Install the database software and supporting modules using &#8216;packages&#8217;<\/h4>\n<p>Update the packages section with the following programs:<\/p>\n<ul>\n<li>mariadb<\/li>\n<li>php-mysql<\/li>\n<\/ul>\n<p>Your code should look like this:<\/p>\n<pre>               packages:\r\n                  yum:\r\n                     httpd: []\r\n                     php: []\r\n                     mariadb-server: []\r\n                     php-mysql: []<\/pre>\n<h4>Start the database and configure it to start on reboot using &#8216;services&#8217;<\/h4>\n<p>Add the following lines in the services section<br \/>\nYour &#8216;services&#8217; code should look like this:<\/p>\n<pre>               services:\r\n                  sysvinit:\r\n                     # needs to be in this order\r\n                     # I do not know why\r\n                     mariadb:\r\n                        enabled: true\r\n                        ensureRunning: true\r\n                     httpd: \r\n                        enabled: true \r\n                        ensureRunning: true<\/pre>\n<h4>Update the database with the information required by WordPress<\/h4>\n<h5>Update Parameters to get the user and database information<\/h5>\n<p>Add the following lines to the Parameters section:<\/p>\n<pre>   DBName:\r\n      AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'\r\n      ConstraintDescription: must begin with a letter and contain only alphanumeric characters.\r\n      Default: wordpressdb\r\n      Description: The WordPress database name\r\n      MinLength: 4\r\n      MaxLength: 64\r\n      Type: String\r\n   DBPassword:\r\n      AllowedPattern: '[a-zA-Z0-9]*'\r\n      ConstraintDescription: must contain only alphanumeric characters.\r\n      Description: The WordPress database admin account password\r\n      MaxLength: 41\r\n      MinLength: 8\r\n      NoEcho: true\r\n      Type: String\r\n   DBRootPassword:\r\n      AllowedPattern: '[a-zA-Z0-9]*'\r\n      ConstraintDescription: must contain only alphanumeric characters.\r\n      Description: MySQL root password\r\n      MaxLength: 41\r\n      MinLength: 8\r\n      NoEcho: true\r\n      Type: String\r\n   DBUser:\r\n      AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*'\r\n      ConstraintDescription: must begin with a letter and contain only alphanumeric characters.\r\n      Description: The WordPress database admin account username\r\n      MaxLength: 16\r\n      MinLength: 1\r\n      NoEcho: true\r\n      Type: String<\/pre>\n<h5>Commands<\/h5>\n<p>Run the commands to:<\/p>\n<ul>\n<li>Set the root database password<\/li>\n<li>Create the empty database using the file we&#8217;ll create in the next step.<\/li>\n<\/ul>\n<p>Enter the following code at the bottom of the existing script.<\/p>\n<pre>               commands:\r\n                  01_set_mysql_root_password:\r\n                     command: !Sub |\r\n                        mysqladmin -u root password '${DBRootPassword}'\r\n                  02_create_database:\r\n                     command: !Sub |  \r\n                        mysql -u root --password='${DBRootPassword}' &lt; \/tmp\/setup.mysql<\/pre>\n<h5>Create The File<\/h5>\n<p>Create a file that will setup and create our database.\u00a0 Add this to the files section.<\/p>\n<pre>                  \"\/tmp\/setup.mysql\":\r\n                     content: !Sub |\r\n                        CREATE DATABASE ${DBName};\r\n                        CREATE USER '${DBUser}'@'localhost' IDENTIFIED BY '${DBPassword}';\r\n                        GRANT ALL ON ${DBName}.* TO '${DBUser}'@'localhost'; \r\n                        FLUSH PRIVILEGES;\r\n                     group: root\r\n                     mode: '000400'\r\n                     owner: root<\/pre>\n<h5>Create the configSets<\/h5>\n<div class=\"warning\">IMPORTANT!<br \/>\nThe cfn-init order of execution is pre-defined as:<br \/>\npackages -&gt; groups -&gt; users-&gt; sources -&gt; files -&gt; commands -&gt; servicesThis causes us trouble because we need to have MariaDB running in order to configure it with our commands. To move &#8216;commands&#8217; after the &#8216;services&#8217; section, we need to create a config set.<\/p>\n<\/div>\n<p>This is a multi-part process.<\/p>\n<ul>\n<li>Define the ConfigSet to use<\/li>\n<li>Define the installation order.<\/li>\n<\/ul>\n<p>Edit the cfn-init command to specify the &#8216;configSet&#8217; to use.<\/p>\n<pre>\/opt\/aws\/bin\/cfn-init <span style=\"color: #008080;\">-c RunThisConfiguration<\/span> -s ${AWS::StackId} ...<\/pre>\n<p>Now, create a config set with the execution order (These will make more sense in the next step)<\/p>\n<pre>      Metadata:\r\n         AWS::CloudFormation::Init:\r\n            <span style=\"color: #008080;\">configSets:\r\n               RunThisConfiguration:\r\n                  -  First\r\n                  -  Second\r\n            First:<\/span>\r\n               packages:\r\n                  yum:\r\n                     httpd: []\r\n                     ...\r\n               services:\r\n                  sysvinit:\r\n                     ...\r\n               files:\r\n                  \"\/var\/www\/html\/index.php\":\r\n                     ...\r\n               sources:\r\n                  \/var\/www\/html: https:\/\/wordpress.org\/latest.tar.gz\r\n            <span style=\"color: #008080;\">Second:<\/span>\r\n               commands:\r\n                  ...<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Main Menu The Ultimate Cloud Formation Guide Overview Security Groups EC2 Instances EC2 Bare Minimum Security Group and Key Name Parameter UserData to install Apache and PHP AWS::CloudFormation::Init config: packages to install Apache config: files to create a basic web page Overview These examples build on each other, but are mostly designed to demonstrate the ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"https:\/\/wiki.thomasandsofia.com\/?p=1236\" title=\"read more...\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,26],"tags":[],"class_list":["post-1236","post","type-post","status-publish","format-standard","hentry","category-amazon-web-services-aws","category-cloudformation"],"_links":{"self":[{"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/posts\/1236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1236"}],"version-history":[{"count":36,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/posts\/1236\/revisions"}],"predecessor-version":[{"id":1281,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=\/wp\/v2\/posts\/1236\/revisions\/1281"}],"wp:attachment":[{"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wiki.thomasandsofia.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}