On the Rails: Capify and Deploy!
Ready to get our app onto that Rackspace Cloud Server? Me too; let’s do it!
Install
First, on our Mac, we need to install Capistrano, which will deploy our app for us once we have it set up. It’s a Ruby gem. Do the following to get it:
sudo gem sources -a http://gems.github.com/ sudo gem install capistrano
Capify
Now, let’s run these commands from our home directory:
cd workspace/railstest capify .
Capistrano will add two files to our app, Capfile and config/deploy.rb. Let’s edit config/deploy.rb:
pico config/deploy.rb
Here is one place we can look for help in figuring out what to put in this file so that Capistrano will know where and how to deploy our app.
Below is what our config/deploy.rb file ends up looking like:
set :application, "railstest"
set :repository, "git@github.com:your_github_username/railstest.git"
# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/local/#{application}"
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
set :scm, :git
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
set :deploy_via, :remote_cache
set :branch, "master"
set :passenger_conf, true
set :user, "app" # Login as?
set :runner, "app" # Run ./script as?
set :use_sudo, false
set :domain, "rails.example.com"
role :web, domain # Your HTTP server, Apache/etc
role :app, domain # This may be the same as your `Web` server
role :db, domain, :primary => true # This is where Rails migrations will run
#role :db, "your slave db-server here"
set :rails_env, "production"
# If you are using Passenger mod_rails uncomment this:
# if you're still using the script/reapear helper you will need
# these http://github.com/rails/irs_process_scripts
namespace :deploy do
task :start do ; end
task :stop do ; end
task :restart, :roles => :app, :except => { :no_release => true } do
run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
end
end
Deploy
Now, we’re ready to run “cap” and actually do some things.
Let’s follow some steps in the handy guide referenced above:
cap deploy:setup cap deploy:check cap deploy:update
Note: The “update” task failed for me the first time I tried it, and I think the “Known Hosts List” section at the bottom of this page explains why. I solved the problem by SSHing into the server and doing the following:
su app git ls-remote git@github.com:your_github_username/railstest.git master
You should see something like:
The authenticity of host 'github.com (207.97.227.239)' can't be established. RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. Are you sure you want to continue connecting (yes/no)?
Type “yes”, and press Enter, and you should see something like:
Warning: Permanently added 'github.com,207.97.227.239' (RSA) to the list of known hosts. 502d44c77a98c812eff27e97d542f47ed891fad1 refs/heads/master
I tried “cap deploy:update” again from my Mac and it succeeded.
OK, let’s continue. We’re already on the server, in a shell as the “app” user, so let’s try this:
cd /var/local/railstest/current rake RAILS_ENV=production db:schema:load
Note: This one didn’t work for me at first either. I found an explanation here, which jibes with what the PostgreSQL manual says. Evidently, the default is for postgresql to only allow UNIX socket connections as a database user with the same name as the operating system user. In our case, we’re running rake as “app”, and rake is trying to connect to postgresql as “railstest”, which isn’t going to work under the default setup. So, let’s change the setup. Type “exit” to get back to your root shell. As root, do this:
pico /etc/postgresql/8.3/main/pg_hba.conf
Comment out the line that says:
local all all ident sameuser
and add a line right below it that says:
local all all trust
Then, run:
sudo su postgres -c "/usr/lib/postgresql/8.3/bin/pg_ctl reload -D /var/lib/postgresql/8.3/main"
to have postgresql reload the config file we just edited. Now, let’s try this step again:
su app cd /var/local/railstest/current rake RAILS_ENV=production db:schema:load
It works! Next, do:
./script/console production
app.get("/")
I got a 404 from this, which apparently isn’t a bad thing in our case, because we haven’t configured our app to return anything from that location in production mode.
Next, opening up a web browser on your Mac and browsing to:
http://rails.example.com/javascripts/prototype.js
should return what you would expect.
So, now that we’ve checked every step of the process, let’s run the whole she-bang. In your Mac Terminal, do:
cap deploy
If it works, then we are now at the moment of truth. In our web browser, let’s browse to:
http://rails.example.com/books
Our app should come up! Success! We’re done! WOO-HOO!!!
Conclusion
Thanks for joining me on this journey (if there’s been anyone out there reading this). It’s actually been quite a ride for me, a PHP/MySQL monkey by trade. I hope you’ve had as much fun learning about this stuff as I have. No doubt there’s a better way to do some of the things described in this series. I’ll probably update some of what I’ve written with better methods in future posts. And I’m sure there will be plenty of all-new adventures “On the Rails” in the future. If you have something to share, please feel free to drop me a line. Thanks again, and see you down the road!