For simplicity, I deploy thin + nginx for most of my rails applications. Thin is lighter weight than Passenger and the combo makes it more favorable than running Apache. I began learning Chef and saw nothing for thin existed so I attempted to make a cookbook.
If you don't want to read any more about this, then jump over to the code on github chef-thin_nginx.
This cookbook will install thin as a gem and complete a configuration. While 'nginx' will be installed from package and installed as a normal service.
To make the 'thin' installation from gem work properly, 'rvm' is required. rvm has a shell interface that is used to install the service from the gem. I previously tried to install thin from source and it wouldn't work correctly because 'rake' tasks are necessary gems that aren't loaded into the internal 'chef' gemset. In addition, I tried to install the thin gem to chef's internal gemset, but I received lots of errors when it came to postgresql gems. That is why rvm is necessary. rvm will install version 1.6.1 of thin unless you change the parameters. This was tested with 1.6.1 so it will work.
nginx, on the other hand, is a simple repository installation and will be installed as a service.
All of this was tested on Ubuntu 12.04.03 LTS and should be fine with 12.04.4 Precise Penguin.
Attributes
There is only one key attribute that is necessary to be changed and that is ['thin_nginx']['app_name']. This attribute should be changed to the application name (or folder name) that is being served. By default it's set to 'jumpsquares' because that is the project this was based off of. You can see that cookbook here and read more about the JumpSquares.net - a new kind of bookmark project.
Optional attributes such as:
- ['thin_nginx']['user'] is the user that will run the webserver. 99% of the time this is www-data
- ['thin_nginx']['number_of_thins'] will take an integer and spin up as many webservers as you define. The amount will also be added to nginx.conf files during the build
- ['thin_nginx']['rails_env'] is to set any particular environment for thin to use in its configuration.
- ['thin_nginx']['ruby_version'] is used to set a variable based on your default ruby version. This was tested with ruby-2.1.2.
I will not go over any other attributes. Check out the chef-thin_nginx github page to see them all.
To get it to work:
First you must have rvm installed. I think my earlier paragraph will make you understand. Second, you need to have your application resting in it's folder. Usually, this will be in '/var/www/myproject'. Make sure 'myproject' has it's contents filled with everything that it will need. Another point to mention is that this cookbook has only been tested with Rails projects. By default, the server template for nginx is set to the '/public' directory.
root <%= node['thin_nginx']['application_dir'] %>/public;
That's all. Put it in your run-list and have it. Here is a sample run-list that works.
Things not working:
For some odd reason I can't get the attributes to override from another cookbook. So if you're using this as an 'include' into another cookbook, be sure this is taken into account and perhaps upload this cookbook into multiple environments
The Recipe/Code (placing this here for giggles. Up to date code will ALWAYS be on chef-thin_nginx):
#this RVM shell will download the thin gem to your local RVM gemset #then we will install the gem and create a configuration file #the wrapper must be created to allow thin to boot at start rvm_shell "install thin" do ruby_string "#{node['thin_nginx']['ruby_version']}" code %{ source #{node['thin_nginx']['rvm_source']} gem install thin -v #{node['thin_nginx']['thin_version']} rvmsudo thin install /usr/sbin/update-rc.d -f thin defaults rvmsudo thin config -C /etc/thin/#{node['thin_nginx']['app_name']} -c #{node['thin_nginx']['application_dir']} --servers #{node['thin_nginx']['number_of_thins']} -e #{node['thin_nginx']['rails_env']} rvmsudo rvm wrapper #{node['thin_nginx']['ruby_version']} bootup thin } end #we are changing the bootup environment to use our new wrapper ruby_block "changing startup DAEMON for thin" do original_line = "DAEMON=#{node['thin_nginx']['ruby_path']}/gems/#{node['thin_nginx']['ruby_version']}/bin/thin" block do daemon_file = Chef::Util::FileEdit.new("/etc/init.d/thin") daemon_file.search_file_replace_line(/#{original_line}/, "DAEMON=#{node['thin_nginx']['ruby_path']}/bin/bootup_thin") daemon_file.write_file end end #install nginx from package apt_package "nginx" do action :install end #make necessary changes to our nginx.conf file template '/etc/nginx/nginx.conf' do path "/etc/nginx/nginx.conf" source 'nginx.conf.erb' owner 'root' group 'root' mode 0644 action :create end #make changes to our default site file template "/etc/nginx/sites-available/#{node['thin_nginx']['app_name']}" do path "/etc/nginx/sites-available/#{node['thin_nginx']['app_name']}" source 'default0.erb' owner 'root' group 'root' mode 0644 action :create end #create a symbolic link between two folder execute "link thin" do command "ln -nfs /etc/nginx/sites-available/#{node['thin_nginx']['app_name']} /etc/nginx/sites-enabled/#{node['thin_nginx']['app_name']}" end #lets start the nginx service and give it some abilities to etc/init.d service "nginx" do supports :status => true, :restart => true, :reload => true action [ :enable, :start ] end #this will start our webserver for first time use! rvm_shell "start the webserver" do ruby_string "#{node['thin_nginx']['ruby_version']}" code %{ rvmsudo /etc/init.d/thin start rvmsudo /etc/init.d/nginx reload rvmsudo /etc/init.d/nginx restart } end