Hosting WordPress Application on an EC2 Instance – AWS

In this post, we will deploy WordPress Application on an EC2 Amazon Linux AMI t2.micro instance following below steps:

Step 1: Set up Amazon EC2 instance following set-up-amazon-ec2-instance.

Step 2: Launch an EC2 instance following ec2-launch-linux-instance.

Step 3: As creating a wordpress application is not a part of this post, I already created one and zipped it as wordpress-app.zip which we will securely copy from local machine to an EC2 instance home directory (/home/ec2-user) using ec2-user as follows:

scp -i /Users/ArpitAggarwal/arpitaggarwal-key-pair.pem /Users/ArpitAggarwal/wordpress-app.zip ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com:/home/ec2-user

arpitaggarwal-key-pair.pem refers to private key file.
ec2-54-218-30-7.us-west-2.compute.amazonaws.com refers to Public DNS name of EC2 instance.

Step 4: Export wordpress-app database, as follows:

cd /applications/MAMP/library/bin
./mysqldump -u root -p**** wordpress > /Users/ArpitAggarwal/export-wordpress-data.sql

/applications/MAMP/library/bin refers to MAMP local database store.
./mysqldump referes to command to get mysqldump.

Step 5: Copy export-wordpress-data.sql we created from local machine directory to EC2 instance home (/home/ec2-user) directory:

scp -i /Users/ArpitAggarwal/arpitaggarwal-key-pair.pem /Users/ArpitAggarwal/export-wordpress-data.sql ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com:/home/ec2-user

Step 6: Login to your EC2 instance with private key file and Public DNS name using ssh:

ssh -i /Users/ArpitAggarwal/arpitaggarwal-key-pair.pem ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com

Step 7: Change collation of your database by executing following commands in /home/ec2-user after login to an EC2 instance:

sed -i 's/utf8mb4/utf8/g' export-wordpress-data.sql
sed -i 's/utf8_unicode_ci/utf8_general_ci/g' export-wordpress-data.sql
sed -i 's/utf8_unicode_520_ci/utf8_general_ci/g' export-wordpress-data.sql

Step 8: Set up Linux, Apache, MySQL, PHP (LAMP) stack on an EC2 CentOS 6 instance and set the processes to run automatically when the server boots, executing below commands:

sudo yum install httpd
sudo yum install mysql-server
sudo yum install php php-mysql
sudo service mysqld start
sudo chkconfig httpd on
sudo chkconfig mysqld on

Step 9: Set a root MySQL password same as you have provided in your wordpess-app, executing below command and choosing specific option for all the prompt:

sudo /usr/bin/mysql_secure_installation

Step 10: Login to MySQL database on an EC2 instance and create DATABASE same as you have provided in your wordpess-app, for me it’s wordpress:

mysql -u root -p****
mysql> CREATE DATABASE IF NOT EXISTS wordpress;

Step 11: Import export-wordpress-data.sql to newly created database, as follows:

mysql -uroot -p**** wordpress < export-wordpress-data.sql

Step 12: Inflate wordpress-app.zip, Copy all the files to /var/www/html directory and create .htaccess file inside the same directory:

