Configuring Your Rails Stack, and Capistrano!

Posted by glenn gillen on Friday, August 31, 2007

Posted in ruby on rails, apache, mod proxy, mod proxy balancer, mysql, postgres, configuration, capistrano, deployment, installation


So you’ve done all the hard work. You’ve got a web server (Apache) complete with a reverse proxy balancer (mod_proxy), to serve requests to your rails back end (mongrel), that is going to hit a database (MySQL or Postgres) to generate pages for your users. You’ve even gone to the trouble of managing versions of your source code with Subversion. You know the site works on your local development machine, now it’s time to link all the pieces together up on the server and make it public.

First things first, lets make our lives even easy going forward by setting up capistrano to manage deploying our site, database, and any other associated tasks required on the remote server. No more SSH (well… almost), no more FTP, yay! Get the latest from the gem repository, on your local machine type:


sudo gem install capistrano -y

Now you need to go to the root directory of your rails application and type:


capify .

This will create the Capify and config/deploy.rb files that capistrano will read for your deployment tasks. Open up the config/deploy.rb file and edit the default entries to match what you have setup for your application and server, then paste the following tasks at the bottom (thanks to Shane and Pat Nakajima for some of the original code)


require 'rubygems'
require 'erb'
require 'bells/recipes/apache'

set :user, "deploy" 
set :group, "deploy" 
set :db_user, "app_user" 
set :db_pass, "password" 

# =============================================================
# Apache Settings
# =============================================================
set :apache_server_name, nil
set :apache_conf_path, "/usr/local/apache2/conf/sites" 
set :apache_conf_file, "#{application}.conf" 
set :apache_ctl, "/usr/local/apache2/bin/apachectl" 
set :apache_server_aliases, []
# set :apache_ssl_enabled, false
# set :apache_ssl_ip, nil
# set :apache_ssl_forward_all, false
# set :apache_ssl_chainfile, false

# In the event you have the urge to develop your own vhost erb template, you can modify
# this variable. I wouldn't do it unless you're strongly confident in what you're doing.
set :apache_conf_template, 'http://footodo.com/open/tools/recipe/templates/vhost.conf'

before "deploy:setup", :db
after "deploy:update_code", "db:symlink" 
after "deploy:setup", "db:create" 

namespace :db do
  desc "Create database yaml in shared path" 
  task :default do
    db_config = ERB.new <<-EOF
    base: &base
      adapter: mysql
      socket: /var/lib/mysql/mysql.sock
      username: #{db_user}
      password: #{db_pass}

    production:
      database: #{application}_production
      <<: *base
    EOF

    run "mkdir -p #{shared_path}/config" 
    put db_config.result, "#{shared_path}/config/database.yml" 
  end

  desc "Make symlink for database yaml" 
  task :symlink do
    run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml" 
  end
end

# Making sure things will go smoothly.
depend :remote, :directory, apache_conf_path
depend :remote, :directory, deploy_to
depend :local, :gem, 'bells'

namespace :deploy do
  namespace :apache do
    desc "Setup vhost conf on Apache web server." 
    task :setup do
      sudo "mkdir -p #{apache_conf_path}" 
      sudo "chown -R #{user}:#{group} #{apache_conf_path} && chmod -R 775 #{apache_conf_path}" 
      logger.info "generating .conf file" 
      conf = Net::HTTP.get URI.parse(apache_conf_template)
      require 'erb'
      result = ERB.new(conf).result(binding)
      logger.info "putting #{application}.conf on #{domain}" 
      put result, "#{application}.conf" 
      run "mv #{application}.conf #{apache_conf_path}/#{apache_conf_file}" 
    end
  end

  # Overwritten to provide flexibility for people who aren't using Rails.
  task :setup, :except => { :no_release => true } do
    dirs = [deploy_to, releases_path, shared_path]
    dirs += %w(system).map { |d| File.join(shared_path, d) }
    run "umask 02 && mkdir -p #{dirs.join(' ')}" 
  end

  # Also overwritten to remove Rails-specific code.
  task :finalize_update, :except => { :no_release => true } do
    run "chmod -R g+w #{release_path}" 
  end
end

And one last thing before I get into explaining what everything there does:


sudo gem install bells -y

Okay, so working backwards. The Bells gem is an add on for capistrano that takes care of certain tasks for us, such as restarting apache (I’ll likely change this in an upcoming post but if you’re following along in real time lets stick with how it is).

Our additions to the capistrano file provide us some methods to restart apache, create a new database.yml on the server and place it in shares/config/ so we don’t have to worry about other developers changing the config locally and breaking everything on deployment, and wrap the db:setup task with the extra features we’ve added. You may need to make sure that the paths to your application and the MySQL sock file are correct. Then save the files and ensure you’ve committed everything back into subversion. Now we can create the DB on the remote server:


cap db:setup

Bookmark

Add to: Digg Add to: Del.icio.us Add to: Reddit Add to: StumbleUpon Add to: Slashdot Add to: Yahoo Add to: Google Add to: Blogmarks Add to: Technorati Add to: Newsvine Add to: Netvouz
blog comments powered by Disqus