TL;DR: I released pp-ngnix on github to provide a declarative way for provisioning ngnix servers, locations and their directives.

I usually set up machines with the nginx package of jfryman (formerly from puppetlabs) or the module of example24.

First of all: I really respect all the hard work which has been put into those modules.

But they do not work for my use cases. I think the high amount of github forks (365 at the time of writing) shows, that the modules are not really usable without modifications. Like R.I. Pienaar noted in his blog: usage of params.pp for configuration forces your users to fork you module IF they want to modify it (happens to me always in production).

I did some code review to find out, what does not work for me with those modules. Here are my key problems, with those modules.

Every location has all parameters

The manifest for nginx::resource::location has lot's of parameters (even though they are not enough :().

But since some templates do not use the parameters at all, puppet cannot report if a variable is unused or not expected.

Since the vhost might also have a location, all location parameters are available to vhosts, too. And eventually will have no effect at all.

Location template is detected by duck typing

This code in location.pp detects, which template to use:

if ( $proxy != undef ) { $content_real = template ( 'nginx/vhost/vhost_location_proxy.erb' ) } elsif ( $location_alias != undef ) { $content_real = template ( 'nginx/vhost/vhost_location_alias.erb' ) } elsif ( $stub_status != undef ) { $content_real = template ( 'nginx/vhost/vhost_location_stub_status.erb' ) } elsif ( $fastcgi != undef ) { $content_real = template ( 'nginx/vhost/vhost_location_fastcgi.erb' ) } elsif ( $www_root != undef ) { $content_real = template ( 'nginx/vhost/vhost_location_directory.erb' ) } else { $content_real = template ( 'nginx/vhost/vhost_location_empty.erb' ) }

Since some location templates do support custom_cfg and others don't (e.g. a location will end up with vhostlocationempty.erb and does support lots of parameters, but renders: only @ location_custom_cfg as KEY VALUE and alphabetic sorted)

Some key value lists are sorted by key

If one adds custom parameters, they are sorted by key (e.g. in vhostlocationempty.erb).

This means in case of nginx's allow and deny (which heavily depend on order) you have no chance, but to modify the template.

Templates are not configurable

In example24's module you can easily override the template.

In the jfryman's nginx module this is not possible (they are mostly hard coded.

So you are forced to either fork it or to use a location, which supports some way of custom cfg and does not require to many other parameters.

Conclusion

With stdlib's getparam function, it's possible to retrieve parameters of an existing resource. So hacks like params.pp or defining all parameters, just to get them in sub resources should not be necessary anymore.

Generally having some kind of $content , which allows you to insert custom text (without a for loop or any key-value stuff) should be possible.

Location directives like auth_basic or auth_basic_user_file of nginx's access module should be defined on their on, maybe like this:

nginx :: server :: location :: auth - basic { "assets-directory" : location => Nginx :: Server :: Location [ 'assets' ] , text => 'This is restricted' , user_file => '/etc/nginx/.htpasswd' }

It's time to have a new, more declarative way to define nginx servers, locations and directives for puppet. I tried to achieve that with pp-nginx. It's definitely NOT perfect, yet. But one has to start somewhere!