The Puppet Labs Issue Tracker has Moved:

This issue tracker is now in read-only archive mode and automatic ticket export has been disabled. Redmine users will need to create a new JIRA account to file tickets using See the following page for information on filing tickets with JIRA:

Bug #19006

per-environment templatedir doesn't actually work,

Added by John Moser about 3 years ago. Updated about 3 years ago.

Status:Needs More InformationStart date:
Priority:NormalDue date:
Assignee:John Moser% Done:


Target version:3.x
Affected Puppet version:3.0.2 Branch:

We've Moved!

Ticket tracking is now hosted in JIRA:


As per

Puppet will only read the modulepath, manifest, manifestdir, and
templatedir settings from environment config blocks; other settings
in any of these blocks will be ignored in favor of settings in the
[master] or [main] blocks. (Issue 7497)

Issue #7497 covers the above.

What this issue covers is as such:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER:
No such file or directory - /percona/loadbalance/haproxy/haproxy.cfg.erb

With the node having (this is not best practice, but I’ll find/write a module later)

file { '/etc/haproxy/haproxy.cfg':
  content => template("$templatedir/percona/loadbalance/haproxy/haproxy.cfg.erb"),
  owner   => 'root',
  group   => 'root',
  mode    => '0444',
  notify  => Service[ 'haproxy' ],

And /etc/puppet/puppet.conf on the Puppetmaster containing:

manifestdir = $confdir/environments/$environment/manifests
templatedir = $confdir/environments/$environment/templates
manifest    = $confdir/environments/$environment/manifests/site.pp

The documentation indicates that this should work; however, it doesn’t.

Using puppetmaster with Passenger here. Apache has been restarted since the templatedir directive went into the config file.

792240_4697494708677_2092141553_o.jpg (136 KB) John Moser, 02/13/2013 05:26 pm

Related issues

Related to Puppet Documentation - Bug #19255: Add more info concerning templatedir behavior to templati... Merged - Pending Release
Related to Puppet - Feature #16856: puppet should support data in modules Re-opened 10/08/2012


#1 Updated by Josh Cooper about 3 years ago

  • Target version changed from 363 to 3.x

Moving to 3.x as we’re not planning any additional 3.0.x releases (now that 3.1 is released)

#2 Updated by eric sorenson about 3 years ago

  • Status changed from Unreviewed to Needs More Information
  • Assignee set to John Moser

Hi, was there a specific piece of documentation you found which suggested to use template("$templatedir/[etc]") in your manifest? This isn’t actually a top-scope variable, it’s a setting, and it’s not needed — the code which searches for templates will automatically prepend the environment’s templatedir to the relative-path argument to the template function. So if you change your code to

content => template(“percona/loadbalance/haproxy/haproxy.cfg.erb”)

it should get found properly.

But in a broader sense (and the Templates guide goes into this) in modern Puppet, templates live inside modules instead of a stand-alone templatedir, and are subject to environments there.

We’ll update the Learning section on templates to point to the guide, and make the guide more clear that you just need a relative path.

So two next actions for you:

  • Does the relative path cause your template to be found?
  • If you can point me at a document that specifically said to use $templatedir, I’ll track it down and remove it because it’s wrong.

I’ve put this ticket’s status into “Needs more Information” and assigned it to you. Please either (a) update it with the information I’ve requested and re-assign it to me if you need more help, or (b) change the status to “Closed” if you were able to resolve the issue on your own.

#3 Updated by John Moser about 3 years ago

Doesn’t look like it works that way. $templatedir is, for example, /etc/puppet/environments/$environment/templates. You have a module percona and you ask for template(percona/loadbalance/haproxy/haproxy.cfg.erb, it’s going to look in $moduledir/percona/templates/loadbalance/haproxy/haproxy.cfg.erb.

I’m overloading templates here and supplying templates to modules. Consider an apache::vhost that uses extremely customized settings that are pattern-replicated. The defined type:

define apache::vhost(
  $template      = 'apache/vhost.erb',
) {

makes a lot of sense.

Now, what you could do is just not do that, and then when somebody uses your module they have to modify the code and the templates and supply their own site-specific templates as part of the module. Then, they have to update to the newer module, and do a git merge, and fix their changes into your changes…

There are clear cases where a node supplies a template to a class. It wasn’t even originally my idea; I forget who I stole it from. I refined it out though and this is where it got me.

To be short, I disagree with the current conventions of [not] separating data (templates) and code units (modules) in the same way the guy who wrote Heira disagreed with the prior conventions of [not] separating data and code. Templates are default data.

I can think of ways to specify this in the language (i.e. an explicit “overload this template for this class/resource” that gets passed as a meta-parameter), but that’s worse: if the template overload isn’t explicitly exposed, it’s internal ABI subject to change (they could rename the template file, and then you’re overloading a non-existent file). So the way Puppet does it now is fine, and it’s up to module developers to expose those kinds of knobs; but Puppet carries a $templatedir variable that does nothing particularly useful and is not exposed as a top level variable, yet is explicitly a per-environment setting as if it’s there for something.

The convention of rigid, inflexible, non-polymorphic code is dead. Locking what are supposed to be extensible, reusable modules down to default data and not allowing for customization without going in with a cutting torch and a power drill is a poor way to go about things.

Also available in: Atom PDF