Virtualization

Automatically Deploy Puppet Agent on VMWare Templates

Learn how to auto-deploy Puppet Agent on VMware templates using simple run once commands for streamlined configuration management.

By InventiveHQ Team

The short answer

To auto-deploy the Puppet agent on VMware clones, attach a list of run-once commands to the vCenter guest customization specification: download the Puppet agent, install it silently while passing your Puppet master's FQDN, then force a first puppet agent -t check-in. The commands run once, the first time each customized clone boots, so every VM installs the agent and registers itself with the Puppet master with zero manual steps. The one rule that saves you from a support ticket: never let the Puppet agent actually run inside the template — if it does, it bakes a fixed certificate name into the image and every clone shows up as the same node.

That's the summary an AI overview would give you. The rest of this article is the part it can't: the exact commands, why the certname collision happens and how to avoid it, how the Puppet master signs certificates from brand-new clones (autosign vs. manual CSR approval), and how the same pattern maps to Linux templates with cloud-init.

The lifecycle: from golden template to converged node

Before the commands, hold the whole flow in your head. Auto-deploying Puppet on a template is really five stages — and the failure everyone hits lives between stages two and three.

Puppet agent auto-deploy flow on VMware templates Five stages: prepare the template with the agent installed but not started, clone the VM, guest customization runs first-boot commands that register the clone with the Puppet master, the master autosigns or an admin approves the certificate request, and finally the agent converges by applying its catalog. A pulse travels along the path from left to right. One template, many self-registering nodes Prepare template Clone First boot Sign cert Con- verge Install agent, do NOT run it Unique hostname per clone Run-once / cloud-init CSR Autosign or admin approves Catalog applied certname must stay unique

The commands below live in stage 3 (first boot). Everything after — the Puppet master signing the certificate and the agent applying its catalog — happens on the master side. Get stages 1 and 2 right and the rest is mechanical.

Explanation

When you deploy a VMWare template, you have the option to create a customization specification. You can add a command to this customization specification to automatically deploy the puppet agent, after the template has finished deploying.

One of the options in your customization specification is a run once command. Or really, it is a list of run once commands. There are three things you need the run once script to do:

  • Download the Puppet Agent

  • Install the Puppet Agent

  • Trigger an immediate puppet run

In the following sections, I will show the commands you need to run to accomplish the three objectives above.

Download the Puppet Agent

First, you want to download the puppet agent by using this command:

Copy Code
```

powershell "new-item C:\install -type directory; (new-object System.Net.WebClient).DownloadFile('https://downloads.puppetlabs.com/windows/puppet-agent-x64-latest.msi','C:\install\puppet-agent-x64-latest.msi')"


The run once commands in VMWare are using the regular windows command shell, so we have to call powershell to get [access to the powershell](https://inventivehq.com/blog/powershell-vs-cmd-complete-command-line-guide) cmdlets. Next, we pass the powershell commands into powershell.exe to actually download the puppet agent. The above command is actually two different powershell commands separated by semi-colons.

The first command is ensuring the C:\install folder exists.

    Copy Code
    ```
#Create C:\install folder
new-item C:\install -type directory

The second command downloads the latest version of the puppet agent, and saves it to the C:\install folder:

Copy Code
```

(new-object System.Net.WebClient).DownloadFile('https://downloads.puppetlabs.com/windows/puppet-agent-x64-latest.msi','C:\install\puppet-agent-x64-latest.msi')"


Powershell can't natively download a file from a web URL, so we have to use the new-object cmdlet and import the system.net.webclient library from the .net framework. We are then able to call the downloadfile function. The downloadfile function takes two inputs, the source of the file, and where to save the file to. In our case, the source of the file is: https://downloads.puppetlabs.com/windows/puppet-agent-x64-latest.msi and the destination file is: C:\install\puppet-agent-x64-latest.msi
Advertisement

Install the Puppet Agent

Now that the appropriate installer is downloaded, we need to silently install the puppet agent with this command (Be sure to replace mypuppetserver.mydomain.com with your actual puppet server FQDN):

Copy Code
```

msiexec /qn /i C:\install\puppet-agent-x64-latest.msi PUPPET_MASTER_SERVER="mypuppetserver.mydomain.com"


This command is calling the msiexec command with the /qn option to make it run silently. We then use the PUPPET_MASTER_SERVER argument to set the puppet master we want to use for this server.

