35

How can you use a Chef recipe to set an environment variable?

I need to set an environment variable using a Chef recipe. Can you provide an example of how to accomplish this?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Brandon
  • 6,832
  • 11
  • 38
  • 50

5 Answers5

28

If you need an env var set strictly within the Chef process, you can use ENV['foo'] = 'bar' since it's a ruby process.

If you need to set one for an execute provider, Chef exposes an environment hash:

execute 'Bootstrap the database' do 
  cwd "#{app_dir}/current"
  command "#{env_cmd} rake db:drop db:create db:schema:load RAILS_ENV=#{rails_env}"
  environment 'HOME' => "/home/#{app_user}"
  user app_user
  action :run
  not_if %[psql -U postgres -c "\\l" | grep #{db_name}]
end

If you're looking to set a persistent environment variable then you may want to have Chef edit /etc/profile.d/chef.sh, /etc/environment, a users' profile, etc.

codeforester
  • 39,467
  • 16
  • 112
  • 140
jodell
  • 1,057
  • 9
  • 20
14

If you want to set it on the system with Chef, checkout the magic_shell cookbook.

magic_shell_environment 'RAILS_ENV' do
  value 'production'
end
sethvargo
  • 26,739
  • 10
  • 86
  • 156
  • 1
    Just a note for others who are googling -- magic_shell_environment is fantastic, with one gotcha. Any command invoked with system("/new/process/to/call") from a ruby script will not pull from /etc/profile.d/* automatically – matt Apr 25 '13 at 16:15
  • @matt you can force that to happen by forcing an interactive login and/or sourcing `/etc/profile` in the Ruby script. – sethvargo Apr 28 '13 at 17:21
  • thanks, @sethvargo. To update an environment variable, such as `$PATH`, how should I use the `magic_shell` cookbook? – Kevin Meredith Mar 24 '14 at 18:29
  • 2
    magic_shell_environment 'PATH' do value '$PATH:whatever' end – sethvargo Mar 24 '14 at 18:32
  • @matt - does my problem (http://stackoverflow.com/questions/22618960/updating-path-with-magic-shell-cookbook) show a concrete example of the potential problem you mentioned? – Kevin Meredith Mar 24 '14 at 19:40
  • If you're trying to roll your own installer, you might want to check out [Ark](https://supermarket.getchef.com/cookbooks/ark) instead. – Zook Jul 11 '14 at 20:49
  • @sethvargo I want to use the variable right after I set it but it is empty. next time I run the recipes, everything is fine ...!? am I doing something wrong? – Philipp Kyeck Feb 24 '15 at 10:25
  • @pkyeck no, that is how shell loading works. You will need to reload the shell after setting the envar. – sethvargo Feb 24 '15 at 14:49
  • @sethvargo Is there any way to `source` the profile file during the execution of a recipe. `execute 'source /etc/profile'` certainly doesn't work as `source` is not available in the ruby shell and it is running in a sub-shell anyway. – Cristian Vrabie Feb 09 '16 at 14:38
5

If you want to set it at the system level in /etc/environment, you can do so directly per the following example without adding an additional recipe (this adds two env variables for Java):

sys_env_file = Chef::Util::FileEdit.new('/etc/environment')
{
  'JAVA_HOME' => '/usr/lib/jvm/java-1.7.0-openjdk-amd64',
  'LD_LIBRARY_PATH' => '/usr/lib/jvm/java-1.7.0-openjdk-amd64/lib'
}.each do |name, val|
  sys_env_file.insert_line_if_no_match /^#{name}\=/, "#{name}=\"#{val}\""
  sys_env_file.write_file
end
Kent Mewhort
  • 1,158
  • 12
  • 11
2

The way to do this is different between Windows and Linux. The easiest way would be:

Windows

Use the windows_env resource to create a System environment variable:

windows_env 'CHEF_LICENSE' do
  value 'accept'
end

Linux

If you only need it for the cookbook run and its children, then use the Ruby ENV resource. This will NOT be permanent:

ENV['CHEF_LICENSE'] = 'accept'

If you need it to be permanent (and use bash):

Create a script in /etc/profile.d:

  1. Create a template script (such as chef.sh.erb)
  2. Fill out the template script:

    #!/bin/bash export CHEF_LICENSE='accept' # Needed for Chef Infra Client 15

  3. Put the template resource in your recipe (You may want to set attributes and owner/group settings, I wanted to keep this example simple)

    template '/etc/profile.d/chef.sh' do source 'chef.sh.erb' end

Here are some additional resources to read up on the different resources referenced here:

template resource
windows_env resource

Taegost
  • 1,208
  • 1
  • 17
  • 26
0

For Linux, the best way to it is by using

ENV['Var'] = 'Value'

When you use this command, every sub process spun by the recipe will be using this ENV value. You can verify it using a bash resource and echoing the value of Var.