Unicorn does not employ keep files for its configuration file. This page describes how to customize Unicorn without a keep file.
The process is:
- Create an alternate Unicorn configuration file.
- Start Unicorn with Bundler instead of running the system Unicorn.
To create the customized Unicorn configuration file and restart Unicorn
-
Add this line to the file
/data/_myapp_/shared/config/env.custom
(where myapp is the name of your application):UNICORN_CONF="/data/_myapp_/shared/config/custom_unicorn.rb"
This specifies an alternate configuration file for Unicorn.
Note: If you are using env_vars, then use the env_vars recipe to customize the environment variable. If you are already using the env_vars recipe, it will override your settings here. Use the recipe to customize your Unicorn settings.
-
Copy
/data/_myapp_/shared/config/unicorn.rb
to/data/_myapp_/shared/config/custom_unicorn.rb
. -
Edit the
/data/_myapp_/shared/config/custom_unicorn.rb
with the customizations that you want. -
Restart Unicorn so that the customizations take effect:
/engineyard/bin/app_myapp reload
To start Unicorn in Bundler
-
Add the Unicorn gem to your Gemfile:
gem 'unicorn'
-
Run these commands to update your Gemfile.lock:
bundle install
git commit -a -m "Gemfile updated for Unicorn"
git push origin
If you have feedback or questions about this page, add a comment below. If you need help, submit a ticket with Engine Yard Support.
The last example file talks about Trinidad so someone needs to fix this page.
Hi Petteri, thank you for your feedback on our documentation. This page has been updated. kjm
I've successfully used step 1 to load a custom unicorn configuration. However, can you please explain why step 2 is necessary? What happens or doesn't happen when the application has its own unicorn gem? Thanks!
Hi Justin,
When you use Bundler, there are at least two sets of gems on your system at any time: system gems, and gems specific to your application. The question then becomes, when launching the application, which set do you use? If you use Bundler properly, only the gems built specifically for your application should be loaded and used when it spawns up. If you use system gems by not specifying "bundle exec", you'll end up with probably old versions of certain gems, including dependencies, being loaded, which can cause things not to start or to bug out. Imagine trying to start your application and an old version of a gem from, say, 2007 gets loaded instead of what you had bundled. Or worse, a dependency on the system is older than what's in your bundle so the application can't start because Gemfile.lock expects a certain version of said dependency.
All this is avoided by making sure that you use bundler properly. Our configuration will use Bundler to launch applications when there's a Gemfile and a Gemfile.lock present, thus generally avoiding such issues as described here.
J. Austin what you are saying about loading old versions loading is probably true on Engine Yard. However on development systems where system gems and bundler gems are always in the path you will most likely end up with newer versions instead (rubygems loads the latest version if not restricted) because of running bundler update in other projects or gem update system wide.
Thanks for the quick followup! I think I was confused, seeing those instructions in the context of customization. Looking back, step 2 (To start Unicorn in Bundler) is also a recommendation if using Engine Yard's out-of-the-box Unicorn deployment option.
To confirm EY is loading the bundled version of Unicorn, would
ps aux | grep unicorn
then display 'bundle exec unicorn'? If so, it doesn't appear to be applying bundle exec for unicorn, with following the example on step 2 (adding unicorn to Gemfile).Any ideas on further tweaks?
Engine Yard uses a monit configuration script to start Unicorn, which calls a shell script that we've written especially for this. That shell script checks for the existence of a Gemfile, Bundler and bundled gems, and if it finds them, launches the version of Unicorn under the /data/appname/shared/bundled_gems directory. It's not a straight "bundle exec", but modifies $PATH in the same way, so ps would not necessarily show the "bundle exec" prefix, even though it's using the bundled version.
Great thanks J.Austin, I noticed the Bundler.exec checking method in the monit script. Cheers.
Do you also have some sample code how to do that with chef? Or otherwise one will have to apply this to all servers, right?
Hi Michael, To achieve this you would create a custom Chef recipe, putting something along the lines of the below (assuming you are only running one app) in your recipe/default.rb file:
#Set your application name here
appname = "_appname_"
service "unicorn_#{appname}" do
supports :restart => true
end
template "/data/#{appname}/shared/config/env.custom" do
source "env.custom.erb"
owner node[:owner_name]
group node[:owner_name]
mode 0644
backup 0
variables({
:appname => appname
})
notifies :restart, resources(:service => "unicorn_#{appname}")
end
remote_file "/data/#{appname}/shared/config/custom_unicorn.rb" do
source "custom_unicorn.rb"
owner node[:owner_name]
group node[:owner_name]
mode 0644
backup 0
notifies :restart, resources(:service => "unicorn_#{appname}")
end
You would then need to create a templates/default/env.custom.erb file containing:
UNICORN_CONF="/data/<%= @appname %>/shared/config/custom_unicorn.rb"
Also you would need to create a files/default/custom.unicorn.rb that combined the standard Unicorn configuration with your own configuration additions. To do this you would want to copy the contents of the existing unicorn.rb config file from your application into your custom.unicorn.rb and the append your custom config to it. You can retrieve the contents of your current unicorn.rb using the following command from the command line on your local machine:
ey ssh -e _environment_ "cat /data/_appname_/shared/config/unicorn.rb"
One caveat is that if the contents of the unicorn.rb file were ever to be updated by ourselves, you would need to reflect these changes in the custom.unicorn.rb file.
There is now an "env_vars" recipe in the official ey-cloud-recipes cookbook.
If you have customized manually your env.custom file, beware that this recipe will overwrite it.
We tried this chef recipe, unfortunately we get this error when triggering the restart:
ERROR: This script must be run as a user, not as root.
We've resorted to manually invoking /etc/init.d/unicorn_appname restart, but this means it happens every time we apply recipes.
Hey Pat, If you could open a ticket for that we can take a look at it for you.
I'm having a problem using this chef recipe. The recipe applies fine, custom_unicorn.rb is there, the custom.env file contains the path to custom_unicorn.rb, yet unicorn still uses the standard unicorn.rb file. Anybody run into the same problem?
Hi Jacob, would you mind opening a ticket so we can look into the issue? Thanks!