I recently had the need to configure multiple rails apps on a new staging machine. Deploying and configuring applications can be really hard when you don’t have complete and working capistrano’s recipes.
I figured out that the best solution is having recipes that allow you to configure both the correct deploy of the application and the tuning of the application server, web server, delayed jobs, monitor application.
The advantages of this solutions is the fully control of your configuration which is stored in your repository instead of being scattered around in filesystem, in that way you can also view history of the tuning.
All you need to do is to integrate your recipes with templates generating configuration files customized for each environment.
Here’s an example of upstart configuration for puma web server using erb:
# lib/capistrano/templates/puma_upstart.erb
description "<%= fetch(:application) %> puma app"
start on filesystem or runlevel [2345]
stop on runlevel [!2345]
setuid <%= fetch(:user) %>
setgid <%= fetch(:user) %>
script
exec /bin/bash <<'EOT'
source /home/<%= fetch(:user) %>/.rvm/scripts/rvm
cd <%= current_path %>
bundle exec puma -e <%= fetch(:rails_env) %> --config <%= fetch(:puma_config)%>
EOT
end script
Associated recipe to allow the template to run is:
# lib/capistrano/tasks/puma.cap
namespace :puma do
desc "Setup Puma configuration and upstart script"
task :setup do
on roles(:app) do
execute :mkdir, "-p #{shared_path}/config"
# Upstart script for puma
template "puma_upstart.erb", "/tmp/puma_upstart", true
execute :sudo ,:chmod, "+x /tmp/puma_upstart"
execute :sudo, :mv, "/tmp/puma_upstart /etc/init/#{fetch(:app_env)}.conf"
end
end
end
def template(from, to, as_root = false)
template_path = File.expand_path("../../templates/#{from}", __FILE__)
template = ERB.new(File.new(template_path).read).result(binding)
upload! StringIO.new(template), to
execute :sudo, :chmod, "644 #{to}"
execute :sudo, :chown, "root:root #{to}" if as_root == true
end
Your recipes can be organized in capistrano’s folder this way:
You can find a complete working example here. To make it work you’ll need these prerequisites:
- Server with Ubuntu 12.04+
- Basic server configuration
- Ruby on Rails with RVM (ruby 2.1.1)
- Latest version on Nginx
- Monit
Clone my repository and change config/deploy/staging.rb
with your server parameter (remember that deployer user should be a sudoer). If everything is configured correclty you only have to create /var/apps
on your server and set deploy user as owner, you’ll therefore be able to run cap staging deploy
for your first deploy.
Run cap -vT
to check the list of all possible tasks 😉