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
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.
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