Capistrano series - configuring Capistrano #2

So now Capistrano has created the base structure for the application deployment, we need to look at actually deploying it.

Let's look at some of the settings we need for this and then deploy the application for the first time.


deploy.rb

So far, the deploy.rb file looks like this:

set :application, "domain.com"
set :user, "demo"
set :repository,  "svn+project1ssh://123.45.67.890/home/demo/repository/project1"

# 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/www/#{application}"

set :port, 30000

set :deploy_to, "/home/demo/public_html/#{application}"

# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion

role :app, application
role :web, application
role :db, application , :primary => true

Let's start by looking at how the deployment will be conducted and what we need to define for that deployment.

Subversion

We've already got subversion installed and configured on our local machine but what about the Slice?

On a default deployment, Capistrano will execute commands on the Slice and checks out the latest application version from the repository. However, we haven't setup the Slice to access the repository.

We also don't need to.

One of the problems with setting up the Slice to access the repository is that a private key will need to be placed on the Slice (if you want to have passwordless access).

This can be a security issue and the way I prefer to do it is to only allow the workstation to access the subversion repository.

This means that during a Capistrano deployment, the latest version will be checked out from the remote repository (to the workstation), compressed, sent via SSH to the Slice and then uncompressed.

This does mean it takes a few seconds longer to deploy an update but the increased security more than makes up for the slight delay.

Setting up Capistrano to use this deployment strategy is as simple as adding this to the deploy.rb file:

set :deploy_via, :copy

Mongrel user

An odd thing with the Capistrano script is that you will need to explicitly set the user that will start the mongrel instances.

If you don't set it, then the script will fail.

In this example, we'll use the same user as previously defined. You can, however, use another username if that fits better with your needs:

set :runner, user

deploy.rb

As we've added a couple of settings, let's have a reminder of what the deploy.rb file should look like:

set :application, "domain.com"
set :user, "demo"
set :repository,  "svn+project1ssh://123.45.67.890/home/demo/repository/project1"

# 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/www/#{application}"

set :port, 30000

set :deploy_to, "/home/demo/public_html/#{application}"

# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion

role :app, application
role :web, application
role :db, application , :primary => true

set :deploy_via, :copy

set :runner, user

Initial deployment

So far, we have nearly everything setup to deploy our application.

However, one final thing we need to sort out is to let it know how to start the mongrels on the initial deployment.

This is done via a 'spin' file in the script directory.

We can create that now (remember we are still on the workstation, not the Slice):

touch script/spin

This file will contain the commands that Capistrano will use to control the mongrels.

As the file needs to be executable, we can ensure it has the correct permissions by setting the property in subversion

svn propset svn:executable on script/spin

So what do we put in the file?

At the moment, we only need one line that relates to our mongrel usage:

/home/demo/public_html/domain.com/current/script/process/spawner -p 8000 -i 2 -e production

As you can see, this sets the path to the 'spawner' script (which has been created for us), the port to start the mongrels on (8000 in this case), the number of mongrels (2 in this example) and the Rails environment to use.

Commit

We've made a few changes that need to be added to the repository.

Make sure you 'add' the files to subversion first - you can check what files need adding like this:

svn status

If any need adding (such as the script/spin file) then add them like so:

svn add script/spin

Lastly commit the changes to the subversion respository:

svn commit -m "added script/spin"

Nearly there

Again, a lot is happening here but we are very close to deploying and serving our application.

We're going to deploy the application for the first time now but I give a word of warning:

The application will not show for the domain

Eek!

Why not?

Well, the simple fact is that we haven't created a vhost for the domain yet (sure, we created a test vhost when we installed Nginx but we don't have one for the soon-to-be deployed application).

However, there is nothing stopping us from deploying the application for the first time. That only leaves us with creating a vhost for the application which, if you are super keen, can be done by referring to the original Nginx vhost article (the next article will go through the exact settings that we need though).

Initial Deployment

Let's get on with it.

To deploy the application for the first time needs a simple:

cap deploy:cold

You will see quite a lot of information scroll by in your terminal.

Once done (and it should end with a section entitled " Starting mongrel dispatchers") have a look at what Capistrano actually did.

It did everything we expected in that it checked out the latest code from subversion and compressed it to a temporary file, uploaded it, uncompressed it and then went through a quite complicated procedure of copying the code and creating symlinks, etc.

Lastly, as already mentioned, it started the two mongrel instances as defined in the script/spin file.

Nice.

Summary

Although possibly a little frustrating that we have to configure a vhost for the application, remember that Capistrano is not designed (by default) to install and configure the web servers for us.

Capistrano allows us to use an existing setup to deploy and serve our application with a single command.

The next article will create and define a vhost file so we can then view and interact with the web application.

PickledOnion

Article Comments:

patrick commented Tue Jan 22 17:39:28 UTC 2008:

The SFTP upload was hanging for me. Adding the following line to my deploy.rb seemed fix the problem:

set :synchronous_connect, true

more info here: http://swik.net/Releases+Capistrano

Thanks again for these excellent articles.

