Setting up an Apache server using AWS CloudFormation

This a is a brief and simple guide to spinning up an instance, installing Apache, and writing output to a webpage.

Note that by following this guide you can incur charges. Im not responsible for them and will not be picking up your bill.

Setup

1. Have an AWS account. You can signup for one here: http://aws.amazon.com/
2. Have a computer you can work from. This guide assumes you are running Linux. What other OS is there anyways? For me I have an instance on AWS that I startup whenever I want to work on stuff. On this computer you need to install the AWS CLI tool. You can install and setup the CLI tool by going here: http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-set-up.html
3. Basic understanding of JSON…not a requirement but it helps to understand what you are reading in the template.

The Template

First here is a link that will guide you further than im going to here on the ins and outs of templates and requirements for CloudFormation: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html

So lets break down the template…

{
 "AWSTemplateFormatVersion" : "2010-09-09",

This is an optional but lets AWS know what version of the template you are using. This is NOT today’s date or something.

"Description" : "Create an Apache webserver with a webpage.",

Gives a description of what your template is for.

"Parameters" : {
    "InstanceType" : {
      "Description" : "Type of EC2 instance to launch",
      "Type" : "String",
      "Default" : "t1.micro"
    },
    "WebServerPort" : {
      "Description" : "TCP/IP port of the web server",
      "Type" : "String",
      "Default" : "80"
    },
    "KeyName" : {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
      "Type" : "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
    },
    "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."
        }
  },

Breaking down the parameters directive…
*If you dont give your parameter a “Default” you will need to pass in the option via the command line. This will be explained further but keep that in mind in this section.
InstanceType – Tells what kind you want to launch. The default here is t1.micro.
WebServerPort – You are telling what port your webserver will accept connections on.
KeyName – This is the name of your AWS key that you use to authenticate with. Use a key that has permissions to setup new instances and connect to them.
SSHLocation – The IP address range that can be used to SSH to the EC2 instances

"Mappings" : {
    "AWSInstanceType2Arch" : {
      "t1.micro"    : { "Arch" : "64" }
    },
    "AWSRegionArch2AMI" : {
      "us-east-1"          : { "64" : "ami-246ed34c" }
    }
  },

Mappings…tells what region and what AMI you want to use. For brevity I already knew what I wanted to use and that I wanted it to fail if not available so my listing of types and regions is VERY short. You can see further info here on mappings: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html

Now we will talk about the Resources section. Its where all the real magic happens. Ill break it down some and then provide the full section at the bottom of this page.

"Resources" : {     
      
    "WebServerInstance": {  
      "Type": "AWS::EC2::Instance",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "InstallAndRun" : [ "Install" ]
          },

          "Install" : {
            "packages" : {
              "yum" : {
                "httpd"        : []              
              }
            },

Here, we are saying that we want to initialize and install something on our instance. Notice that we are using “yum”. The AMI I use is an Amazon AMI which is RHEL based. It comes with some tools already setup and installed specific to AWS so its easier to use this AMI base. Here all we are installing is Apache, or “httpd”.

"files" : {
              "/var/www/html/index.html" : {
              "source" : "https://s3.amazonaws.com/BUCKET_NAME/index.html",  
              "mode"  : "000600",
              "owner" : "apache",
              "group" : "apache"
              },

              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },

Here we are pulling down our simple html file from our S3 bucket. I could have easily added code here that would have written to the file the HTML code. Its just cleaner looking code wise to simply pull down the file from your bucket. We are also setting the conf file for cfn-hup. That’s a helper daemon that detects changes and reacts when you are making updates to your stack.

"/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
                  "action=/opt/aws/bin/cfn-init -v ",
                  "         --stack ", { "Ref" : "AWS::StackName" },
                  "         --resource WebServerInstance ",
                  "         --configsets InstallAndRun ",
                  "         --region ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },
            "services" : {
              "sysvinit" : {  
                "httpd"   : { "enabled" : "true", "ensureRunning" : "true" },
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                              "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}}}}}
},

More cfn helper to manage changes. Also see that we are enabling and making sure that httpd and cfn-hup are running on startup. This could also be done through scripting placed into the template.

"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 -xe\n",
             "yum update -y aws-cfn-bootstrap\n",

             "# Install the files and packages from the metadata\n",
             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --configsets InstallAndRun ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n",

             "# Signal the status from cfn-init\n",
             "/opt/aws/bin/cfn-signal -e $? ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"]]}}}
},

Properties for the instance…Calling on the Mappings info and the yet to be mentioned SecurityGroup. This is also where the packages are installed and configured as you can see the scripting here. Also note that this has all been part of “WebServerInstance”. We are just ending that section.

"WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access via port 80",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
          {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
        ]
      }
    }
  },

This sets up the security group and allows access to ports 22 and 80 for http and ssh traffic.

"Outputs" : {
    "WebsiteURL" : {
      "Description" : "URL for newly created Apache server",
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] }
    }
  }
}

This section will output the info you need to know the URL of your new instance. You will look in the Output section of your CloudFormation stack to see the info which will be a link you can click to see your webpage.

AWS Command

So now you have your AWS CLI tool installed and you have your template written…now its time to fire up your stack and see the fruits of your labor.

The command you will want to run is:

aws cloudformation create-stack --stack-name STACK_NAME --template-url https://s3.amazonaws.com/BUCKET_NAME/template.json --parameters  ParameterKey=KeyName,ParameterValue=YOUR_KEY_NAME

This declares that you are using cloudformation to create a new stack, you are giving the stack name, location of where you will download and read the template from, and finally filling in the parameter of your AWS key.
*Remember earlier when I said that if you do not have a “default” for a parameter that you will need to provide it? This is where I was talking about. For the KeyName param we did not provide a default keyname to use. You can pass a number of parameters on the command line as we have here up to a maximum of 60. Really at that point you should be looking at a scripted option to provide those right?

So once you have executed the above command you can look in your CloudFormation and see your stack being created. If it fails it will stop and rollback the creation. Once it completes go to your Output tab and you should see the URL of your webpage. Click it and you should see whatever you put in your index.html file that is in your S3 bucket.

That’s about it. The best way to learn this is to play around with it and read through the CloudFormation documentation. Let me know if you have comments or questions.

 

Full template for you to copy and paste:

Make sure you use a json validator to be sure that the copy and paste didn’t mangle anything.
{
  "AWSTemplateFormatVersion" : "2010-09-09",

  "Description" : "Create an Apache webserver with a webpage.",

  "Parameters" : {
    "InstanceType" : {
      "Description" : "Type of EC2 instance to launch",
      "Type" : "String",
      "Default" : "t1.micro"
    },
    "WebServerPort" : {
      "Description" : "TCP/IP port of the web server",
      "Type" : "String",
      "Default" : "80"
    },
    "KeyName" : {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
      "Type" : "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
    },
    "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" }
    },
    "AWSRegionArch2AMI" : {
      "us-east-1"          : { "64" : "ami-246ed34c" }
    }
  },

"Resources" : {     
      
    "WebServerInstance": {  
      "Type": "AWS::EC2::Instance",
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "InstallAndRun" : [ "Install" ]
          },

          "Install" : {
            "packages" : {
              "yum" : {
                "httpd"        : []              
              }
            },

            "files" : {
              "/var/www/html/index.html" : {
              "source" : "https://s3.amazonaws.com/BUCKET_NAME/index.html",  
              "mode"  : "000600",
              "owner" : "apache",
              "group" : "apache"
              },

              "/etc/cfn/cfn-hup.conf" : {
                "content" : { "Fn::Join" : ["", [
                  "[main]\n",
                  "stack=", { "Ref" : "AWS::StackId" }, "\n",
                  "region=", { "Ref" : "AWS::Region" }, "\n"
                ]]},
                "mode"    : "000400",
                "owner"   : "root",
                "group"   : "root"
              },

              "/etc/cfn/hooks.d/cfn-auto-reloader.conf" : {
                "content": { "Fn::Join" : ["", [
                  "[cfn-auto-reloader-hook]\n",
                  "triggers=post.update\n",
                  "path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
                  "action=/opt/aws/bin/cfn-init -v ",
                  "         --stack ", { "Ref" : "AWS::StackName" },
                  "         --resource WebServerInstance ",
                  "         --configsets InstallAndRun ",
                  "         --region ", { "Ref" : "AWS::Region" }, "\n",
                  "runas=root\n"
                ]]}
              }
            },

            "services" : {
              "sysvinit" : {  
                "httpd"   : { "enabled" : "true", "ensureRunning" : "true" },
                "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true",
                              "files" : ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"]}
              }
            }
          }

        }
      },
      "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 -xe\n",
             "yum update -y aws-cfn-bootstrap\n",

             "# Install the files and packages from the metadata\n",
             "/opt/aws/bin/cfn-init -v ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --configsets InstallAndRun ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n",

             "# Signal the status from cfn-init\n",
             "/opt/aws/bin/cfn-signal -e $? ",
             "         --stack ", { "Ref" : "AWS::StackName" },
             "         --resource WebServerInstance ",
             "         --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}        
      }
    },
    
    "WebServerSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable HTTP access via port 80",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0"},
          {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "SSHLocation"}}
        ]
      }
    }
  },
  
  "Outputs" : {
    "WebsiteURL" : {
      "Description" : "URL for newly created Apache server",
      "Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]] }
    }
  }
}
Advertisements

