I have taken the plunge and got my hands dirty with rails in a shared hosting environment recently. I chose Site5 because they had a good deal on at the time, I think no more than $140 for 2 years. They are slower than my previous host, 4uhosting, perhaps because I am in the UK, but more likely because Site5 put both CPU and burst bandwidth caps on shared accounts, as most big hosting setups do. Anyway, in this article, I will explain how I got my ssh – svn – rails – capistrano setup going, with the help of a few tips from elsewhere in the ether.

Your Machine

First of all, this post on the Site5 forums was a help, if a little out of date in places. I aim to fill in some of the gaps and share my experiences in following the same rough plan. Ok let’s get started. If you haven’t already Step 0 is to get Ruby and Rails up and running on your own development machine. This is not something I will go into, as it is well documented – I’m on a Mac and this walkthrough, "Building
Ruby, Rails, LightTPD, and MySQL on Tiger;quot;
, was straightforward. However you do it, make sure you have mysql, ruby, rails, activerecord etc installed and understand how they all work together before you continue. If you creating a new rails project ‘rails projectname’ MAKE SURE YOU USE THE SAME VERSION AS YOUR HOST (Site5 currently has Rails 1.1.6 installed)! It’s not fun troubleshooting your code trying to work with two different versions of rails.

Next, you will want SVN installed on your machine. If you don’t know why, or think don’t think it’s worth the effort, then head to Wikipedia – Subversion or do some reading around so you understand the basics. Subversion helps you to manage your workcycle and takes a lot of pain out of version control. The best getting started guide for SVN I’ve found is at Circle Six. Get SVN working, and if you are new to it, try creating a test repository, checking out a version and committing changes.

SSH Public / Private Keys

It is very handy to have a public/private key pair set on your shared hosting account/local account respectively so you don’t have to keep typing your password when you perform actions with svn and later capistrano. It also saves time when you need to SSH into your hosting account. You will need SSH access enabled first though, and with Site5 you can do that yourself by going to ‘Advanced Tools’ in Site Admin page, and clicking ‘Get Shell Access’. Mine was enabled by default, but it was not a bash shell, which we need. After sending a ticket requesting bash, I was told simply to disable and re-enable it to enable bash. Excellent. If your host doesn’t have a control to do this, request that ssh and bash be enabled for you.

Now we can create an ssh public/private key pair to enable passwordless ssh entry to your hosting account (the private key is associated with your specific login on your own machine, so unless you are worried about who has access to your own user account on your computer then you can simply see this as a simple and secure timesaver). If you are running ‘unix you will have ssh installed by default. Open a new local command line and run these commands to create a .ssh folder and the key pair (here we are using rsa encryption, you can use dsa if you wish). Note mkdir will fail if there is already a directory by that name present, in which case just skip that command: cd ~
mkdir .ssh
cd .ssh
ssh-keygen -t rsa

Now name the key ‘id_rsa’. You don’t need a passphrase so just hit return twice. Next we make sure the permissions are correct on the private key, and upload the public key to your hosting account using the ‘scp’ command – the trailing colon ‘:’ is important.
cd ..
chmod 600 .ssh/id_rsa
scp .ssh/id_rsa.pub username@server.address:

Next ssh normally into your account (it will ask for your password), create a .ssh directory if needed, and append the public key value to authorized_keys. Finally, delete the now redundant .pub file, and set the correct permissions for the .ssh directory:
ssh username@server.address
cd ~
mkdir .ssh
cat id_rsa.pub >> .ssh/authorized_keys
rm id_rsa.pub
chmod 700 .ssh

Finally, you should be able to log out and log back into your remote server without typing a password – Oh the joys!
logout
ssh username@server.address
$ "Last Login...etc..." but NO password prompt!

Finally create a PRIVATE key on your remote server too. This is to allow Capistrano to use SVN without you having to type your password, in what would be, annoyingly, clear text. Preventing svn asking for a password during Capistrano operations when using svn+ssh:// took me a long time to figure out. If we were using http:// or file:/// we could use svn’s password caching to fix the problem, but since we are using ssh and we need to allow capistrano running on the server to authenticate using ssh, and its own public/private key pair. Creating them is much the same as with your local machine, but without the need to ‘scp’ it up. I actually just copied my local private key to the .ssh directory but this is not advisable so instead, ssh into your server and:
cd ~/.ssh
ssh-keygen -t rsa
<id_rsa>
chmod 600 id_rsa
cat id_rsa.pub >> authorized_keys
rm id_rsa.pub

SVN

Now let’s set up SVN on the remote server. First, if you haven’t already, create your rails application template somewhere on the server, or upload it if you have been working locally already. SSH into your server if you haven’t already and create the main repository. This will be the repository for your web application. As suggested on the Site5 forum, I just created mine in ~/repos:

