SSH Key Generation with Capistrano and Ruby

Posted by Daniel on 10/05/2009

Adding SSH Keys with a custom Capistrano Recipe

Capistrano is great for deploying applications, but the ability to write custom recipes makes it a valuable tool. I've found that every time I deploy a new Linux box, setting up SSH keys to avoid password prompts makes things easier. I am lazy, and can't ever remember the commands to execute this though, so I created a custom recipe to handle it for me every time.

Here is my custom capfile

##Run using cap SSH###

set(:remoteHost) do
 Capistrano::CLI.ui.ask "Hostname or IP address of remote server: "
end

set(:username) do
 Capistrano::CLI.ui.ask "Username for SSH: "
end

namespace :SSH do
   
   task :default do
      keygen
   end
   
   desc "Check for existance of a public key, otherwise generate it. Then trigger sendFile"
   task :keygen do
      relative = File.expand_path("~")
      if !File.exist?(relative + '/.ssh/id_rsa.pub')
         system "ssh-keygen -t rsa"
      end
      sendFile
   end
   
   desc "Send the id_rsa.pub file from the local machine to the remote machine's home dir, then trigger checkDirectory"
   task :sendFile do
      system "scp ~/.ssh/id_rsa.pub #{username}@#{remoteHost}:~/id_rsa.pub"
      checkDirectory
   end
   
   desc "Check for existance of .ssh directory. If true, goes to checkFile, if false goto createDirectories"
   task :checkDirectory, :hosts => "#{username}@#{remoteHost}" do
      begin
         run "ls -a ~/.ssh"
      rescue Exception
          createDirectories
      else
          checkFile
      end
      
   end
   
   desc "Check for existance of .ssh/authorized_keys, goto createKeys if false, goto appendKeys if true"
   task :checkFile, :hosts => "#{username}@#{remoteHost}" do
      begin
         run "ls -a ~/.ssh/authorized_keys"
      rescue Exception
          createKeys
      else
         appendKeys
      end
   end
   
   desc "Append the new key to the already existing public key file"
   task :appendKeys, :hosts => "#{username}@#{remoteHost}" do
      run "cat ~/id_rsa.pub >> ~/.ssh/authorized_keys"
      run "rm ~/id_rsa.pub"
   end
   
   desc "Create the .ssh directory, trigger createKeys"
   task :createDirectories, :hosts => "#{username}@#{remoteHost}" do
      run "mkdir ~/.ssh/"
      createKeys
   end
   
   desc "Move the new ky into the authorized_keys file because it doesn't exist, triggers setPermissions"
   task :createKeys, :hosts => "#{username}@#{remoteHost}" do
      run "mv ~/id_rsa.pub ~/.ssh/authorized_keys"
   end
   
   desc "set the correct premissions on the .ssh dir and the authorized_keys file"
   task :setPermissions, :hosts => "#{username}@#{remoteHost}" do
      sudo "chown -R #{username}:#{username} ~/.ssh"
      run "chmod 700 ~/.ssh"
      run "chmod 600 ~/.ssh/authorized_keys"
   end
end   

And the result of running the "cap SSH" command from your home directory

dwestendorf@HLY24411VM2:~$ cap SSH
Username for SSH: dwestendorf
Hostname or IP address of remote server: mynewserver
  * executing `SSH'
  * executing `SSH:keygen'
Generating public/private rsa key pair.
Enter file in which to save the key (/home/dwestendorf/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/dwestendorf/.ssh/id_rsa.
Your public key has been saved in /home/dwestendorf/.ssh/id_rsa.pub.
The key fingerprint is:
58:55:5c:b5:03:90:65:00:94:11:9a:42:5b:71:0e:c8 dwestendorf@HLY24411VM2
The key's randomart image is:
+--[ RSA 2048]----+
|    ...+o**=*=...|
|    .Eo *o .o . .|
|     o o..     o |
|      .o        .|
|      . S  !     |
|   . .   .       |
|                 |
|                 |
|                 |
+-----------------+
  * executing `SSH:sendFile'
The authenticity of host 'mynewserver (192.168.1.100)' can't be established.
RSA key fingerprint is 11:88:b8:3i:a2:ca:06:c4:u5:3a:bb:e0:6d:6c:bf:l2.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'mynewserver' (RSA) to the list of known hosts.
dwestendorf@mynewserver's password: 
id_rsa.pub                                    100%  405     0.4KB/s   00:00    
  * executing `SSH:checkDirectory'
  * executing "ls -a ~/.ssh"
    servers: ["mynewserver"]
Password: 
    [dwestendorf@mynewserver] executing command
 ** [out :: dwestendorf@mynewserver] .
 ** [out :: dwestendorf@mynewserver] ..
 ** [out :: dwestendorf@mynewserver] authorized_keys
    command finished
  * executing `SSH:checkFile'
  * executing "ls -a ~/.ssh/authorized_keys"
    servers: ["mynewserver"]
    [dwestendorf@mynewserver] executing command
 ** [out :: dwestendorf@mynewserver] /home/dwestendorf/.ssh/authorized_keys
    command finished
  * executing `SSH:appendKeys'
  * executing "cat ~/id_rsa.pub >> ~/.ssh/authorized_keys"
    servers: ["mynewserver"]
    [dwestendorf@mynewserver] executing command
    command finished
  * executing "rm ~/id_rsa.pub"
    servers: ["mynewserver"]
    [dwestendorf@mynewserver] executing command
    command finished
dwestendorf@HLY24411VM2:~$ ssh mynewserver
Last login: Mon Oct  5 10:24:51 2009 from 192.168.1.102
[dwestendorf@mynewserver ~]$ exit
logout

Connection to mynewserver closed.

Comments.

No comments yet.

Name: (required)

Email: (not shown or published)

Website Url:


(Use Markdown Syntax, <pre> your code </pre>)