unzip wordpress-app.zip
sudo cp -R wordpress-app/* /var/www/html
cd /var/www/html
sudo touch .htaccess

Replace the content of .htaccess file with below:

# BEGIN WordPress
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Step 13: Edit httpd.conf placed in /etc/httpd/conf to set value of AllowOverride directive to All for the /var/www/html directory, as below:

<Directory "/var/www/html">
  Options Indexes FollowSymLinks
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

Step 13: Restart apache to reflect all of the changes we did:

sudo service httpd restart

Now, access the wordpress-app from your browser using Public DNS name or Public IP of your EC2 instance as: http://ec2-54-218-30-7.us-west-2.compute.amazonaws.com/

Need to move WordPress site to a new Host?

It can be easily done by updating the option_value, post_content and guid of the application directly in the MySQL database executing below scripts:

UPDATE wp_options SET option_value = 'http://new-host/' WHERE option_name = 'home';
UPDATE wp_options SET option_value = 'http://new-host/' WHERE option_name = 'siteurl';
UPDATE wp_posts SET post_content = REPLACE(post_content,'http://old-host/','http://new-host/');
UPDATE wp_posts SET guid = REPLACE(guid,'http://old-host/','http://new-host/');

Executing Cookbooks with Chef-Solo

Chef-Solo is an open source tool that runs locally and allows us to provision the guest machine using chef cookbooks without the complication of any chef client and server configuration. In this post, we will learn to execute a simple recipe which will create a file with some content inside /tmp directory using chef cookbook recipe.

To start with, we will create a directory where all our chef related content resides and for me it’s chef-repository, as follows:

$ mkdir chef-repository

Next, we will configure Knife inside our chef-repository to create cookbooks and recipes, as follows:

$ cd chef-repository
$ mkdir .chef
$ echo "cookbook_path [ '/vagrant/chef-repository/cookbooks' ]" > .chef/knife.rb

/vagrant/chef-repository/cookbooks specified above refers the path to chef cookbooks.

Now, we will create our first cookbook using knife which will also create recipe with name default.rb for us with default content, as follows:

$ knife cookbook create mycookbook

Edit the content of cookbooks/mycookbook/recipes/default.rb to create the file with name default-file with given content inside /tmp directory as below:

file "/tmp/default-file" do
  content "It's file created by Chef Recipe"
  owner "root"
  group "root"
  mode 00600
end

Move to directory ‘cookbooks’ and create chef configuration file solo.rb:

$ echo "cookbook_path ['$PWD']" > solo.rb

Next, run the recipe we created using chef-solo., as follows:

$ chef-solo -c solo.rb -o mycookbook::default;

Running multiple recipes inside cookbook?

We can run multiple recipes using chef-solo –override-runlist and –json-attributes command line options as follows:

a). Using chef-solo –override-runlist

chef-solo -c solo.rb -o recipe[mycookbook::default],mycookbook::first

mycookbook::first refers to the recipe with name first.rb inside directory cookbooks/mycookbook/recipes/

b). Using chef-solo –json-attributes

Create a .json file with any name for me it’s recipes.json with content as:

{
  "run_list": [
    "recipe[mycookbook::default]",
    "recipe[mycookbook::first]"
  ]
}

Then execute below command from directory ‘cookbooks’:

sudo chef-solo -c solo.rb -j recipes.json

Dockerizing Web Application with Puppet

In post Installing Puppet Modules – Librarian Puppet we provisioned a Vagrant VM to install the puppet module from  Puppet Forge using librarian-puppet, now in this post we will do the same thing except we provision Docker container instead of Vagrant VM and deploy a hello-spring application in provisioned container.

Before starting with application deployment in Docker container let’s understand brief about Docker and how it is different from Virtual Machine.

What is Docker?

Docker is a high level abstraction over linux containers which manages the life cycle of containers. Docker allows to package an application with all of its dependencies into a standardize unit for software development. And if that unit runs on your local, we can guarantee that it will run exactly the same way, anywhere from QA, to staging, to production environments.

Docker vs Virtual Machine

Virtualization technologies like VirtualBox, VMWare, KVM, etc. use full machine virtualization whereas Docker share certain portions of the host kernel and operating system instance offering lower overhead at the cost of less isolation. Also, Docker provides a virtual environment that has its own CPU, memory, block I/O, network, etc. space using Cgroups features in Linux kernel on LXC host compared to virtualization technologies which offer us complete new virtual machine.
Now, let’s start with our deployment in container, following below steps:

Step 1: Create a directory with any name for me it’s docker and file with name Dockerfile and  Puppetfile inside the directory as follows:


$ mkdir docker
$ cd docker
$ touch Dockerfile Puppetfile

Dockerfile created above contains all the commands a user could call on the command line to assemble an image.

Puppetfile created above is a Ruby-based DSL specifies where puppet modules should be installed and where to fetch the modules from.

Step 2: Copy the below content in Puppetfile:

# Puppetfile Configuration for librarian-puppet.
forge "http://forge.puppetlabs.com"
mod "puppet-java8", :git => "https://github.com/arpitaggarwal/puppet-java8.git"
mod "arpitaggarwal/tomcat"

Step 3: Copy the below content in Dockerfile

FROM ubuntu:latest
MAINTAINER arpitaggarwal "aggarwalarpit.89@gmail.com"
RUN apt-get -y update
RUN apt-get -q -y install git
RUN sudo apt-get install -y ruby
RUN apt-get install -y ruby-dev
RUN apt-get -y update
RUN apt-get install -y make
RUN apt-get install -y build-essential
RUN apt-get install -y puppet
RUN gem install librarian-puppet
ADD Puppetfile /
RUN librarian-puppet install
RUN puppet apply --modulepath=/modules -e "include java8 class { 'tomcat':version => '7',java_home => '/usr/lib/jvm/java-8-oracle'}"
RUN apt-get remove -y make puppet build-essential ruby-dev

Step 4: Build the the application inside a docker directory, for me it’s hello-spring cloned from github:

$ git clone https://github.com/arpitaggarwal/hello-spring.git
$ cd hello-spring
$ mvn clean install

Step 5: Update the Dockerfile adding your .war file location using Docker COPY command:

COPY hello-spring/target/hello-spring.war /var/lib/tomcat7/webapps/
EXPOSE 8080

EXPOSE command specified above refers to Docker command which is good for inter-container communication.

Finally, Dockerfile should like as:

FROM ubuntu:latest
MAINTAINER arpitaggarwal "aggarwalarpit.89@gmail.com"
RUN apt-get -y update
RUN apt-get -q -y install git
RUN sudo apt-get install -y ruby
RUN apt-get install -y ruby-dev
RUN apt-get -y update
RUN apt-get install -y make
RUN apt-get install -y build-essential
RUN apt-get install -y puppet
RUN gem install librarian-puppet
ADD Puppetfile /
RUN librarian-puppet install
RUN puppet apply --modulepath=/modules -e "include java8 class { 'tomcat':version => '7',java_home => '/usr/lib/jvm/java-8-oracle'}"
RUN apt-get remove -y make puppet build-essential ruby-dev
COPY hello-spring/target/hello-spring.war /var/lib/tomcat7/webapps/
EXPOSE 8080

Step 6: Build the Docker container using Docker build command:


docker build --no-cache=true -t spring-application-container .

spring-application-container specified above refers to name of a docker image.

Step 7: Once built, run the container using Docker run command:

docker run -p 8080:8080 --cap-add SYS_PTRACE -it spring-application-container /bin/bash

Step 8: Get your Docker container IP Address, using docker-machine:


docker-machine ip your_vm_name

Next, open the url http://container-ip-address:8080/hello-spring

The complete source code is hosted on github.

Deploying Web Application on EC2 Instance- AWS

In this post, we will deploy spring web application on EC2 Amazon Linux AMI t2.micro instance following below steps:

Step 1: Set up Amazon EC2 instance following set-up-amazon-ec2-instance.

Step 2: Launch an EC2 instance following ec2-launch-linux-instance.

Step 3: Upload .war file from local machine directory to EC2 user home (/home/ec2-user) directory using secure copy as follows:

scp -i /Users/ArpitAggarwal/arpitaggarwal-key-pair.pem /Users/ArpitAggarwal/hello-spring/target/hello-spring.war ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com:/home/ec2-user

arpitaggarwal-key-pair.pem refers to private key file.
ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com refers to public dns name of EC2 instance.

Step 4: Connect to your EC2 instance using your private key file and public dns name as follows:

ssh -i /Users/ArpitAggarwal/arpitaggarwal-key-pair.pem ec2-user@ec2-54-218-30-7.us-west-2.compute.amazonaws.com

Step 5: Install Tomcat7 on EC2 instance as a root user:

[ec2-user@ip-10-0-0-28 ~]$ sudo su root
[ec2-user@ip-10-0-0-28 ~]$ yum install tomcat7

Step 6: Copy .war file from ec2-user home directory to webapps folder of tomcat, as follows:

[root@ip-10-0-0-28 ec2-user]# cp hello-spring.war /usr/share/tomcat7/webapps/

Step 7: Edit the JAVA_HOME in /etc/tomcat7/tomcat7.conf to point to JDK 7, replacing

# Where your java installation lives
JAVA_HOME="/usr/lib/jvm/jre"

to

# Where your java installation lives
JAVA_HOME="/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64"

Step 8: Start tomcat as follows:

[root@ip-10-0-0-28 ec2-user]# start tomcat7

Step 9: As tomcat is running on port 8080, we have to allow 8080 port from security group. To do that, from your instance, find out the security group associated and edit the security group adding another Type as Custom TCP Rule, Protocol as TCP, Port Range as 8080 and Source as Anywhere.

Now, access the web application from your browser using public dns name of your ec2 instance as:
http://ec2-54-218-30-7.us-west-2.compute.amazonaws.com:8080/hello-spring/

The complete source code of spring web application is hosted on github.

Installing Puppet Modules – Librarian Puppet

Of course we can manually download the modules from Puppet Forge and install it but it becomes messy as you have to manually maintain the dependencies between the modules which definitely makes your repository bigger than necessary.

Already I briefed about librarian-puppet  in my Blog At Xebia, still to provide little more context, it manages the Puppet modules your infrastructure depends on, whether the modules come from the Puppet Forge, Git repositories or just a path. People who are familiar with Maven can relate librarian-puppet similar to it as it automatically download and manage dependent modules.

In this article we will learn how to install arpitaggarwal/tomcat Puppet Module using librarian-puppet. The complete source code is hosted on github.

Step 1: Create a directory with any name for me it’s vagrant, as follows:


$ mkdir vagrant
$ cd vagrant
$ vagrant init

Step 2: Edit the Vagrantfile with below content:


VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "hashicorp/precise32"
config.vm.network :private_network, ip: "90.0.9.99"
config.vm.provision "shell", path: "installation-script.sh"
config.vm.provision :puppet do |puppet|
puppet.manifests_path = 'puppet/manifests'
puppet.module_path = 'puppet/modules'
puppet.manifest_file ="init.pp"
end
end

Step 3:  Create installation-script.sh in your current project directory(vagrant), which will install, librarian-puppet, it’s dependency GIT and Puppet in your guest machine, as follows:


$ touch installation-script.sh

Content of installation-script.sh should look something like this:


#!/usr/bin/env bash
set -e
# Directory in which PuppetFile is placed to be scanned by librarian-puppet.
PUPPET_DIR=/vagrant/puppet

echo "Installing Git.."
apt-get -q -y install git

echo "Installing librarian-puppet.."
if [ "$(gem search -i librarian-puppet)" = "false" ]; then
RUBY_VERSION=$(ruby -e 'print RUBY_VERSION')
case "$RUBY_VERSION" in
1.8.*)
# For ruby 1.8.x librarian-puppet needs to use 'highline' 1.6.x
# highline >= 1.7.0 requires ruby >= 1.9.3
gem install highline --version "~>1.6.0" > /dev/null 2>&1
# Install the most recent 1.x.x version, but not 2.x.x which needs Ruby 1.9
gem install librarian-puppet --version "~>1"
;;
*)
gem install librarian-puppet
;;
esac
fi
echo "librarian-puppet installed!"

echo "Executing PuppetFile.."
cd $PUPPET_DIR && librarian-puppet install --path modules

echo "Installing Puppet repo for Ubuntu 12.04 LTS"
wget -qO /tmp/puppetlabs-release-precise.deb \
https://apt.puppetlabs.com/puppetlabs-release-precise.deb
dpkg -i /tmp/puppetlabs-release-precise.deb
rm /tmp/puppetlabs-release-precise.deb
aptitude update
echo Installing puppet
aptitude install -y puppet
echo "Puppet installed!"

Step 4: Make directory puppet and then modules and manifests under it, as follows:


$ mkdir puppet
$ cd puppet/
$ touch Puppetfile
$ mkdir modules
$ mkdir manifests
$ cd manifests
$ touch init.pp

Content of Puppetfile should look like:


forge "http://forge.puppetlabs.com"
mod "arpitaggarwal/tomcat"

Content of puppet/manifests/init.pp should look like:


class { 'tomcat': }

After performing all the above steps, your project structure should look like as:

Step 6: Now you can boot up your VM provisioned with Tomcat from the vagrant directory executing command:


$ vagrant up

That’s all. Happy Learning!

Creating Identity and Access Management (IAM) User – AWS

In this post we will create an Identity and Access Management (IAM) User with administrative permissions for AWS and then we will access AWS using a special URL with the credentials of the newly created IAM user. Steps are as follows:

Create the Administrators group

  1. Sign in to the AWS Management Console and open the IAM console at https://console.aws.amazon.com/iam/.
  2. In the navigation pane, click Groups, and then click Create New Group.
  3. In the Group Name box, type Administrators , and then click Next Step.
  4. In the list of policies, select the check box next to the AdministratorAccess policy.
  5. Click Next Step, and then click Create Group.

Your new group called “Administrators” is listed under Group Name.

Create an IAM user

  1. In the navigation pane, click Users, and then click Create New Users.
  2. In box 1, type a user name. Clear the check box next to Generate an access key for each user. Then click Create.

Add the user to the Administrators group

  1. In the navigation pane, click Groups.
  2. In the Groups section, click Add User to Groups.
  3. Select the check box next to the Administrators group, then click Add Users to Groups from Group Actions dropdown.
  4. Select the check box next to the user name, then click Add Users.

Create a password for the user

  1. In the navigation pane, click Users, select the user and click Manage Password from User Actions dropdown.
  2. Select Assign a custom password. Then type a password in the Password and Confirm Password boxes, then click Apply.

Is IAM User Created?

  1. Sign out of the AWS console, then use the following URL, https://your_aws_account_id.signin.aws.amazon.com/console/
    where your_aws_account_id is your AWS account number.
  2. Enter the IAM user name and password that you just created. When you’re signed in, the navigation bar displays “your_user_name @ your_aws_account_id”.

Want to know your AWS Account Number?

Sign in as a root user to your AWS Account at following url: https://console.aws.amazon.com/billing/home?#/account.