PickledOnion commented Tue Jan 22 17:44:10 UTC 2008:

Patrick,

Thanks for the heads-up and link.

I didn't get that issue. I wonder if it is related to the OS of your workstation?

Anyway, thanks again. I am sure that will save a few people some frustration!

PickledOnion

Mike commented Fri Jan 25 17:14:24 UTC 2008:

Deploying from a Windows box, I had one snag. Make sure the spin script is saved in UNIX file format and not DOS. The latter will cause a parsing error when the mongrels try to start.

Great article.

PickledOnion commented Fri Jan 25 17:16:42 UTC 2008:

Mike,

Thanks for the note, I hope that helps other's using Windows as the workstation.

PickledOnion

Mike commented Fri Jan 25 17:22:56 UTC 2008:

One other comment for someone using Windows. The set :deploy_via, :copy relies on having tar installed. The cygwin version of tar works. The gnuwin32 version does not work because it doesn't implement the fork functionality.

Stagiros commented Sun Jan 27 12:50:47 UTC 2008:

I had the same problem with Patrick. I am running the exact same OS configuration on my machine and the slice (aka Ubuntu 7.10 Gutsy). Once I added the line "set :synchronous_connect, true" as Patrick suggested, everything worked correctly. If more people are getting the same behaviour from the system, I think that somebody should look seriously into that problem.

Otherwise a superb series of tutorials. Thank you!

Virginian commented Sat Feb 02 00:09:14 UTC 2008:

I had to manually run rake RAILS_ENV=production globalize:setup to get it to work.

How can i put this in my deploy.rb file?

Todd commented Thu Mar 13 13:39:49 UTC 2008:

what i have mutiple enviroments?

1 server is a svn server, 1 server is a 'staging' server (for beta deployments) and there's 1 more final server for production deployments...

PJ commented Tue Mar 18 11:17:59 UTC 2008:

For Windows users, how do you save the script/spin file in Unix format?

Kyle commented Thu Mar 20 22:02:15 UTC 2008:

Amen to the 'set :synchronous_connect, true' fix. Same thing here - Ubuntu 7.10 on workstation and slice. Maybe this should go into the main article text as a precaution.

Brian commented Tue Mar 25 18:40:56 UTC 2008:

Hey I just wanted to add that the "set :deploy_via, :copy" was taking too long for me. I have a relatively big project and the upload time is annoying.

I tried taking out the "set :deploy_via, :copy" and I got the following error:

** [err] svn: Undefined tunnel scheme 'project1ssh'

I found a way to get around it but not sure if this is right:

It was looking for "svn+project1ssh" tunnel on the slice as well.

Not only does the local machine need to be able to tunnel into the slice, the slice needs to be able to tunnel into itself (this seems really bizarre to me, but its the only way I got it to work).

We already added it to the local machine, but you need to add it to the slice as well. Add:

project1ssh = /usr/bin/ssh -p 30000 -l admin

In the tunnels section of: sudo nano ~/.subversion/config

Then you also need to make a private/public key pair so the command works on the server.

ssh-keygen -t rsa ... Go through the prompts and write down the pass phrase that you specify. cat ~/.ssh/idrsa.pub >> ~/.ssh/authorizedkeys

then try ssh'ing from the slice into the slice once to see if it works without passwords.

If anyone knows a better way please post it this seems very hackish.

michael commented Wed May 07 16:30:25 UTC 2008:

How do you set the permissions on spin if you are using git and not svn?

Daniel commented Sun Aug 24 04:20:03 UTC 2008:

Is anybody else having trouble with permissions when trying to cap deploy:cold?

I can run the cap deploy:setup ok, but when I run cap deploy:cold, cap can't create any of the directories, and I get a whole long list of failed attempts, for example:

* [err :: (my ip address)] tar: 20080824034850: Cannot mkdir: Permission denied

Maybe I messed something up earlier on in this process?

Thanks for any pointers. Excellent, excellent series of articles.

Braxo commented Fri Aug 29 18:46:24 UTC 2008:

@Daniel

I am also having the same issues. Capistrano is now at version 2.5.0 where this tutorial was written when it was 2.1.0. I wonder if that is causing us the grief?

Tom commented Mon Sep 01 07:18:31 UTC 2008:

I just configured this with 2.5.0.

In order it to work completely, you need to add trunk at the end of set :repository, "svn+project1ssh://123.45.67.890/home/demo/repository/project1"

so it'll be set :repository, "svn+project1ssh://123.45.67.890/home/demo/repository/project1/trunk"

Also.. Braxo and Daniel, you need to set the permissions for demo or whatever account. Refer to Pickel's guide on Permissions for Vhosts, I believe it is under apache.

You need to be able to write to the folder. For instance, the reason you are getting is this is because if you were to log in with demo, and try mkdir test, in the folder capi is suppose to deploy to, it won't work. You need proper permissions.

Pickel should update the article to reflect that.

Firefly commented Wed Sep 03 07:41:56 UTC 2008:

Daniel, Braxo, I also had problem with permission.

This is what I did.

  1. Login to slice
  2. sudo chown myuser /home/www/project_path -R

