Out-of-order chef recipes causing apt package install to fail

I'm writing a Chef recipe to install among other things nginx and Phusion Passenger. The short summary is that the recipes on my run list are not executing in the order I expect, and that's causing an apt package installation to fail in a way I don't know how to fix. The full sequence is a little complicated, I'll do my best to keep to the essential details.

I have my own recipe, lr-web for customising the web server to the state I want it to be in. One of its actions to make changes to nginx.conf. I also have a role to orchestrate the overall configuration, whose run list is:

 "run_list":[
   "recipe[apt]",
   "recipe[nginx]",
   "recipe[passenger]",
   "recipe[lr-web]"
 ]

Moreover, the lr-web recipe lists passenger and nginx as dependencies in its metadata.rb.

The apt and nginx recipes are the standard OpsCode ones. But I've written my own passenger recipe, as the OpsCode one uses rubygems to install passenger, but that version is no longer supported. Following the advice on modrails.com to install via apt, I have the following steps in my passenger recipe:

cookbook_file "/etc/apt/sources.list.d/passenger.list" do
  source "passenger.list"
  mode 600
  action :create_if_missing
end

bash "apt-get-update" do
  user "root"
  code <<-EOF
    apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
    apt-get install apt-transport-https ca-certificates
    apt-get update
EOF
end

apt_package "nginx-extras" do
  action :install
end

What happens when I converge the node is that I get a prompt from apt-get, even though it passes the -y flag because the nginx-extras package installer doesn't want to overwrite nginx.conf:

Configuration file `/etc/nginx/nginx.conf'
 ==> Modified (by you or by a script) since installation.
 ==> Package distributor has shipped an updated version.
   What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
 The default action is to keep your current version.
*** nginx.conf (Y/I/N/O/D/Z) [default=N] ? 
Configuration file `/etc/nginx/sites-available/default'
 ==> Modified (by you or by a script) since installation.
 ==> Package distributor has shipped an updated version.
   What would you like to do about it ?  Your options are:
    Y or I  : install the package maintainer's version
    N or O  : keep your currently-installed version
      D     : show the differences between the versions
      Z     : start a shell to examine the situation
 The default action is to keep your current version.
*** default (Y/I/N/O/D/Z) [default=N] ? dpkg: error processing nginx-common (--configure):
 EOF on stdin at conffile prompt
dpkg: dependency problems prevent configuration of nginx-extras:
 nginx-extras depends on nginx-common (= 1:1.4.4-2.4.0.37~precise1); however:
  Package nginx-common is not configured yet.
dpkg: error processing nginx-extras (--configure):
 dependency problems - leaving unconfigured
No apport report written because the error message indicates its a followup error from a previous failure.
Errors were encountered while processing:
 nginx-common
 nginx-extras
E: Sub-process /usr/bin/dpkg returned an error code (1)

As far as I can tell, the only way this can be happening is if my lr-web recipe is run before the passenger recipe, which it shouldn't do.

So. The problem I have is that lr-web is running before passenger, and thus change the nginx conf. I either need to find out why that's happening, and stop it, or find a way when apt_package is installing nginx-extras to pass the 'N' response saying "don't overwrite the nginx.conf". Any suggestions on either angle of attack would be very welcome.


This is probably coming about since the nginx cookbook modifies the /etc/nginx/nginx.conf file after it has been installed by apt, and the dpkg command is warning you about that change. This will also conflict on /etc/nginx/sites-available/default.

Change the order of what is applied when.

Placing the passenger recipe above the nginx one will ensure that the repo and packages will get installed. Since the nginx-extras provides it's own nginx.conf file, this will then immediately be overwritten by the nginx recipe, and be controlled from there on in.

Your modified run list would look like this:

 "run_list":[
   "recipe[apt]",
   "recipe[passenger]",
   "recipe[nginx]",
   "recipe[lr-web]"
 ]

Tell Apt to answer correctly

You could also try force apt to respond the way you want it to - this has the danger of being a little too aggressive on apt's behavior, potentially affecting the rest of the Chef run. I don't recommend this, but you could try it out and see if it works for your use case.

ENV['DEBIAN_FRONTEND'] = 'noninteractive'
package 'nginx-extras' do
  options '--force-yes'
  options '-o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"'
  action :install
end

Read more on this here.

This has the danger of answering this way for other resources, and not surfacing the problem to the operator, as well as having resources potentially overwrite each other, and trigger undesired notifications to other resources, like triggering an nginx restart when a config file changes, etc.

Convert bash to apt_repository resource

This isn't really to solve the ordering problem, just better Chef resource use.

You show to be providing a cookbook file, and then executing bash resources to activate them. This would happen every run if not guarded with a only_if/not_if statement.

The apt cookbook you are using already has a repository resource, and would change your recipe to look like this:

apt_repository 'passenger' do
  uri          'https://oss-binaries.phusionpassenger.com/apt/passenger'
  distribution node['lsb']['codename']
  components   ['main']
  keyserver    'keyserver.ubuntu.com'
  key          '561F9B9CAC40B2F7'
end

This will then behave in a saner fashion that running apt-get commands during the run, and the output is pretty much the same:

deb     https://oss-binaries.phusionpassenger.com/apt/passenger precise main

(on Ubuntu 12.04)

TL, DR:

Use the first solution to change the order in which recipe is applying changes to the files provided by two differing package.

Use the third solution to clean up the code a little further.