Follow Me Icons

 

Follow @KendrickColeman on TwitterConnect on LinkedInWatch My Videos on YouTubeFollow me on FacebookCheck Out My Projects on GitHubStay Up To Date with RSS

Search

Deploying JumpSquares with Chef Cookbooks

Over the past week, I started learning Chef. There are a few different configuration management toolsets out there such as Puppet, SaltStack, and Ansible. But Puppet and Chef have majority amount of market share and use Ruby as its code base so it made sense for me to start there. There's no point in starting a project unless you have a goal to accomplish so after I read more about Chef cookbooks, recipes, attributes, etc it seemed like making a JumpSquares cookbook would be a good place to start.

 

Skip the blah blah and see the code at chef-jumpsquares or read on for the complete back story.

 

The setup of Chef is simple and only takes about an hour or two to complete. After the server is up and a node has been added, that's where the fun begins. I began my involvement with looking around for cookbooks that use the same components that are needed in the JumpSquares appliance model. Cookbooks such as postgres for database, rvm for ruby, and nginx for web/application servers were already available and made my job starting out much easier.

 

 

After a while of figuring out how to correctly upload cookbooks via knife (aka, renaming folders for cookbooks properly) and looking at code recipes it was time to go ahead and deploy to see what happens. Of course, everything always fails miserably when you're first starting out, but I was quickly able to read the chef console output and know where something messed up. At this point, I was successfully getting apt, openssl, and postgresql all working correctly. Now it was time to create a JumpSquares recipe to bring the code down. Read along to know what's going on...

include_recipe "postgresql::server"
include_recipe "postgresql::libpq"
include_recipe "postgresql::client"

#create our postgresql user that will have access to the server
pg_user "jumpgres" do
  privileges superuser: true, createdb: true, login: true
  password "jump123"
end
#create the jumpsquares appliance-production environment database
pg_database "jumpsquares_prod" do
  owner "jumpgres"
  encoding "UTF-8"
  template "template0"
  locale "en_US.UTF-8"
end

#create the directory where www files live. most likley this is /var/www/
directory node['jumpsquares']['www_dir'] do
  owner "www-data"
  group "www-data"
  mode 00755
  action :create
end
#create the subdirectory where our application will live
directory node['jumpsquares']['jumpsquares_dir'] do
  owner "www-data"
  group "www-data"
  mode 00755
  action :create
end
#copy from git our jumpsquares project
git node['jumpsquares']['jumpsquares_dir'] do
  user "www-data"
  group "www-data"
  repository "https://github.com/kacole2/JumpSquares.git"
  reference "master"
  action :sync
end
#imagemagick is needed for our apptype images. this is a beastly install. just hang tight
apt_package "imagemagick" do
  action :install
end
#Bundle install runs. This relies on the rvm shell script
#this will also setup the environment by creating the database tables and precomiling some stuff
#IMPORTANT NOTE: the recipe may die here because the rvm environment isn't set. you have two options.
#1. reboot the machine, then run chef-client again
#2. go to the console of the machine and key in "source /usr/local/rvm/scripts/rvm" then run chef-cleint
rvm_shell "bundle install" do
     ruby_string "#{node['rvm']['default_ruby']}"
     cwd node['jumpsquares']['jumpsquares_dir']
     code %{
source #{node['jumpsquares']['rvm_source']}
rvmsudo bundle install
rvmsudo rake RAILS_ENV=appliance-production db:setup
rvmsudo rake RAILS_ENV=appliance-production assets:precompile
}
   end

 

 

This script successfully creates:

  • a postgresql user and database
  • /var/www/jumpsquares folder
  • clones the git repository
  • installs ImageMagick
  • installs all required gems for JumpSquares
  • creates the database schema
  • precompiles all the assets

 

It's still not done. Now that we have the base setup, we have to serve it up. The nginx cookbook from OpsCode uses Passenger as it's webserver. It took me about 2.5 days to figure out why it wasn't working correctly as you can see from stackoverflow thread. Come to find out it was a simple fix, but it isn't implemented anywhere in the nginx cookbook. So for that fix to work, I created a new recipe called jumpsquares::passenger_nginx. This recipe will install all the necessary components (including the jumpsquares::default) and then make changes to nginx configuration files. Remember, the latest code will always be available on github at chef-jumpsquares:

include_recipe "apt"
include_recipe "openssl"
include_recipe "rvm::system"

rvm_shell "bundle install" do
      
     ruby_string "#{node['rvm']['default_ruby']}"
     
     code %{
source #{node['jumpsquares']['rvm_source']}
rvmsudo gem install passenger -v 4.0.42 --no-rdoc --no-ri
rvmsudo gem install rake -v 10.3.1 --no-rdoc --no-ri
}
   end
include_recipe "jumpsquares::default"
include_recipe "nginx::source"
ENV['PATH']="#{node['nginx']['rvm_path']}:#{ENV['PATH']}"

#the passenger configuration is never enabled with the OpsCode nginx cookbook. let's add it
ruby_block "add passenger variable" do
  block do
    site_file = Chef::Util::FileEdit.new("#{node["nginx"]["dir"]}/sites-enabled/000-default")
    site_file.insert_line_after_match(/\slocation\s\/\s{/, " passenger_enabled on;")
    site_file.write_file
  end
end
#we have to specify the rails environment we want to use since we do not want to use 'production'
ruby_block "add rails environment" do
  block do
    passenger_file = Chef::Util::FileEdit.new("#{node["nginx"]["dir"]}/conf.d/passenger.conf")
    passenger_file.insert_line_if_no_match(/passenger_app_env appliance-production;/, "passenger_app_env appliance-production;")
    passenger_file.write_file
  end
end

 

 

During those 2.5 days, I got fed up and decided I could do it my own way. I've always had great success running thinnginx for the JumpSquares appliance as well as MonsterRemote. There were no cookbooks for thinnginx so I decided to make one. Take a look at chef-thin_nginx. It's not fancy, but it gets the job done. So now there is an additional JumpSquares recipe called 'jumpsquares::thin_nginx' that will use this particular cookbook. All of the parameters need to be set in attributes and the chef-thin_nginx cookbook. Remember, the latest code will always be available on github at chef-jumpsquares:

include_recipe "apt"
include_recipe "openssl"
include_recipe "rvm::system"
include_recipe "jumpsquares::default"
include_recipe "thin_nginx"

 

You shouldn't have to change any attribute settings for any of these recipes to work correctly.

 

This was all a great learning experience and made me hate webservers just a little bit more :). But it was simple enough to finally figure out my frustrations and create some open source code as well.