Puppet client-server configuration

Puppet client-server configuration

Puppet Client-Server Configuration: A Comprehensive DevOps Guide

When managing infrastructure at scale, configuration drift becomes your worst enemy. Puppet solves this by enforcing desired state across hundreds of servers from a single master node. In this definitive tutorial, I'll walk you through setting up a production-grade Puppet 6 client-server architecture on CentOS 8 - exactly as I've implemented it for enterprise environments handling 500+ nodes.

Puppet's client-server model (unlike agentless tools like Ansible) provides continuous enforcement of configurations through a persistent agent that checks in with the master every 30 minutes by default. This makes it ideal for compliance-heavy environments where you need to guarantee configuration consistency across your fleet.

Prerequisites

  • Two or more CentOS 8 servers (minimum 2GB RAM for master, 1GB for agents)
  • Root or sudo privileges on all nodes
  • Static IP addresses for all servers
  • Basic familiarity with Linux system administration
  • Network connectivity between nodes (TCP port 8140 open)

For this guide, we'll use:

  • Master server: master.hakase-labs.io (10.5.5.21)
  • Agent server: agent01.hakase-labs.io (10.5.5.22)

Step 1: Puppet Pre-Installation

Before installing Puppet, we need to prepare our environment. This foundation work prevents 80% of the issues I see in production Puppet deployments.

1.1 Configure Hostnames and FQDN

Puppet relies heavily on proper DNS resolution. Misconfigured hostnames are the #1 cause of certificate signing failures.

# On master server
hostnamectl set-hostname master

# On agent server
hostnamectl set-hostname agent01

Edit /etc/hosts on both servers to include both nodes:

vim /etc/hosts
10.5.5.21    master.hakase-labs.io    master
10.5.5.22    agent01.hakase-labs.io   agent01

Verify the configuration:

hostname
hostname -f

Expected output on master:

master
master.hakase-labs.io

Restart the hostname service to apply changes:

systemctl restart systemd-hostnamed

1.2 Configure NTP with Chrony

Time synchronization is critical for Puppet's certificate authority. Even a 5-minute time difference will break certificate validation. I recommend using chrony over ntpd as it handles network interruptions better.

Install chrony on both servers:

dnf install chrony -y

Edit the configuration file:

vim /etc/chrony.conf

Replace the default pool with country-specific NTP servers (find yours at pool.ntp.org):

server 0.us.pool.ntp.org iburst
server 1.us.pool.ntp.org iburst
server 2.us.pool.ntp.org iburst
server 3.us.pool.ntp.org iburst

Start and enable the service:

systemctl start chronyd
systemctl enable chronyd

Verify synchronization:

chronyc tracking
chronyc sources -v

Look for "Leap status: Normal" and "Source state: Current" in the output.

1.3 Add Puppet Repository

Puppet isn't included in CentOS 8's default repositories. We'll add the official Puppet 6 repository:

sudo rpm -Uvh https://yum.puppet.com/puppet6-release-el-8.noarch.rpm

Verify the repository was added:

dnf repolist | grep puppet

Expected output:

puppet6           Puppet 6 Repository el 8 - x86_64

1.4 Disable SELinux

While Puppet can work with SELinux in enforcing mode, I recommend starting with it disabled to eliminate one variable during initial setup. You can re-enable it later after verifying your configuration works.

Edit the SELinux configuration:

vim /etc/sysconfig/selinux

Change the line to:

SELINUX=disabled

Reboot the server:

sudo reboot

After reboot, verify SELinux is disabled:

sestatus

Expected output:

SELinux status:                 disabled

Step 2: Install and Configure Puppet Server

The Puppet master (now called "Puppet Server" in version 6) is the central management node that compiles and serves configurations to agents.

2.1 Install Puppet Server

Install the puppetserver package:

sudo dnf install puppetserver -y

2.2 Configure Memory Allocation

The puppetserver service runs on the JVM, which needs proper memory allocation. The default configuration assumes 2GB RAM, which is often too much for lab environments.

Edit the service configuration:

vim /etc/sysconfig/puppetserver

