7

I'm having loads of trouble getting my Chef recipe to clone a private repo. Well, I had it working yesterday but after 'cheffin' my Vagrant box half a dozen times, I've broken it. I'm a Chef newbie as you may guess.

Following the deploy_resource guide here, I've created my deploy.rb recipe (shortened):

deploy_branch "/var/www/html/ps" do
  repo              git@github.com:simonmorley/private-v2.git
  ssh_wrapper       "/tmp/.ssh/chef_ssh_deploy_wrapper.sh"
  branch            "rails4"
  migrate           false
  environment       "RAILS_ENV" => node[:ps][:rails_env] 
  purge_before_symlink %w{conf data log tmp public/system public/assets}
  create_dirs_before_symlink []
  symlinks(                        # the arrow is sort of reversed:
    "conf"   => "conf",            # current/conf          -> shared/conf
    "data"   => "data",            # current/data          -> shared/data
    "log"    => "log",             # current/log           -> shared/log
    "tmp"    => "tmp",             # current/tmp           -> shared/tmp
    "system" => "public/system",   # current/public/system -> shared/system
    "assets" => "public/assets"    # current/public/assets -> shared/assets
  )
  scm_provider Chef::Provider::Git # is the default, for svn: Chef::Provider::Subversion
  notifies :restart, "service[ps]"
  notifies :restart, "service[nginx]"
end

In defaults, I have the following to create the dirs etc.

directory "/tmp/.ssh" do
  action :create
  owner node[:base][:username]
  group node[:base][:username]
  recursive true
end

template "/tmp/.ssh/chef_ssh_deploy_wrapper.sh" do
  source "chef_ssh_deploy_wrapper.sh.erb"
  owner node[:base][:username]
  mode 0770
end

# Put SSH private key to be used with SSH wrapper
template "/tmp/.ssh/id_deploy" do
  source "id_rsa.pub.erb"
  owner node[:base][:username]
  mode 0600
end

And in the wrapper:

#!/bin/sh
exec ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "/tmp/.ssh/id_deploy" "$@"

And I have created a public key and uploaded this to github.

When I deploy the recipe, it gives me an error:

 deploy_branch[/var/www/html/ps] action deployEnter passphrase for key '/tmp/.ssh/id_deploy': 

Obvs I don't have a password set... The private key must therefore be missing..

Just by chance, I removed the id_deploy key from the recipe, deleted the folders and ran it again. Low and behold, it started working... The reason being that the id_rsa.pub && id_rsa files were in /root/.ssh from when I manually generated them to test.

I don't understand what I'm doing wrong here. My questions are therefore:

  • Do I need a private and public key on each node I deploy to? The docs don't mention this.
  • Should this not be deploying as non-root user? I have set a user in my roles file..
  • Why is the ssh_wrapper not doing what it's supposed to
simonmorley
  • 2,810
  • 4
  • 30
  • 61

2 Answers2

18

It took a good couple of days to figure this out properly.

Just to clarify, this is what I did to fix it. I do not know if it's correct, but it works for me.

  • Generate a set of public and private keys following this tutorial.

  • Add the public key to the Github repo that you want to clone.

  • Create a template in my default recipe which includes both the public and private keys. See below.

  • Created the relevant templates for the pub and private keys.

  • Created the chef_ssh_deploy_wrapper.sh.erb file (see below)

  • Created a deploy.rb recipe (see below)

  • Uploaded and added the recipes to my role. Ran chef-client.

  • Hey presto! Sit back with a beer and watch your repo. smartly cloned into your dir.

The templates are as follows:

Create the directories and templates:

template "/tmp/.ssh/chef_ssh_deploy_wrapper.sh" do
  source "chef_ssh_deploy_wrapper.sh.erb"
  owner node[:base][:username]
  mode 0770
end

template "/home/#{node[:base][:username]}/.ssh/id_rsa.pub" do
  source "id_rsa.pub.erb"
  owner node[:base][:username]
  mode 0600
end

template "/home/#{node[:base][:username]}/.ssh/id_rsa" do
  source "id_rsa.erb"
  owner node[:base][:username]
  mode 0600
end

Create an ssh wrapper chef_ssh_deploy_wrapper.erb

#!/bin/sh
exec ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "/home/#{node[:base][:username]}/.ssh/id_rsa" "$@"

(Make sure you use the private key here or it will fail)

Finally the deploy.rb recipe:

deploy_branch node[:my_app][:deploy_to] do
  repo              node[:base][:repository]
  ssh_wrapper       "/tmp/.ssh/chef_ssh_deploy_wrapper.sh"
  branch            "rails4"
  user               node[:base][:username]
  group              node[:base][:username]
  rollback_on_error  true
  migrate            false
  environment        "RAILS_ENV" => node[:my_app][:environment] 
  purge_before_symlink %w{conf data log tmp public/system public/assets}
  create_dirs_before_symlink []
  symlinks(                        
    "config"   => "config",        
    "data"   => "data",            
    "log"    => "log",             
    "tmp"    => "tmp",             
    "system" => "public/system",  
    "assets" => "public/assets"  
  )
  scm_provider Chef::Provider::Git # is the default, for svn: Chef::Provider::Subversion
  before_restart do
    system("su #{node[:base][:username]} -c 'cd #{node[:my_app][:deploy_to]}/current && /usr/bin/bundle install'") or raise "bundle install failed"
    system("su #{node[:base][:username]} -c 'RAILS_ENV=production /usr/local/bin/rake assets:precompile'")
  end
  notifies :restart, "service[my_app]"
  notifies :restart, "service[nginx]"
end

The before restart has since been replaced as we were initially compiling ruby from source but decided to use rvm in the end. Much easier for multi-user installations.

NB: I'm deploying as an sudo user, if you're doing so as root (avoid this), use the /root/.ssh path instead.

I took much inspiration from this article.

Good luck, I hope this helps someone.

Mez
  • 24,430
  • 14
  • 71
  • 93
simonmorley
  • 2,810
  • 4
  • 30
  • 61
  • 1
    Only problem with that solution is that you are storing not encrypted private key in your repo. Better use encrypted data bag to store the private key, and then in ruby_block do file open, file write (value from encrypted data bag), file close. Same effect, but no private keys in the repository. Check this out: [deploying from a private Github repository](http://www.jasongrimes.org/2012/06/deploying-a-lamp-application-with-chef-vagrant-and-ec2-3-of-3/#private-repo) – jkulak Nov 17 '14 at 21:17
  • Valid point and a sign of when I wrote this. Didn't know such things existed then – simonmorley Nov 17 '14 at 23:06
1

Your question doesn't have a link to to the deploy_resource source, so I can't be sure if this will apply, but if it uses a git resource underneath, the following might be helpful...

As described in this answer to a similar question, you can avoid creating extra script files to go with each SSH key by adding the SSH command as an "external transport" part of the repository URL:

git "/path/to/destination" do
  repository "ext::ssh -i /path/to/.ssh/deployment_key -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no git@github.com %S /my_name/some_repo.git"
  branch "master"
  ...
end
Community
  • 1
  • 1
Adam Franco
  • 81,148
  • 4
  • 36
  • 39