This will give the user ownership to directory.

Hope it helps.

VJ commented Wed Sep 03 14:40:57 UTC 2008:

@brian,

I had the same issue like yours. I didn't want to use deploy_via copy.

Like you, I had to add private/public key pair, but i didn't have to modify subversion config with "sudo nano ~/.subversion/config". Which is one step less.

At first i also encountered error, but I tried to do check out manually at slice. The system prompted to authorized the computer, afterwards, I can already do the cap deploy:cold.

svn checkout -q -r12 svn+ssh://server.example.com/home/repo/project1 /home/www/example.com/releases/20080903142954

@all, I had problem with the syntax svn+project1ssh, so I only use svn+ssh. Works well for me.

vidar commented Mon Sep 08 19:48:02 UTC 2008:

@all, just set

set :use_sudo, false

and

set :chmod755, "app config db lib public vendor script script/* public/disp*"

That should take care of any permission rights.

maryrosecook commented Tue Oct 14 21:03:55 UTC 2008:

@michael Took me a little while to figure this too. git is actually sensible in that it uses the real permissions on the real file.

Thus, all you have to do is use chmod on script/spin

Dave commented Wed Nov 12 22:34:11 UTC 2008:

@Daniel there is another article under Apace on vhost permissions that should help http://articles.slicehost.com/2007/9/18/apache-virtual-hosts-permissions

gregory commented Mon Mar 02 23:14:26 UTC 2009:

As of 2.3, rails no longer includes a process folder or process scripts. This means no spawner script and I'm currently dead in the water for following this (otherwise fantastic) tutorial. Apparently they were "unnecessary baggage" and we're supposed to be using something called Passenger?

http://weblog.rubyonrails.org/2008/12/5/this-week-in-edge-rails

pat commented Tue Mar 31 07:48:08 UTC 2009:

Everything worked during deployment and I didn't get any error messages. However, I don't see my rails app. All I see is a page that says "welcome to nginx". Does anybody know what this is symptomatic of?

Thanks!

Kenny commented Wed Apr 08 02:29:21 UTC 2009:

Thanks to Firefly for saving my butt. That ownership issue was driving me insane. Works fine now.

vidar, I tried your fix and couldn't get it to work for some reason. No clue why. Probably my fault.

Mike commented Wed May 20 00:16:04 UTC 2009:

I'm hosed. I have to say that the rest of the setup tutorials are fantastic, but I'm disappointed with the organization of the Cap tutorials. There's not mention of the server configuration, as far as I can tell, until you're too far down the line to recover. I've followed the Apache & Passenger setup, but this cap setup then takes a turn for Apache:Mongrel. There's nothing in the titles that indicate this, as far as I can tell. I've looked in vain for an organizing principal behind these.

Enough griping and on to my error. I get tons of 'Cannot mkdir: No such file or directory" errors. I used my IP address for the :application variable, skipped the Mongrel section, but did everything else identically to the tutorial. Any ideas?

Again, the previous tutorials were excellent. I'm just disappointed with the (lack of) organization and lack of detail of the Capistrano section. (For example, when do I 'rake db:create' on the Slice, if ever?)

My frustration is showing through, above. I should end by repeating that I've found the rest of the content on this site remarkably good.

PickledOnion commented Thu May 21 13:25:41 UTC 2009:

Hi Mike,

The list of applications used (nginx/mongrel, etc) are laid out in detail on the very first article which explains what this series is and what we will be working with and what the end result is intended to be:

Capistrano Series Introduction

Hope that helps.

gman commented Fri Feb 05 15:26:38 UTC 2010:

Brian, you are the man - i was getting sooo tired of using :copy in my cap recipe and now my :remotecache option works a treat, about 10 times faster at least. the only difference on my slice was that the keygen created idrsa.pub (i.e. with an underscore) in case anyone else just copies your text without looking! by then connecting with ssh on the slice itself (like you would on your local machine), it adds the RSA to the list of known hosts on the server permanently - a necessary step if you want the cap deploy to work from local. thanks for saving me a headache.

James Black commented Mon Jun 21 06:17:47 UTC 2010:

I ran into a couple of issues with this article, most were because of the different setup I was using. Namely, I am running Thin so there were some changes to be made on the deploy.rb, but nothing major. First issue I had was when I ran cap deploy:setup, I got the following error:

no tty present and no askpass program specified

I found the solution was to put the following line in my ~/.caprc (or config/deploy.rb) file:

default_run_options[:pty] = true

Simple enough, the next part was to add support for thin in the config/deploy.rb file with the following lines:

namespace :deploy do %w(start stop restart).each do |action| desc "#{action} the Thin processes" task action.to_sym do find_and_execute_task("thin:#{action}") end end end namespace :thin do %w(start stop restart).each do |action| desc "#{action} the app's Thin Cluster" task action.to_sym, :roles => :app do run "/etc/init.d/thin #{action}" end end end

This seems to work based on the nginx/thin article, and of course the domain.com configuration file in sites-available needs to be modified/created for the new file locations, but that part is already covered.

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)