Populating Your Puppet Master: Modules, Environments, and R10k Made Simple
In the last few posts in this Puppet with Foreman series, we’ve covered the full infrastructure setup, the initial installation, agent registration, and even a deep dive into the confdroid_puppet module. At this point, you have a working Puppet server with Foreman — agents are connecting, facts are flowing, and the basics are in place.
Now it’s time to make it useful. That means populating the Puppet master with the modules that actually do the work: your custom ones from the ConfDroid Forge, community modules from the Puppet Forge, or even your own internal code.
Today, we’ll walk through the best way to handle this — using R10k, the gold standard for Puppet module management. We’ll also show how the confdroid_puppet module makes the whole process effortless.
Where Puppet Stores Modules
Puppet expects modules to live in a specific directory structure:
/etc/puppetlabs/code/environments/
├── production/
│ ├── manifests/
│ ├── modules/
│ └── hieradata/
├── development/
│ └── ...
└── ...
Each subfolder is an environment (production, staging, testing, etc.). Inside each one, you’ll find:
manifests/— site.pp and other top-level manifestsmodules/— your Puppet moduleshieradata/— Hiera data (if you’re using it)
You could manually copy modules into these folders, but that’s error-prone, hard to version-control, and doesn’t scale. Git clones with cron jobs work okay for small setups, but they still require manual intervention.
Enter R10k — the elegant, automated solution.
What Is R10k?
R10k is a tool from Puppet Labs (now Puppet) that turns your Puppet environments into GitOps. It uses a single control repository (a Git repo) to define everything for your Puppet setup.
Here’s how it works:
- You maintain one Git repo (the control repo) with branches for each environment.
- Each branch contains a Puppetfile — a simple manifest that declares exactly which modules should be in that environment.
- R10k reads the Puppetfile, pulls the modules (from Git or the Forge), and deploys them into the correct environment folder.
- It also removes anything not listed in the Puppetfile — keeping things clean and consistent.
This approach is perfect for teams, CI/CD pipelines, and anyone who wants reproducible, version-controlled Puppet code.
The Puppetfile: Your Module Shopping List
The heart of R10k is the Puppetfile. Here’s a real-world example from the ConfDroid Forge:
# Custom modules from the ConfDroid Forge
mod 'confdroid_puppet',
:git => 'https://sourcecode.confdroid.com/confdroid/confdroid_puppet.git',
:ref => 'master'
mod 'confdroid_resources',
:git => 'https://sourcecode.confdroid.com/confdroid/confdroid_resources.git',
:ref => 'master'
# Official Forge modules with exact versions
mod 'puppetlabs-firewall', '8.1.2'
mod 'puppetlabs-apt', '9.0.0'
- Git modules: Use
:gitand:ref(branch, tag, or commit) to pull from any repo. - Forge modules: Just the name and version — R10k downloads them automatically.
- You can add anything else to the control repo: custom facts, functions, Hiera data, even scripts.
R10k creates an environment for every branch in the control repo (production, development, etc.). Super clean.
The r10k.yaml Configuration
On the Puppet master, R10k reads its settings from /etc/puppetlabs/r10k/r10k.yaml:
:cachedir: /var/cache/r10k
:sources:
:puppet:
remote: git@your-git-server:path/to/control-repo.git
prefix: false
basedir: '/etc/puppetlabs/code/environments'
This tells R10k where to find the control repo and where to deploy the environments. (Make sure your puppet master host has git installed and can read from the repo, i.e. using deployment keys)
Making It Easy with confdroid_puppet
Configuring all this manually can feel overwhelming at first. That’s why confdroid_puppet does the heavy lifting for you.
Just set two parameters in Foreman:
pt_use_r10k:true(defaults tofalse)pt_r10k_remote:git@your-git-server:path/to/control-repo.git
Optionally (see below):
pt_use_r10k_webhook:true(defaults tofalse)pt_r10k_webhook_port: ` ` (defaults to 8085)
That’s it. The module:
- Installs R10k
- Creates the
r10k.yamlfile - (If enabled) Installs a webhook listener on port 8085 (or your choice) and opens the firewall for it ( requires puppetlabs-firewall).
Deploying Modules
Once configured, run the deployment command on the master:
r10k deploy environment -pv
-p= purge (remove modules not in the Puppetfile)-v= verbose (see what’s happening)
R10k will clone the control repo, fetch all modules, and populate every environment.
The Cherry on Top: GitOps with the Webhook
For true automation, enable the webhook in confdroid_puppet:
- Every time you push to your control repo (or a module repo), the webhook triggers r10k deploy automatically. For this to work, you need to create a webhook in the repo(s) and set it to your puppet master:
http://puppet.example.net:8085. - In my own setup, I wire this to GitLab CI/CD: successful builds or merged MRs hit the webhook.
- Result: Changes land on the Puppet master in seconds — no manual steps. Codebase is always in sync.
This is the GitOps dream for Puppet.
Wrapping Up
With R10k and confdroid_puppet, managing modules becomes predictable, versioned, and effortless. You can mix ConfDroid Forge modules, Puppet Forge gems, and your own code — all in one clean workflow.
Ready to try it? Clone the control repo template from the ConfDroid Forge and get deploying!
Next in the series: We’ll take a specific module (like confdroid_postgresql) and show how to use it in practice.
In the meantime, check out:
- The confdroid_puppet module docs: https://deepwiki.com/grizzlycoda/puppet_collection/4.1-confdroid_puppet
- Official R10k repo: https://github.com/puppetlabs/r10k
Questions or feedback? Hit the portal at https://feedback.confdroid.com. Happy Puppet-ing! 🚀
Did you find this post helpful? You can support me.



Related posts
- Puppet with Foreman – Pilot
- Puppet with Foreman – Installation
- Puppet with Foreman – Infrastructure
- Puppet with Foreman – Host registration


