12

I'm writing a Chef cookbook to install Hubot. In the recipe, I do the following:

bash "install hubot" do
  user hubot_user
  group hubot_group
  cwd install_dir
  code <<-EOH
    wget https://github.com/downloads/github/hubot/hubot-#{node['hubot']['version']}.tar.gz && \
    tar xzvf hubot-#{node['hubot']['version']}.tar.gz && \
    cd hubot && \
    npm install
  EOH
end

However, when I try to run chef-client on the server installing the cookbook, I'm getting a permission denied writing to the directory of the user that runs chef-client, not the hubot user. For some reason, npm is trying to run under the wrong user, not the user specified in the bash resource.

I am able to run sudo su - hubot -c "npm install /usr/local/hubot/hubot" manually, and this gets the result I want (installs hubot as the hubot user). However, it seems chef-client isn't executing the command as the hubot user. Below you'll find the chef-client execution. Thank you in advance.

Saving to: `hubot-2.1.0.tar.gz'

     0K ......                                                100%  563K=0.01s

2012-01-23 12:32:55 (563 KB/s) - `hubot-2.1.0.tar.gz' saved [7115/7115]

npm ERR! Could not create /home/<user-chef-client-uses>/.npm/log/1.2.0/package.tgz
npm ERR! Failed creating the tarball.
npm ERR! couldn't pack /tmp/npm-1327339976597/1327339976597-0.13104878342710435/contents/package to /home/<user-chef-client-uses>/.npm/log/1.2.0/package.tgz
npm ERR! error installing hubot@2.1.0 Error: EACCES, permission denied '/home/<user-chef-client-uses>/.npm/log'

...

npm not ok
---- End output of "bash"  "/tmp/chef-script20120123-25024-u9nps2-0" ----
Ran "bash"  "/tmp/chef-script20120123-25024-u9nps2-0" returned 1
Arthur Maltson
  • 312
  • 3
  • 12

3 Answers3

8

The problem is (likely) not Chef running the command as the wrong user, but that the shell running your script is not a login shell. This means that some environment variables (like HOME) will not be set the way you expect, leading npm to try to write files in the wrong place.

The problem is discussed in issue CHEF-2288. While that remains outstanding, you could try adding HOME=/home/hubot-user in your code block, before npm is invoked.

zts
  • 945
  • 5
  • 8
5

Taken from a comment in CHEF-2288:

environment ({ 'HOME' => ::Dir.home('USERNAME'), 'USER' => 'USERNAME' })

Worked for me!

In your case:

environment ({ 'HOME' => ::Dir.home(hubot_user), 'USER' => hubot_user })

Drew Khoury
  • 4,569
  • 8
  • 26
  • 28
claptimes
  • 159
  • 1
  • 2
  • 2
    This assumes the `hubot_user` has already been created before the chef-client run. This is because the `Dir.home` command is run when the file is loaded, not when the recipe is executed. When creating a new machine, this will most likely be before any of your user creation recipes run and will result in a failure. – Russ Bradberry May 27 '15 at 16:58
  • For the asked question, this answer works perfectly. – look May 28 '15 at 03:52
  • 1
    not on the first bootstrap of the machine, it doesn't. it only works if the user already exists on the machine. – Russ Bradberry Jun 04 '15 at 19:22
  • I'll second that this is a non-solution if chef is also managing the user in question because this code executes in the compile phase, before any recipe execution. there are bigger hacks around it possibly to push it into the second stage, but...... doing 'HOME' => "/home/#{hubut_user}" will work since it's just string passing - but of course lacks the magic touch. – keen Jul 14 '16 at 16:51
1

After: https://serverfault.com/a/432916/129232

To execute a script or a command as a user, you need to combine su -l and bash -i, e.g.:

 execute "npm_install" do
    command "su vagrant -l -c 'cd /shared-with-host/helperScripts/ && bash -i npm install -g q zombie should mocha coffee-script'" 
    action :run
  end

Because of some bugs, chef does not set properly the environment for the specified user in execute.

Skarab
  • 327
  • 3
  • 11