Archive for the ‘Brightbox’ Category

Monday, April 28th, 2008

I’ve had this before so I should have learnt my lesson. But I didn’t.

I had a site, inherited from another developer, that was migrated to a new server.

The other developer sent me the images associated with the site and I dutifully copied them over. I took a look - lots of “missing image” place-holders, but as this was a work in progress, in a database of thousands of items, I didn’t know what should be there and shouldn’t.

So I asked the other developer to check things over.

No - there should be much more than that” he said.

But look - they are there - in the correct folder on the server!” I replied.

You’re right, ” he said, “but why aren’t they on the site?

It turns out that the code for deciding whether to show the product image or the place-holder looked something like this (with superfluous guff removed):

if File.exists?("#{RAILS_ROOT}/public#{product_image(img, true)}") 
  "<img src="http://blog.3hv.co.uk/wp-admin/#{product.image_filename}" />"
else
  "<img src="http://blog.3hv.co.uk/images/products/image_missing.jpg" />"
end

I spent a while playing around, using script/console on the server (a truly fantastic tool). I asked it to generate the image tag for a given product - it returned exactly what I was expecting. I looked at the equivalent page in the application - it returned the image missing place-holder. But mongrel was running as the same user as script/console - there couldn’t be a permissions issue could there?

Then I remembered …

  • on my dev box, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on my dev box, in mongrel, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in console and/or test suites, RAILS_ROOT returns an absolute path
  • on a typical Ubuntu server, in mongrel, RAILS_ROOT returns a relative path

That was the issue - the file system was getting confused as mongrel gave it a relative path for RAILS_ROOT (ignoring the fact that it should be able to resolve it, no matter how many double dots there were). And even worse, things appeared to be working fine until it was deployed to the webserver.

The fix is simple - add the following to your application controller:

helper_method :rails_root
def rails_root
  File.expand_path RAILS_ROOT
end 

and then replace all instances of RAILS_ROOT within your controllers, views and helpers with rails_root. Problem solved.

Saturday, March 22nd, 2008

Ruby on Rails deployment is often regarded as a dark art. But the guys at Brightbox have made it simple with their Brightbox gem. I have recently moved three clients over - so I’m getting pretty good at deploying there. Here are the steps that I follow:

One:

Sign up with Brightbox and buy a box. You will need to know the account name, the ‘rails’ user password and the mysql password - all of which are available from the VM details page that is emailed to you. The brightbox will be provisioned with a name similar to “account-001.vm.brightbox.net”. I recommend ssh’ing into the box and changing the ‘rails’ user’s password - you will be typing it a lot - or installing your ssh keys.

Two:

Prepare your application in subversion.

You need to make sure that your config/database.yml file is included in your subversion repository (many developers prefer to leave it out for team reasons - don’t worry, you can take it out again later).

You should edit the production entry to point at your desired production database. Set the database name to account_database (where account is your Brightbox account name and database is whatever you want), set the user to your account name, the password to whatever you noted down above and the hostname to sqlreadwrite.brightbox.net (the Brightbox MySql cluster).

Don’t forget to set the svn:ignore property on your log and tmp folders.

Three:

Install the Brightbox gem on your development machine.

Use the brightbox command to generate the Capistrano file (telling it your application name, the name of your Brightbox and the desired domain name that your application will be running on).

At the same time, point your domain name (via an A record) at the Brightbox’s IP address and place a support ticket to set up a Reverse DNS entry (if you will be sending out emails). If you don’t have a domain name yet then use myapp.account-001.vm.brightbox.net.

Then open config/deploy.rb and edit the source code repository entry to point at your svn server (if necessary setting up scm_username and scm_password entries).

Four:

Run the cap setup command (if you have capistrano 2 installed, this becomes cap _1.4.1_ setup as, at the time of writing, the cap 2 version of the gem is still in beta). This will ssh into your server (so you will need that password) and set up the folder structure for you.

Then run the cap cold_deploy command. This tests whether things are working - as it tries to get your code out of svn and onto the server, sets up monit (to keep tabs on your app), uses the database.yml file to create a database and configures Apache with your domain name. If it fails you will need to edit your deploy.rb (and probably get rid of the created database so you can run it again).

You should see your application at your domain name. Stop a second and reflect on how much you have achieved :-).

Five:

Remove your database.yml from svn (set the svn:ignore property on it). Then copy it to the Brightbox (using scp) and place it in /home/rails/my_app/shared/ (where my_app is obviously your application’s name). If you have any file uploads (attachment_fu) or shared assets then copy them into the shared folder as well. Then edit your deploy.rb to add something similar to the following:



task :after_update_code do

  # link the relevant database.yml from the shared folder to the app's folder

  run "ln -nfs #{deploy_to}/#{shared_dir}/database.yml #{release_path}/config/database.yml"

  # link the file store to the application

  run "ln -nfs #{deploy_to}/#{shared_dir}/files #{release_path}/public/public"

end

This means that, after deployment, capistrano will create symlinks from your shared database.yml and shared files into your applications config and public folders respectively.

Six:

Try another deployment to test your symlinking. cap _1.4.1_ deploy - if all goes well then your application should still be running at your domain name, and monit will report that your processes are running correctly. From now on, all you need to do is commit to svn and then cap _1.4.1_ deploy.