Adjust the memory settings based on your available RAM:

  • For 2GB RAM: JAVA_ARGS="-Xms1g -Xmx1g"
  • For 4GB RAM: JAVA_ARGS="-Xms2g -Xmx2g"
  • For 8GB+ RAM: JAVA_ARGS="-Xms4g -Xmx4g"

Example for a 2GB server:

JAVA_ARGS="-Xms1g -Xmx1g -Djruby.logger.class=com.puppetlabs.jruby_utils.jruby.Slf4jLogger"

2.3 Configure Puppet Server Settings

Edit the main Puppet configuration file:

cd /etc/puppetlabs/puppet
vim puppet.conf

Add these configurations under the appropriate sections:

[master]
dns_alt_names = master.hakase-labs.io,puppet

[main]
certname = master.hakase-labs.io
server = master.hakase-labs.io
environment = production
runinterval = 1h

Key settings explained:

  • dns_alt_names: Additional names agents might use to connect to the master
  • certname: The name that will appear in certificates
  • server: The FQDN agents should use to connect
  • runinterval: How often agents check in (default is 30m)

2.4 Start Puppet Server

Enable and start the service:

systemctl enable puppetserver
systemctl start puppetserver

Verify it's running:

systemctl status puppetserver

Check the listening port:

ss -tulnp | grep 8140

Expected output:

tcp    LISTEN  0  100  *:8140  *:*  users:(("java",pid=1234,fd=42))

2.5 Configure Firewall

Puppet server listens on TCP port 8140. Add this to firewalld:

firewall-cmd --add-port=8140/tcp --permanent
firewall-cmd --reload

Verify the rule was added:

firewall-cmd --list-ports

Step 3: Install and Configure Puppet Agent

Now we'll configure our first agent node to connect to the master.

3.1 Install Puppet Agent

On the agent server, install the puppet-agent package:

sudo dnf install puppet-agent -y

3.2 Configure Puppet Agent

Edit the agent configuration:

cd /etc/puppetlabs/puppet
vim puppet.conf

Add these settings:

[main]
certname = agent01.hakase-labs.io
server = master.hakase-labs.io
environment = production
runinterval = 1h

3.3 Start Puppet Agent

Enable and start the agent service:

systemctl enable puppet
systemctl start puppet

Verify it's running:

systemctl status puppet

3.4 Sign Agent Certificate on Master

Puppet uses SSL certificates for authentication. The agent generates a certificate request that must be signed by the master.

On the master server, list pending certificate requests:

puppetserver ca list

Expected output:

Requested Certificates:
    agent01.hakase-labs.io (SHA256) 12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF

Sign the certificate:

puppetserver ca sign --certname agent01.hakase-labs.io

Verify the certificate was signed:

puppetserver ca list --all

Step 4: Verify Puppet Agent Configuration

Now let's verify the agent can successfully communicate with the master.

4.1 Test Agent Connection

On the agent server, run a manual Puppet run:

puppet agent -t

Expected output:

Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Caching catalog for agent01.hakase-labs.io
Info: Applying configuration version '1234567890'
Notice: Applied catalog in 0.01 seconds

If you see errors about certificate verification, run:

puppet agent --test --waitforcert 60

4.2 Check Reports on Master

On the master server, check the last run report for the agent:

puppetserver ca list --all
puppet node find agent01.hakase-labs.io

View the report:

puppet report list --node agent01.hakase-labs.io
puppet report show <report-hash>

Step 5: Create Your First Puppet Manifest

Now let's create a simple manifest to manage a file on our agent node.

5.1 Create Site Manifest

On the master server, create the main manifest directory structure:

mkdir -p /etc/puppetlabs/code/environments/production/manifests
cd /etc/puppetlabs/code/environments/production/manifests

Create a site manifest file:

vim site.pp

Add this content to manage the /etc/motd file:

node 'agent01.hakase-labs.io' {
  file { '/etc/motd':
    ensure  => file,
    content => "Welcome to ${fqdn}\nManaged by Puppet\n",
  }
}

5.2 Apply the Manifest

On the agent server, trigger a Puppet run:

puppet agent -t

Verify the file was created:

cat /etc/motd

Expected output:

