Trace Data

Ramblings on devops, data, games, programming, and more

Automating SSH Key Deployment With Capistrano

| Comments

I’ve been playing with capistrano at work recently both as a convenient ad-hoc method of running arbitrary or pre-defined commands on our farms and possibly as an addition or replacement to deployments that we largely manage with Chef Solo right now.

For some legacy reasons that are changing, SSH keys have been somewhat taboo until recently so none were set up on any of our machines. Between our numerous dev, test, and production servers, we manage over a hundred VMs. Manually setting up keys struck me as time-consuming, boring, and an ideal candidate for some basic automation.

Our current Chef usage is a little weird and needs some rethinking so I decided to see what could be done with Capistrano. Here’s the task I whipped up to copy keys around.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    desc "Add a public key to the remote machine"
    task :copykey do

      keyfile = ENV['KEY']

      # make user provided a proper key (exists and is .pub)
      unless keyfile
        abort "Provide a keyfile: KEY=~/.ssh/id_rsa.pub cap copykey"
      end
      unless keyfile.end_with?(".pub")
        abort "Keyfile must end in .pub"
      end
      unless File.exist?(keyfile)
        abort "Missing key file at #{keyfile}"
      end

      # put the pub key on the server
      remotefile = "cap-key-tmp.pub"
      put File.new(keyfile).read, remotefile, :mode => 0600

      # make sure .ssh/ exists, add the key if it's not already there, clean up
      run <<-EOC
        mkdir -p -m 700 .ssh;
        if ! grep -f #{remotefile} .ssh/authorized_keys;
        then
          cat #{remotefile} >> .ssh/authorized_keys;
        fi;
        chmod 600 .ssh/authorized_keys;
        rm #{remotefile};
      EOC

    end

Comments