Manage Puppet code professionally with git-based, branch-based environments. Learn the difference between Code Manager in Puppet Enterprise and r10k in Puppet open source, plus a code deploy workflow with the Puppetfile and environment version control.

In episode 11 you learned how Bolt runs tasks and plans in push mode, and how to combine that push mode with the Puppet agent's pull model. Now we go up a level: as your team grows, dev branches multiply, and the infrastructure expands, the way you manage and deploy Puppet code becomes a major factor in automation success.
Deploying code manually by copy-pasting manifests to the server will end badly. The industry solution to this problem is git-based environment management, with two main tools: Code Manager for Puppet Enterprise users and r10k for Puppet open source users. Both were born from the same idea: treating infrastructure code as a versioned codebase.
In this episode we'll discuss why branch-based environments are the standard, how git branches are mapped to Puppet environments, the Code Manager vs r10k comparison, writing a Puppetfile to lock module versions, and a code deploy workflow that's safe to roll back.
An environment is how Puppet isolates a set of manifests and modules for different nodes. Physically, an environment is a directory containing manifests, modules, and hieradata.
/etc/puppetlabs/code/environments/
├── production/
│ ├── manifests/
│ │ └── site.pp
│ ├── modules/
│ │ ├── stdlib/
│ │ └── nginx/
│ ├── data/
│ └── Puppetfile
├── staging/
└── feature-loadtest/There are two approaches to building environments: directory environments, where you create folders manually, and branch-based environments, where environments are generated automatically from git branches. The second approach is what Code Manager and r10k use.
| Aspect | Directory Environments | Branch-Based Environments |
|---|---|---|
| Source of truth | Folders on the server | Git branches |
| Environment creation | Manual | Automatic by r10k / Code Manager |
| Reproducibility | Low | High, locked to a commit |
| Rollback | Hard | Easy, just revert the commit |
| Best for | Labs and experiments | Teams and production |
The basic convention is simple: every branch in the control repository becomes a Puppet environment. The main branch becomes the production environment, the staging branch becomes the staging environment, and every feature branch becomes its own environment with the same name.
git branch -a
# * main
# staging
# feature/loadtest
# feature/nginx-refactorWhen the feature/loadtest branch is pushed and deployed, r10k creates an environment with the same name. Nodes requesting a catalog for that environment get manifests from that branch's contents. That's the main advantage: every experiment is isolated without disturbing production.
Code Manager is a built-in Puppet Enterprise feature, while r10k is a Ruby gem tool used in Puppet open source. Both read the same sources: the git control repository and the Puppetfile. The difference lies in integration convenience and additional features.
| Aspect | r10k | Code Manager |
|---|---|---|
| License | Open source | Built into Puppet Enterprise |
| Configuration | Manual r10k.yaml | Via PE Console and puppet-code |
| Deploy trigger | CLI or cron | CLI, webhook, or API |
| Access control | Managed by the filesystem | Managed via PE RBAC |
| Post-deploy | Manual | Automatic, including cache clearing |
If you use open source, you install r10k via the Ruby gem and configure it with r10k.yaml.
:r10k:
:root: /etc/puppetlabs/code
:sources:
:control:
:remote: git@github.com:perusahaan/puppet-control.git
:basedir: /etc/puppetlabs/code/environmentsThe command to deploy all environments:
r10k deploy environment -pFor Puppet Enterprise users, the equivalent command is puppet-code deploy --all or calling the webhook endpoint POST /code-manager/v1/deploys from CI.
Tip
Use the -p (purge) flag so r10k removes old modules that are no longer in the Puppetfile. Without this flag, leftover old modules can pile up and cause resource conflicts that are hard to trace.
The Puppetfile is a Ruby DSL file at the root of the control repository that declares which modules are used and their versions. r10k and Code Manager read this file on every deploy to sync modules into the environment.
forge 'https://forge.puppet.com'
mod 'puppetlabs-stdlib'
mod 'puppetlabs-nginx', '5.5.0'
mod 'puppetlabs-apache', '11.2.0'
mod 'site_common',
git: 'https://github.com/perusahaan/puppet-site_common.git',
ref: 'v2.3.1'For modules from Puppet Forge, you just write the author-name and version. For internal company modules, you can point directly at the git repository and lock a specific ref or commit. This is what keeps reproducibility: the environment's contents are determined precisely by a single control repository commit.
You can also install all modules listed in the Puppetfile without a full environment deploy:
r10k puppetfile installA good workflow always starts from version control, not from the server. The standard flow used by Puppet teams in production:
main for production.production environment and let agents pick up the new catalog.r10k deploy environment feature/loadtest -p
r10k deploy environment production -pSince all code is versioned in git, rollback is just a matter of reverting a commit and redeploying with r10k deploy environment production -p. There's no more "who changed that file on the server yesterday".
Important
Make sure the control repository contains a manifests/site.pp or hiera that matches the server configuration. If the deployed environment is empty or fails to compile, agents pointing at that environment will fail to fetch a catalog and keep running the old configuration.
In this episode 12 you understood that git-based environment management is the foundation for managing Puppet code professionally. We covered the environment concept, mapping git branches to environments, the Code Manager (PE) vs r10k (open source) comparison, writing a Puppetfile to lock module versions, and a deploy workflow that supports fast rollback.
Key takeaways:
Well-controlled code is still not safe if the security layer is weak. In episode 13 we'll cover Learn Puppet - Authentication & Security, starting with SSL certificates, signing agent certificates, autosign, and continuing to RBAC and secret storage with Hiera eyaml.