Welcome to agent01.hakase-labs.io
Managed by Puppet

Common Pitfalls and Troubleshooting

Here are the most common issues I encounter when setting up Puppet, along with their solutions:

Certificate Issues

  • Problem: "Could not request certificate: getaddrinfo: Name or service not known"
    • Solution: Verify DNS resolution works in both directions. Check /etc/hosts and hostname -f output.
  • Problem: "Server hostname 'master.hakase-labs.io' did not match server certificate"
    • Solution: Ensure the master's certname in puppet.conf matches the certificate. Run puppetserver ca list --all to verify.

Time Synchronization Issues

  • Problem: "SSL_connect returned=1 errno=0 state=error: certificate verify failed"
    • Solution: Check time synchronization with timedatectl and chronyc tracking. Time differences >300 seconds will break SSL.

Firewall Issues

  • Problem: "Connection refused" when agent tries to connect
    • Solution: Verify port 8140 is open on the master: firewall-cmd --list-ports. Check connectivity with telnet master.hakase-labs.io 8140 from the agent.

Memory Issues

  • Problem: Puppet server fails to start with "Java heap space" errors
    • Solution: Reduce memory allocation in /etc/sysconfig/puppetserver. For 2GB RAM, use -Xms1g -Xmx1g.

How to Verify Your Puppet Setup

Use these commands to verify each component of your Puppet infrastructure:

Component Verification Command Expected Output
Master Service systemctl status puppetserver Active: active (running)
Agent Service systemctl status puppet Active: active (running)
Certificate Status puppetserver ca list --all Signed certificates for all agents
Agent Connection puppet agent -t No errors, catalog applied successfully
File Sync ls -l /etc/puppetlabs/code/environments/ production environment directory exists
Port Access telnet master.hakase-labs.io 8140 Connected successfully

Key Takeaways

  • DNS is critical: Puppet relies on proper hostname resolution. Always verify hostname -f and /etc/hosts before installation.
  • Time synchronization matters: Even small time differences will break SSL certificate validation. Use chrony for reliable NTP.
  • Memory allocation is important: The puppetserver service needs proper JVM memory settings. Start with 1GB for lab environments.
  • Certificate management is manual: Remember to sign agent certificates on the master with puppetserver ca sign.
  • Start simple: Begin with basic file resources before moving to complex modules. Verify each step before adding complexity.

FAQ

How do I add more agents to my Puppet master?

For each new agent:

  1. Install puppet-agent package
  2. Configure /etc/puppetlabs/puppet/puppet.conf with the master's FQDN
  3. Start the puppet service
  4. On master: puppetserver ca sign --certname <agent-fqdn>
  5. On agent: puppet agent -t

What's the difference between puppet apply and puppet agent?

puppet apply runs manifests directly on the local system without a master, while puppet agent connects to a master to retrieve and apply configurations. Use apply for testing manifests and agent for production environments.

How do I update Puppet to a newer version?

On CentOS 8:

# Update repository
sudo rpm -Uvh https://yum.puppet.com/puppet7-release-el-8.noarch.rpm

# Update packages
sudo dnf update puppetserver puppet-agent

# Restart services
sudo systemctl restart puppetserver
sudo systemctl restart puppet

How can I check when an agent last checked in?

On the master server:

puppet node find <agent-fqdn>

Look for the "last_run" timestamp in the output. For more detailed reporting:

puppet report list --node <agent-fqdn>

What's the best way to organize Puppet code?

I recommend this structure for production environments:

/etc/puppetlabs/code/environments/
└── production
    ├── manifests/          # Main manifests
    │   └── site.pp         # Node definitions
    ├── modules/            # Custom modules
    │   ├── apache/
    │   ├── mysql/
    │   └── ...
    └── hieradata/          # Hiera data
        ├── common.yaml
        └── nodes/
            └── agent01.yaml

This setup allows for environment-specific configurations and clean separation of code and data.

🛒 Recommended gear on Amazon

Disclosure: some links above are affiliate links — if you buy through them I may earn a small commission at no extra cost to you. Thanks for supporting the channel!

Post a Comment

Previous Post Next Post