Chef'ing Custom Nginx Configs With the Nginx Cookbook
| Comments
The nginx cookbook has been
super helpful Chef’ing some web apps recently. One thing I struggled to
understand was how to use my own custom conf, like /etc/nginx/nginx.conf
, that
is optimized for how I use nginx.
One solution I tried, which is probably a Chef anti-pattern, is to only include the nginx cookbook on the initial converge:
The Wrong Way
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# the nginx community cookbook will relentlessly revert conf files,
# so avoid running it unless nginx isn't installed,
# or we explicitly reset/delete the node attribute
include_recipe 'nginx' unless node['nginx']['installed']
node.set['nginx']['installed'] = true
# our custom nginx.conf
template '/etc/nginx/nginx.conf' do
source 'nginx.conf.erb'
owner 'root'
group 'root'
mode '0644'
notifies :reload, "service[nginx]", :delayed
end
I knew this was wrong when I wrote it. Chef is all about idempotency.
But, I couldn’t figure out a way to keep the nginx cookbook from reverting my
custom conf during subsequent converges, only to have my template
restore my
custom conf a few seconds later.
The Better Way
The OpsCode blog Doing Wrapper Cookbooks Right shows the right way, and really opened my eyes on the power of Chef’s two phase model (compile, then converge).
1 2 3 4 5 6
include_recipe 'nginx'
# use our custom nginx.conf, rather than the one that ships in the nginx cookbook
# this avoids the nginx and my-app cookbooks from fighting for control of
# the same target file
resources('template[nginx.conf]').cookbook 'my-app'