First off, I'm using Chef Solo and I would like things to stay as automated as possible. So I have a problem that I'm not quite sure how to solve. I'm setting up the deployment of a lot of different Linux boxes, and all of them are going to require custom installation nodes/roles. Example:


"run_list": [ "role[app_server]" ]


name 'app_server'
description 'App_Server'
override_attributes({ "apache" => {
                                      "proxypass" => [" /  http://localhost:8080/"]
run_list 'recipe[app_server]'

My issue is that I'm going to be running a script to install chef on all these different boxes, but each one is going to have a different ip in-between http://[xxxxxx]:8080/

I need a way to be able to -via command line- specify those ip's without having to create like a hundred node or role files.

I've looked at an example on their website that shows:

The Web Server Role

description "The base role for systems that serve HTTP traffic"
run_list "recipe[apache2]", "recipe[apache2::mod_ssl]", "role[monitor]"
env_run_lists "prod" => ["recipe[apache2]"], "staging" => ["recipe[apache2::staging]"],"_default" => []
default_attributes "apache2" => { "listen_ports" => [ "80", "443" ] }
override_attributes "apache2" => { "max_children" => "50" }

which seems like it would be useful, but I would like to set different override set's for each env_run_list config and then when I run all the chef commands, be able to target each one that I want.

Am I going about this in the wrong fashion? I've scoured all of the docs for nodes/roles/environments etc and haven't found any solution that requires me to not have to make a dozen different files.

  • I have the same problem. Did you find a solution?
    – j7nn7k
    Jan 11, 2013 at 15:47

2 Answers 2


Without access to your app_server recipe, I infer that you are using the node['apache']['proxypass'] attribute to populate a line in an apache config file generated from a template.

My guess is that the relevant line in your template looks something like this:

ProxyPass <%= node['apache']['proxypass'] %>

I think you will have greater success if you use more granular elements to compose that line in your template. If the IP address you wish to proxy requests to will differ in every environment, you can make use of Chef's search facilities to determine the required IP address and pass that IP address to the template as a variable.

The code in your recipe might look something like this:

# this search assumes that the role 'myapp_backend' is in the run list of the backend server you need to discover.
# the search returns an array of node objects, for simplicity we'll just take the first result.
proxypass_backend = search(:node, "roles:myapp_backend AND chef_environment:#{node.chef_environment}").first

template ::File.join(node['apache']['dir'],'sites-available','myapp.conf') do
    :proxypass_local_path => '/',
    :proxypass_remote_ip => proxypass_backend['ipaddress'],
    :proxypass_remote_port => '8080',
    :proxypass_remote_path => '/'
  source 'myapp.conf.erb'

And the line in your template would look something like this:

ProxyPass <%= @proxypass_local_path %> http://<%= @proxypass_remote_ip %>:<%= proxypass_remote_port %><%= @proxypass_remote_path %>

For the sake of simplicity I've specified static values for the remote port and path, but those could also be set using attribute values that can be overridden at the role or environment level. Because search returns entire node objects, any attribute of a node returned by a search (e.g. the port a service is running on) can be used to populate template variables as well (e.g. proxypass_remote_port).

  • Sorry, but my answer is very much oriented toward the client/server approach. I guess I completely skimmed over your mentioning that you are using solo.
    – cwjohnston
    Jan 13, 2013 at 17:41

You can create a json file for each server that contains only the overrides, and you can pass that file to chef-solo with the -j option: chef-solo -j node.json

You might create those files before the chef run. Be aware that input redirection isn't implemented yet: https://tickets.opscode.com/browse/CHEF-1918 so you can't just have one bash command.

But I second @cwjohnston that you should split that string and put the ip, port and protocol into separate node attributes. You can probably find the current node's IP with Ohai (node['ipaddress']) or from Ruby, and set sensible defaults for the last 2.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .