Module Fundamentals

This version of Puppet is not included in Puppet Enterprise. The latest version of PE includes Puppet 4.4. A newer version is available; see the version menu above for details.

Modules are self-contained bundles of code and data. You can write your own modules or you can download pre-built modules from the Puppet Forge.

Nearly all Puppet manifests belong in modules. The sole exception is the main site.pp manifest, which contains site-wide and node-specific code.

Every Puppet user should expect to write at least some of their own modules.

Using Modules

Modules are how Puppet finds the classes and types it can use — it automatically loads any class or defined type stored in its modules. Within a manifest or from an external node classifier (ENC), any of these classes or types can be declared by name:

# /etc/puppet/manifests/site.pp

node default {
  include apache

  class {'ntp':
    enable => false;

  apache::vhost {'personal_site':
    port    => 80,
    docroot => '/var/www/personal',
    options => 'Indexes MultiViews',

Likewise, Puppet can automatically load plugins (like custom native resource types or custom facts) from modules; see “Using Plugins” for more details.

To make a module available to Puppet, place it in one of the directories in Puppet’s modulepath.

You can easily install modules written by other users with the puppet module subcommand. See “Installing Modules” for details.

Module Layout

On disk, a module is simply a directory tree with a specific, predictable structure:

    • manifests
    • files
    • templates
    • lib
    • facts.d
    • tests
    • spec


This example module, named “my_module,” shows the standard module layout in more detail:

  • my_module — This outermost directory’s name matches the name of the module.
    • manifests/ — Contains all of the manifests in the module.
      • init.pp — Contains a class definition. This class’s name must match the module’s name.
      • other_class.pp — Contains a class named my_module::other_class.
      • my_defined_type.pp — Contains a defined type named my_module::my_defined_type.
      • implementation/ — This directory’s name affects the class names beneath it.
        • foo.pp — Contains a class named my_module::implementation::foo.
        • bar.pp — Contains a class named my_module::implementation::bar.
    • files/ — Contains static files, which managed nodes can download.
      • service.conf — This file’s URL would be puppet:///modules/my_module/service.conf.
    • lib/ — Contains plugins, like custom facts and custom resource types. These will be used by both the puppet master server and the puppet agent service, and they’ll be synced to all agent nodes whenever they request their configurations. See “Using Plugins” for more details.
    • facts.d/ — Contains external facts, which are an alternative to Ruby-based custom facts. These will be synced to all agent nodes, so they can submit values for those facts to the puppet master. (Requires Facter 2.0.1 or later.)
    • templates/ — Contains templates, which the module’s manifests can use. See “Templates” for more details.
      • component.erb — A manifest can render this template with template('my_module/component.erb').
    • tests/ — Contains examples showing how to declare the module’s classes and defined types.
      • init.pp
      • other_class.pp — Each class or type should have an example in the tests directory.
    • spec/ — Contains spec tests for any plugins in the lib directory.

Each of the module’s subdirectories has a specific function, as follows.


Each manifest in a module’s manifests folder should contain one class or defined type. The file names of manifests map predictably to the names of the classes and defined types they contain.

init.pp is special and always contains a class with the same name as the module.

Every other manifest contains a class or defined type named as follows:

Name of module :: Other directories:: (if any) Name of file (no extension)
my_module ::   other_class
my_module :: implementation:: foo


  • my_module::other_class would be in the file my_module/manifests/other_class.pp
  • my_module::implementation::foo would be in the file my_module/manifests/implementation/foo.pp

The double colon that divides the sections of a class’s name is called the namespace separator.

Allowed Module Names

Module names should only contain lowercase letters, numbers, and underscores, and should begin with a lowercase letter; that is, they should match the expression [a-z][a-z0-9_]*. Note that these are the same restrictions that apply to class names, but with the added restriction that module names cannot contain the namespace separator (::) as modules cannot be nested.

Although some names that violate these restrictions currently work, using them is not recommended.

Certain module names are disallowed:

  • main
  • settings


Files in a module’s files directory are automatically served to agent nodes. They can be downloaded by using puppet:/// URLs in the source attribute of a file resource.

Puppet URLs work transparently in both agent/master mode and standalone mode; in either case, they will retrieve the correct file from a module.

Puppet URLs are formatted as follows:

Protocol 3 slashes “Modules”/ Name of module/ Name of file
puppet: /// modules/ my_module/ service.conf

So puppet:///modules/my_module/service.conf would map to my_module/files/service.conf.


Any ERB template (see “Templates” for more details) can be rendered in a manifest with the template function. The output of the template is a simple string, which can be used as the content attribute of a file resource or as the value of a variable.

The template function can look up templates identified by shorthand:

Template function (‘ Name of module/ Name of template ’)
template (' my_module/ component.erb ')

So template('my_module/component.erb') would render the template my_module/templates/component.erb.

Writing Modules

To write a module, simply write classes and defined types and place them in properly named manifest files as described above.

  • See here for more information on classes
  • See here for more information on defined types

Best Practices

The classes, defined types, and plugins in a module should all be related, and the module should aim to be as self-contained as possible.

Manifests in one module should never reference files or templates stored in another module.

Be wary of having classes declare classes from other modules, as this makes modules harder to redistribute. When possible, it’s best to isolate “super-classes” that declare many other classes in a local “site” module.

↑ Back to top