Using AWS CLI to connect to MySQL on RDS

I messing around with RDS on Amazon Web Service for a project im working on and realized that there is not a true way to connect to the instance that the database is running on when you stand up a MySQL instance.

After poking around a little bit I came up with this solution and it worked ok for me. Probably needs to be refined and there is probably an easier way also but this worked for me.

First im going to assume you have a MySQL instance running in RDS. Once you have this done you will need to download and unzip the AWS CLI tool to a directory you have access to. > http://aws.amazon.com/developertools/2928

Once you have done this you will need to unzip the package. You can check out the README if you want or you can just do this…
1. copy the credential-file-path.template file and call it something like “cred-file” then chmod it 600
2. vi cred-file fill in the AWSAccessKeyId and AWSSecretKey values. You can get these values from IAM control panel in AWS under your user. If you are lost on that there’s a handy tool called Google. 🙂
3. You will need to set AWS_RDS_HOME in your path
4. Make sure JAVA_HOME is set in your path

Once you have followed these steps you can now try it out…
Do: $AWS_RDS_HOME/bin/rds-describe-db-instances --aws-credential-file cred-file --headers
Hopefully your formatting will be better than what you see here but you should see something similar to this:

DBINSTANCE DBInstanceId Created Class Engine Storage Master Username Status Endpoint Address Port AZ SecAZ Backup Retention Multi-AZ Version License Publicly Accessible Storage Type
DBINSTANCE blah 2014-10-15T17:36:01.553Z db.t1.micro mysql 5 blah available blah.czbrj4wkmqs3.us-east-1.rds.amazonaws.com 3306 us-east-1b us-east-1a 7 y 5.6.19 general-public-license y gp2
SECGROUP Name Status
SECGROUP default active
PARAMGRP Group Name Apply Status
PARAMGRP default.mysql5.6 in-sync
OPTIONGROUP Name Status
OPTIONGROUP default:mysql-5-6 in-sync

Now you have tested and know you can access your MySQL db in RDS.

Chef: Spin-up and bootstrap a node on AWS

A few quick instructions for spinning up a node on AWS using Chef and the Knife EC2 plugin.
Some of these steps I culled together from various sites and thought it might be helpful to have them all in one spot.

Base box: This is running from an instance I stood up on AWS (redhat)

Prep work:

DO: yum groupinstall Development tools
DO: Install Chef Client: curl -L https://www.opscode.com/chef/install.sh | bash
DO: Download your starter kit from your Chef Hosted account and unzip in /opt/chef/ (assuming you have a hosted account already setup there)
DO: copy your AWS key file (.pem) to your /home/ec2-user/.ssh/ folder so your workstation can connect back to AWS to spin up new instances. (There may be a different or better way of doing this but it worked for me)

 

Install the Knife EC2 plugin…
sudo /opt/chef/embedded/bin/gem install knife-ec2

Configure the knife.rb for AWS…(knife.rb is located at something like… /opt/chef/chef-repo/.chef/knife.rb)

Knife File
____________________________________________________________________________________________

current_dir = File.dirname(__FILE__)
log_level :info
log_location STDOUT
node_name "YOUR_USERNAME"
client_key "#{current_dir}/YOUR_USERNAME.pem"
validation_client_name "YOUR_ORGNAME-validator"
validation_key "#{current_dir}/YOUR_ORGNAME-validator.pem"
chef_server_url "https://api.opscode.com/organizations/YOUR_ORGNAME"
cache_type 'BasicFile'
cache_options( :path => "#{ENV['HOME']}/.chef/checksums" )
cookbook_path ["#{current_dir}/../cookbooks"]

#A note about where to find this info…
#You will need to log into your AWS IAM (https://console.aws.amazon.com/iam) Go to users, click your #username and you should see an area that says “Access Credentials”. You will likely need to create new #ones if you didnt already know what your keys were at this point. Do so and then make sure you download #them and keep in a safe spot. Fill out the next two lines…the rest is optional at this point but #useful to know that you can have this here.

knife[:aws_access_key_id] = “AWS_ACCESS_KEY_ID”
knife[:aws_secret_access_key] = “AWS_SECRET_ACCESS_KEY”

# Default flavor of server (m1.small, c1.medium, etc).
knife[:flavor] = “m1.small”

# Default AMI identifier, e.g. ami-12345678
#knife[:image] = “ami-b06a98d8”