💡 Also See: How to [use Vagrant with VMWare Vcenter](https://inventivehq.com/blog/how-to-use-vagrant-with-vmware-vcenter)!

## Using Chocolatey

As an alternative to downloading and installing the puppet agent as outlined above. If you have chocolatey installed, you can use the choco commands to install the puppet agent. The command to do it using chocolatey is:

    Copy Code
    ```
`choco install puppet-agent -installArgs '"PUPPET_MASTER_SERVER=mypuppetserver.mydomain.com"'`

Be sure you replace "mypuppetserver.mydomain.com" with the proper FQDN of your puppet server.

If you don't have chocolatey installed, you can checkout our article on how to install chocolatey. As you can see, installing this with Chocolatey is a little easier than the alternative.

Force Puppet Agent to Run

Now that we have installed the puppet agent, we need to trigger a puppet agent run so your machine will checkin with puppet, and start applying whatever is in the node definition. Since puppet was just installed, the puppet command may not yet be available in the existing command shell. For this reason, we need to open a new command shell by using the cmd /c command. Here is an example of how you would force a run of the puppet agent right now:

Copy Code
```

cmd.exe /c "puppet agent -t"


puppet agent -t is the command to test the puppet agent. It also happens to be the easiest way to force the puppet agent to check-in immediately.

## The rule that trips everyone: keep the certname unique

Here is the failure mode that turns "auto-deploy Puppet" into a support ticket. The Puppet agent identifies itself to the master with a **certname** and a matching SSL certificate. Those are generated the first time the agent *runs* — not when it's installed. If the agent runs even once inside your golden template, that certname and certificate get baked into the image. Every VM you clone then presents the same identity, and they all collide on a single node definition on the master.

The run-once approach in this article sidesteps the problem by design: nothing runs until vCenter guest customization has already given each clone its own unique hostname, so each clone requests its own certificate. If you'd rather pre-install the agent into the template to speed up first boot, that's fine — just install it and **stop there**. Do not start the `puppet` service and do not run `puppet agent -t` before you seal the template. Leave the actual first run to the clone.

If you've already contaminated a template, clear the agent's SSL state on each affected clone (`C:\ProgramData\PuppetLabs\puppet\etc\ssl` on Windows, `/etc/puppetlabs/puppet/ssl` on Linux), then run the agent again so it requests a fresh, unique certificate.

## Signing the certificate: autosign vs. manual approval

Registering is only half the handshake. When a new clone runs `puppet agent -t` it generates a **certificate signing request (CSR)** and sends it to the master — but the master has to *sign* that request before the agent can pull its catalog. You have two options:

- **Manual approval** — on the master, list pending requests and sign them: `puppetserver ca list` then `puppetserver ca sign --certname <name>`. Safe, but it means a human has to act before each new clone converges, which defeats the point of full automation.
- **Autosigning** — the master signs matching requests automatically. *Naive* autosigning (`autosign = true`, or a whitelist of `*.mydomain.com`) trusts any request on your domain and is a security risk on shared networks. **Policy-based autosigning** — a custom executable that inspects the CSR (for example, a pre-shared token baked into a custom CSR extension) and exits 0 only if it's valid — gives you hands-off provisioning without blindly trusting the network.

For a template you clone constantly, policy-based autosigning is the piece that makes the whole flow truly zero-touch.

## Doing the same thing on Linux templates

The Windows run-once mechanism has no direct Linux equivalent, but the pattern is identical. Use **cloud-init** (or a VMware `guestinfo` first-boot script) to run the same three logical steps after the clone gets its unique hostname:

```yaml
#cloud-config
runcmd:
  - curl -fsSL https://apt.puppet.com/puppet8-release-$(lsb_release -cs).deb -o /tmp/puppet.deb
  - dpkg -i /tmp/puppet.deb && apt-get update
  - apt-get install -y puppet-agent
  - /opt/puppetlabs/bin/puppet config set server mypuppetserver.mydomain.com --section main
  - /opt/puppetlabs/bin/puppet agent -t

The same certname rule applies: cloud-init runs on first boot of the clone, after the hostname is set, so each machine requests its own certificate. Never run the agent in the source image.

Auto-deploy readiness checklist

Before you seal the template and start cloning, walk this checklist. It's the difference between "every clone self-registers" and "every clone is the same broken node."

StepWhat to doWhy it matters
1. Install, don't runPre-install the agent in the template or leave install to first boot — but never run puppet agent -t inside the templateRunning the agent bakes a certname/SSL cert into the image, causing clone collisions
2. No baked SSLConfirm the template's Puppet ssl directory is emptyAny leftover certificate is inherited by every clone
3. Unique hostnameLet vCenter guest customization set a unique hostname before Puppet runsThe certname derives from the hostname; identical hostnames = identical certnames
4. Run-once / cloud-initAdd the download → install → puppet agent -t commands to the customization spec (Windows) or cloud-init (Linux)This is what makes registration automatic on first boot
5. Set the master FQDNPass PUPPET_MASTER_SERVER (install) or server = (config) with your real Puppet master FQDNThe agent has to know where to send its CSR and pull its catalog
6. Fresh shell for the runWrap the run as cmd.exe /c "puppet agent -t" on WindowsThe installing shell has a stale PATH and can't find the new puppet binary
7. Signing policyEnable policy-based autosigning or plan manual CSR approvalWithout a signed cert the agent registers but never converges
8. Verify on the masterAfter the first clone boots, confirm the node appears and its catalog appliedConfirms the whole loop — install, register, sign, converge — actually works

Summary

To summarize, you need to add the three following commands to the run once section of your VMWare customization specification:

Copy All Commands
```

Step 1: Download the Puppet Agent MSI installer

powershell "new-item C:\install -type directory; (new-object System.Net.WebClient).DownloadFile('https://downloads.puppetlabs.com/windows/puppet-agent-x64-latest.msi','C:\install\puppet-agent-x64-latest.msi')"

Step 2: Silently install Puppet Agent and configure the Puppet Master server

msiexec /qn /i C:\install\puppet-agent-x64-latest.msi PUPPET_MASTER_SERVER="mypuppetserver.mydomain.com"

Step 3: Force immediate puppet run to register with Puppet Master

cmd.exe /c "puppet agent -t"


⚠️ Note: Be sure to fill in the proper address for your puppet server on the second line

If you add the three above commands to the run once section of your customization template, your puppet agent should automatically install the first time someone logs into the server.

Frequently Asked Questions

How do I automatically install the Puppet agent when a VMware VM is cloned?

Add a list of run-once commands to the vCenter guest customization specification you apply at clone time. On Windows the three commands are: download the Puppet agent MSI with PowerShell's WebClient, install it silently with msiexec while passing PUPPET_MASTER_SERVER set to your Puppet master's FQDN, then run "puppet agent -t" to force a first check-in. The commands fire the first time the customized guest boots and logs in, so every cloned VM installs and registers itself without manual work.

Should I bake the Puppet agent into the VMware template or install it at first boot?

Either works, but with one hard rule: never let the agent generate a certificate or run inside the template. If you pre-install the agent in the golden image, install it but do NOT start the puppet service or run "puppet agent -t" before you seal the template. If the agent runs in the template it locks in a certname and SSL certificate that every clone then shares, causing certificate collisions on the Puppet master. Installing fresh at first boot via run-once commands sidesteps this entirely because nothing runs until the clone has its own unique hostname.

Why do all my cloned VMs show up as the same node in Puppet?

Because the Puppet agent ran inside the template and baked a fixed certname and SSL certificate into the image before it was cloned. Every clone inherits that identity, so they all present the same certificate to the master and fight over one node definition. The fix is to seal the template without ever running the agent, and let the first-boot / run-once step run "puppet agent -t" only after guest customization has given each clone its own unique hostname. If templates were already contaminated, clear /etc/puppetlabs/puppet/ssl (or the Windows equivalent) on each clone and re-request a certificate.

How does the Puppet master approve certificates from newly cloned VMs?

When a new agent runs for the first time it generates a certificate signing request (CSR) and sends it to the master. The master must sign that CSR before the agent can pull its catalog. You either approve requests manually with "puppetserver ca sign --certname <name>", or you enable autosigning so the master signs matching requests automatically. Policy-based autosigning (a custom script that validates the request) is far safer than naive autosigning that trusts every request on your domain.

What is the run once command in a VMware customization specification?

Run-once commands are a list of commands that vCenter executes exactly one time, the first time a customized guest boots. They run through the regular Windows command shell (cmd), so to use PowerShell cmdlets you have to explicitly call powershell.exe. They are ideal for post-clone provisioning tasks such as downloading and installing an agent, joining a domain, or forcing a configuration-management check-in.

Can I install the Puppet agent with Chocolatey in a run once command?

Yes. If Chocolatey is present on the template, a single run-once command handles it: choco install puppet-agent -installArgs '"PUPPET_MASTER_SERVER=mypuppetserver.mydomain.com"'. This is cleaner than the manual download-and-msiexec approach because Chocolatey resolves the latest package and handles the install arguments for you. Replace the FQDN with your own Puppet master.

How do I do the same thing on Linux VMware templates?

Use cloud-init or a VMware guestinfo / first-boot script instead of Windows run-once commands. The script installs the puppet-agent package (from the Puppet platform repo), writes the master's FQDN into /etc/puppetlabs/puppet/puppet.conf under [main] as "server = mypuppetserver.mydomain.com", then runs "puppet agent -t". As on Windows, make sure the agent has never run in the template so each clone requests its own certificate after cloud-init sets a unique hostname.

Why does 'puppet agent -t' fail right after installing the agent?

Usually because the puppet binary is not yet on the PATH of the shell that just installed it. The MSI adds Puppet to the system PATH, but the shell that ran the install already captured the old PATH, so it cannot find the command. Open a fresh shell for the run — on Windows wrap it as cmd.exe /c "puppet agent -t". The other common cause is that the master has not signed the agent's CSR yet, which shows as the agent waiting for its certificate.

Advertisement