ssh username@server.address
cd ~
svnadmin create repos

Import your rails app into your repository. The file path should be from the root of your shared hosting server. For Site5 (and the default Linux setup) it is /home/username/. The ‘trunk’ at the end of the repository path is important for later setup, and as good SVN practice.

svn import /home/username/path_to_rails_app file:///home/username/repos/rails_app_name/trunk -m "Initial Import"

You should now see the console happily list all the files being added to the repository. The structure you just imported is now stored in the database, ready for checkout. Personally, since you probably have imported a fresh template, I see no need to keep the original files, do I deleted them, but you may wish to move them to a backup folder. Those files will NOT be used again by SVN now they have been imported. We will use a working copy – so check one out. I stored mine in ~/rails.

svn checkout file:///home/username/repos/rails_app_name/trunk ~/rails/rails_app_name

Excellent. Now you should be able to check out a working copy for your local machine. Open a new prompt in your machine and:

cd ~
svn checkout svn+ssh://username@server.address/home/username/repos/rails_app_name/trunk path_for_local_rails_app

Note we are using the svnserve path here, NOT an http path. This uses ssh for svn authentication and your password is not cached. We will return to svn+ssh in the Capistrano setup.

Now, this last step is optional and described in the Circle Six article. Obviously you will be making changes to your local copy and committing them to write the changes to remote repository. Incidentally you should try this to make sure it is working. Change some files on your local copy and from your local machine: cd /path_for_local_rails_app/
svn commit -m 'testing local changes'

You should see ‘Sending file whatever_you_changed’ then ‘Committed revision X’. But these changes are NOT yet echoed to the working copy you checked out on the remote server. The latest version is only updated in the repository. You can automate the updating of the working copy on your SERVER by adding a simple hook to the commit action in the repository. Use an ftp client (or a command line editor if you are familiar with one) and on the server head to ~/repos/hooks. Remove the ‘.tmpl’ extension from the ‘post-commit.tmpl’ file and add the following to the bottom (comment out everything else unless you want it):
svn up /home/username/path_to_rails_app
This will automatically ‘version up’ your remote working copy as soon as the changes you have made locally have been committed to the repository. Great!

Capistrano

Capistrano is an automation tool, which facilitates speedy deployment by automating, among other things:

  • Database Migrations
  • Application and Database Server distribution
  • Server restarts
  • SVN updates and rollbacks

Even if you don’t yet see the need for Capistrano, you should become familiar with it if you intend to build more complex or higher load applications in the future. First apply the Capistrano magic to your rails app (creates 2 files to get you started with a few rails tasks and recipies). You can do this locally then ‘SVN’ the new files and the changes you make to them to your remote server later.
cd /path_to_local_rails_app/
cap --apply-to ./

The next part is often glossed over a bit, but if you are new to Capistrano, it can be a little tricky, especially if your setup is not the default. Capistrano needs some variables to be set properly before it will work. Open your newly created rails_app/config/deploy.rb file and set the variables to look something like this:

set :application, "rails_app_name"
set :repository, "svn+ssh://username@server.address/home/username/repos/#{application}/trunk"

role :web, "electronicholas.com"
role :app, "electronicholas.com"
role :db, "electronicholas.com", :primary => true

#assuming your remote application is in ~/rails/
set :deploy_to, "/home/username/rails/#{application}"
set :user, "username"

#remember the ssh keys we created earlier - enter the full path to each from the machine roots
ssh_options[:keys] = %w(/Users/local_user/.ssh/id_rsa /home/username/.ssh/id_rsa)
ssh_options[:host_key] = 'ssh-rsa'
ssh_options[:paranoid] = false
ssh_options[:username] = 'username'

And towards the bottom of the deploy.rb file, there is a ‘restart’ task definition. This won’t do much on Site5, but I’ve found this works great:
desc "Restart the web server by killing your fgci instance, forcing it restart upon the next request."
task :restart, :roles => :app do
run "pkill -9 -u electron -f dispatch.fcgi"
end

Excellent. Now you are ready to set up capistrano and use it as you wish, free from SVN password worries and with SSH security. First, though, make sure you commit these changes you’ve made to this local copy of your app to the remote version. To set up the standard deployment file structure you can now, from your local machine, run the following commands. Be sure you understand what they do beforehand though.
cd path_to_local_rails_app
cap setup

And to deploy:
cap deploy

One last thing…

Make sure you amend your rails application’s root .htaccess file to tell the server to use FastGCI. I was tearing my hair out for weeks with the slowness of it all, until I realised I had not configured it correctly (I thought I had). It’s just a case of adding an ‘f’ to the end of dispatch.cgi on top of what’s already there:
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

Enjoy :-)

Leave a Reply...