# AWS Region
#knife[:region] = “us-east-1”

# AWS Availability Zone. Must be in the same Region.
#knife[:availability_zone] = “us-east-1b”

# A file with EC2 User Data to provision the instance.
#knife[:aws_user_data] = “”

# AWS SSH Keypair.
##knife[:aws_ssh_key_id] = “Name of the keypair you want to use in AWS…Instance> Keypair”
___________________________________________________________________________________________

 

Final Command

Finally run this command to connect to AWS and start up your instance and install the recipe:
sudo knife ec2 server create -x ec2-user -S *KEY_NAME* -G default,www -r 'recipe[apache2]' -I ami-b06a98d8

-x = user that we’ll connect with SSH
-S = AWS SSH keypair
-G = Security groups
-r = recipes to run once the instance is up
-I = AMI Identifier e.g. ami-12345678

(This is assuming you already know how to store your cookbooks locally and upload them to your Chef server. )

Once this completes you should have a new instance on AWS with a working apache2 instance and should be able to navigate to the webpage you created for Apache. A separate post will be coming soon to cover these steps.

 

Possible Error

You could possibly run into this:
[fog][WARNING] Unable to load the ‘unf’ gem. Your AWS strings may not be properly encoded.
ERROR: Excon::Errors::SocketError: getaddrinfo: Name or service not known (SocketError)

If so install UNF via gem like so:
sudo /opt/chef/embedded/bin/gem install unf
Try your create command again…

Once you are finished playing around you can use Knife EC2 to actually delete the AWS instance and also remove the node from your hosted Chef management Console:
sudo knife ec2 server delete -y –purge INSTANCE_IDENTIFIER
sudo knife ec2 server delete -y --purge i-e639ca0d

 

Setting up Open Chef Server and a Workstation

The quick and dirty way…

Prep work

For me, I stood up two Centos 6.5 instances in virtualbox. I did the basics of installing the EPEL repo, groupinstall of “Base” and “developer tools” in YUM, setup and configured a user for myself.

Create my user:

useradd -m -G wheel seth
passwd seth

Install EPEL repo:

wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

YUM Groupinstall:

sudo yum groupinstall base "developer tools"


Downloading the needed files

http://www.getchef.com/chef/install/

First we will install the server…

 

For the server

Pick which package you need here and download it to the “chef-server”

cd /opt
sudo wget "https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-server-11.0.12-1.el6.x86_64.rpm"
sudo rpm -ivh  chef-server-11.0.12-1.el6.x86_64.rpm
sudo chef-server-ctl reconfigure

This command will set up all of the required components, including Erchef, RabbitMQ, and PostgreSQL

 sudo chef-server-ctl test

 

For the Workstation

As root run the curl command supplied to you from the Chef Download page. For me it was…

curl -L https://www.opscode.com/chef/install.sh | bash

Once this completes do this to test the install and see the version number:

chef-client -v

Now install GIT…

yum install git

(This will install version 1.7.1-ish)

From here as my own user I went to my home directory and cloned down the Chef GIT repo:

git clone git://github.com/opscode/chef-repo.git

Next cd into the chef-repo dir and create your .chef folder. This folder will hold your authorization files in a few steps from now.

cd chef-repo
 mkdir .chef

Add your .chef to the .gitignore file so it and its contents will not be uploaded.

echo .chef >> .gitignore

Get the .pem files and knife.rb files
You will need to copy these files from the chefserver that you previously setup. These files essentially give you access to connect to the server via chef-client and with knife. For me the command run from my workstation was…

sudo scp root@192.168.1.152:/etc/chef-server/admin.pem /home/seth/chef-repo/.chef/admin.pem
sudo scp root@192.168.1.152:/etc/chef-server/chef-validator.pem /home/seth/chef-repo/.chef/chef-validator.pem

You then want to run the knife initial command to create the knife.rb file in your .chef folder. Unless you know the hostname of your server and the locations of your admin and chef-validator.pem files this step will fail. You also need to make sure that port 443 is open on your server. You can do that with this:

sudo iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
sudo service iptables save

Now do this:

knife configure --initial

Here is what my output looked like to give you an idea of what to expect:

[seth@chefworkstation001 .chef]$ knife configure --initial
 Overwrite /home/seth/.chef/knife.rb? (Y/N)y
 Please enter the chef server URL: [https://chefworkstation001.devopshomelab:443] https://192.168.1.152:443
 Please enter a name for the new user: [seth]
 Please enter the existing admin name: [admin]
 Please enter the location of the existing admin's private key: [/etc/chef-server/admin.pem] /home/seth/chef-repo/.chef/admin.pem
 Please enter the validation clientname: [chef-validator]
 Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] /home/seth/chef-repo/.chef/chef-validator.pem
 Please enter the path to a chef repository (or leave blank):
 Creating initial API user...
 Please enter a password for the new user:
 Created user[seth]
 Configuration file written to /home/seth/.chef/knife.rb

