How to setup a password-less “cap deploy” with Capistrano

The situation
You want to type “cap deploy” without having to enter your ssh password every time

The background
You have configured your server to allow public key authentications over ssh and have given the proper permissions to the resulting files & folders (how to do this). Oh and the repository as well as your application is located in the same server.

The problem
Capistrano still asks for your password at one time in the deployment procedure!

Why Does this happens?
Once you typed cap deploy and the ssh session is established, the remote server will do a checkout (or clone, or whatever) at some point to fetch the latest revision from your repository. It will do this by using your capistrano :repository variable that probably looks like “ssh://me@blablabla.com/home/user/repositories/myapp”. The “problem” (which is not really a problem) is on your remote server only… it has nothing to do with your public key authentication setup or your local machine. If you want to reproduce the problem, log into your ssh server and do the same checkout/clone operation that capistrano is trying to do. It should asks for a password. Why? Because you do the checkout with an “external url scheme”. So even if the repository url is pointing to the very same server that does the request, it still needs a password.

Solution
Checkout/Clone your repository with a physical path.

And that’s it!

At first you might think that it should be the other way around. Wouldn’t it make more sense if the :repository variable was set to a “ssh://” path and local_repository to a “local” path?

Well, yes. But for capistrano it means : “When I’m on your local workstation, I will use :local_repository to access your repository. And when I’m connected on the remote server, I will use :repository”

Encryption with Alphanumeric output

What if you want to generate reasonably short alphanumeric user activation codes without having to store anything in a DB (so in this case generating random user codes won’t do) ? Why would someone need this? Think about an application where you want to print activation cards and sell them to your customers. The customer then login to your website, put the activation code that is printed on its card… and bingo : they are activated.

So, how to do this? With encryption, of course.

The thing is that most encryption algorithms will generate ciphers with non-friendly characters, like : Òèç`{&[ùỲgǛ... so bad for readability. It seems complicated at first but finally one solution turns out to be fairly simple :

Step #1

Step #2

Step #3

The Blowfish algorithm takes 8-bytes blocks only… so you have to take that into account when you generate your keys. The unpack(“H*) and pack(“H*”) parts are the most important. It simply encodes/decodes the block in hexadecimal. So, here we are, you have a readable & decryptable 16-chars cipher that looks like : 9048bb8f56eddd47. You can even display the codes into chunks of 4 characters and it gives you the following friendly code : 9048-bb8f-56ed-dd47

Tip: Associate to each code a SHA-1 hashed password (which is the result of activation code + some salt) and you have a pretty safe account activation procedure that doesn’t pollute your database.

Last deployment date with Rails and Capistrano

When you are developing an app or a website for your client, it is pretty common to setup a sandbox environment where your client can test and see the application while it is still in development. One thing I find useful is to display the last deployment date on the home page.

Here is a quick and easy way to automate the process :

Step #1 (we can have lots of fun)
I will consider that you use capistrano for deploying your app. The only thing you have to do in your capistrano recipe is to “touch” a dummy file to update its modification date.

Step #2 (there’s so much we can do)
Now in application_controller, add a before_filter like this

Step #3 (it’s just you and me)
Display the date in the layout or in the view of your choice

Edit : Oh, dear readers, I just want to let you know that RubyFleebie is now on Twitter.