Hardening SSH with Puppet

Picture of me

Author: Baden

May 15, 2025

Introduction

In today’s security landscape, leaving your infrastructure’s SSH configuration at its defaults is like locking your front door but leaving the key under the mat. As the most common remote access method on Unix-like systems, SSH is also a primary target for attackers. Configuration drift, weak policies, and human error can expose critical systems to brute-force attacks, privilege escalation, and compliance violations
In this article, we'll walk through how to enforce secure SSH configurations across your fleet using Puppet, with a focus on the official puppetlabs/ssh module.

🚀 Why Use Puppet for SSH Hardening?

Puppet allows you to:
SSH is a perfect use case: critical, ubiquitous, and frequently misconfigured.

🔧 Key SSH Security Settings

Here are some of the most important SSH settings you may want to enforce. Of course, every enviroment is different so feel free to modify.
Setting Recommended Value Reason
PermitRootLogin no or prohibit-password Prevents direct root access
PasswordAuthentication no Forces use of SSH keys
X11Forwarding no Minimizes attack surface
MaxAuthTries 3 Reduces brute-force risk
AllowUsers Specific accounts Controls login access
LogLevel VERBOSE Improves audit trail
ClientAliveInterval 300 Auto-closes idle sessions

📦 Using the saz/ssh Module

Instead of managing raw files or templates, the saz/ssh module provides a clean, structured interface to manage both SSH client and server settings with native Puppet resources.
Make sure to check out the Puppet Forge page here before installing anything.
After checking the module out, install the module from Puppet Forge by adding it to your Puppetfile:
                
mod 'saz-ssh', '13.1.0' # Check Forge for the latest version
      
    

✏️ Example: Harden SSH with Puppet

Here’s how to lock down SSH on all your servers using the saz/ssh class:
                
class { 'ssh':
    server_options => {
        'PermitRootLogin'        => 'no',
        'PasswordAuthentication' => 'no',
        'X11Forwarding'          => 'no',
        'MaxAuthTries'           => '3',
        'AllowUsers'             => 'adminuser',
        'ClientAliveInterval'    => '300',
        'LogLevel'               => 'VERBOSE',
    },
}      
      
    
This simple class call will:
You can also manage SSH client options using the client_options parameter if needed.

📍 Using Hiera for Clean Configuration

To keep your Puppet code tidy and environment-aware, use Hiera to define SSH settings:
                    
ssh::server_options:
    PermitRootLogin: 'no'
    PasswordAuthentication: 'no'
    X11Forwarding: 'no'
    MaxAuthTries: '3'
    AllowUsers: 'adminuser'
    ClientAliveInterval: '300'
    LogLevel: 'VERBOSE'                      
          
        

🧪 Validation and Safety

Before restarting the SSH service after applying Puppet changes, always validate the syntax:
                    
sshd -t                    
          
        
This will test the current SSH security settings to ensure it works as expected.

🧠 Final Thoughts

Security shouldn’t be optional or manual. By using the saz/ssh module with Puppet, you make SSH hardening automatic, scalable, and consistent. From disabling root login to enforcing SSH key-based auth and reducing brute-force risk, every tweak helps close the door to attackers—without extra work from your ops team. Make security the default, not an afterthought. Let Puppet enforce it for you.