Once you successfully make it past this point you should be good to go. You can test your configuration and connectivity to your server by running the following two commands:

knife client list
knife user list

Now lets bootstrap our new chef workstation

On the server you will need to configure knife like we did on the client side so do:

sudo knife configure -i

You will see something similar to what we saw the firwst time we ran this. Here is my output…

WARNING: No knife configuration file found
Where should I put the config file? [/root/.chef/knife.rb]
Please enter the chef server URL: [https://chefserver.devopshomelab:443]
Please enter a name for the new user: [seth] chefserver
Please enter the existing admin name: [admin]
Please enter the location of the existing admin's private key: [/etc/chef-server/admin.pem]
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem]
Please enter the path to a chef repository (or leave blank):
Creating initial API user...
Please enter a password for the new user:
Created user[chefserver]
Configuration file written to /root/.chef/knife.rb

If you have everything configured correctly you can now bootstrap your workstation by running the following command:

sudo ./knife bootstrap 192.168.1.153 --sudo -x seth -N "chefworkstation001"

 

You should have successfully installed and configured a working Chef open server and workstation following these steps. If you have questions or comments please feel free to use the comment section below. As always you can also consult the official Chef documentation on this subject by going here:

SERVER: http://docs.opscode.com/install_server.html

WORKSTATION: http://docs.opscode.com/install_workstation.html

Also check out my other post about bootstrapping a node in your new Chef environment. HERE

Chef Logs

Looking for chef’s log files? Look in your /etc/chef/client.rb file.

Here’s mine on my local test machine…

log_level :info
log_location STDOUT
chef_server_url 'https://localhost:443'
validation_client_name 'chef-validator'

You can change the location of where the log file points to here to something like: /var/log/chef/client.log

If such a place doesnt already exist you can always do:

sudo mkdir /var/log/chef/
sudo touch /var/log/chef/chef-client.log

I suppose if you wanted to be fancy about it you could hook that logfile into Logstash to track whatever type of trends you wanted.

Happy logging…

 

Log into your AWS EC2 instance as your own user

Once you have created and stood up your EC2 instance on AWS you will want to create your own user. By default you have to use the “ec2-user” user and you are not allowed to log in as root*. So you create your own…

sudo useradd -m -G wheel seth
passwd seth

Once you have done this and you have setup your keys correctly (Separate post) you will want to log in as your new user you created…but you cant. Until you do this…

cp -r /root/.ssh /home/user
chown -R user /home/user/.ssh

This allowed me to use the keypair.pem file to log in.

Now what you must do is turn on the ability to SSH in with a password. This option is turned off by default in all Linux AMIs.

vi, nano, pico, etc. into the following file with root privileges:

sudo vi /etc/ssh/sshd_config

Set the following to YES

PasswordAuthentication = yes

Finally you must restart SSH

sudo service sshd restart

That’s it. You must still add users with the adduser command and give them passwords with the passwd command for them to be able to login to your AMI.

* – In case you need to login as root you can do it with this… sudo su -

Add a new drive to Centos Virtualbox Guest

I run into this a lot and always forget what the steps are…

With the guest powered off you will need to open VBx manager, right click on your guest name that you want to add the drive to and go to SETTINGS.

Click STORAGE and then either click IDE or SATA controller to highlight it. Then you will click the little drive icon next to it. I always choose new disk at the next little pop up. Follow the prompts….
If you get to this step and that icon is ghosted out make sure your guest is powered off. As of right now I dont think there is a way to hot-add a drive in VBx.

I choose VDI and DYNAMICALLY ALLOCATED, give it a name and a size. I ususally go with about 50GB since all of my VMs are for experimental use and I likely wont use that whole amount.

From here thats all you have to do in VBx itself. Next you will want to start up your gest and mount the drive…

Once you get logged in follow these steps…
sudo fdisk -l
Make sure you see your new drive here. It might be listed as something like /dev/sdb Then do the following….

mkdir /mnt/newdisk
mount -t ext3 /dev/sdb1 /mnt/newdisk
cd /mnt/newdisk
df

to mount automatically on boot, add disk to /etc/fstab my /etc/fstb for example, i added last line

LABEL=79d3d2d4 / ext4 defaults,noatime 0 0
LABEL=e21a3e10 /boot ext3 defaults,noatime 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
/dev/sdb1 /mnt/newdisk ext3 defaults 0 0