How to run Chef-Solo programmatically: require 'chef' require 'chef/application/solo' Chef::Config[:solo_legacy_mode] = true Chef::Config[:cookbook_path] = [File.join(File.absolute_path(File.dirname(__FILE__)), 'cookbooks')] chef_client = Chef::Application::Solo.new chef_client.config[:override_runlist] = ['recipe[openvpn::create_consul]'] chef_client.run Tricky way to setup attributes programmatically: require 'chef' require 'chef/application/solo' class Chef::Application::Solo def set_json_attr(attr_hash) @chef_client_json = attr_hash end end Chef::Config[:solo_legacy_mode] = true Chef::Config[:cookbook_path] = [File.join(File.absolute_path(File.dirname(__FILE__)), 'cookbooks')] chef_client = Chef::Application::Solo.new chef_client.config[:override_runlist] = ['recipe[openvpn::create_consul]'] chef_client.set_json_attr({foo: 'bar'}) chef_client.run