Category Archives: Puppet

Using Puppet to host a private RPM repository

A repository is a place where files are stored, indexed, and available through a package manager to anyone who has the repository information. With rpm based systems, a repository is created with a tool called createrepo. Most of the time, publicly available repositories already offer the packages your server needs. When you have a custom application you want to deploy (or even rebuild an existing application with your patches), it is best to distribute that package with a repository rather than a file share or some other means. Often a folder structure is created so that differing client OS versions can connect to the same repository and access versions compiled to that specific release. In my example below, I am not creating this folder structure as I am only serving one major release – Centos 7 – and the packages I am generating are website directories which are just a collection of portable code.

A private repository is not a tricky feat – all you have to do is serve the repository via https and require http basic authentication. You then configure the clients to connect to the repository with the basic authentication in the URL string (i.e. baseurl= The HTTPS protocol is not required to serve a repository, but it does prevent network snoopers from seeing your repository credentials.

Now that we know what is needed for a private repository, we can then define it in our puppet code.

node '' {

  file { '/var/yumrepos':
    ensure => directory,

  createrepo { 'yumrepo':
    repository_dir => '/var/yumrepos/yumrepo',
    repo_cache_dir => '/var/cache/yumrepos/yumrepo',
    enable_cron    => false, #optional cron job to generate new rpms every 10 minutes

  package { 'httpd':
    ensure => installed,

  httpauth { 'repouser':
    ensure    => present,
    file      => '/usr/local/nagios/etc/htpasswd.users',
    password  => 'some-long-password',
    mechanism => basic,
    require   => Package['httpd'],

  file { '/usr/local/nagios/etc/htpasswd.users':
    ensure => file,
    owner  => 'nginx',
    mode   => '0644',

    manage_repo    => true,
    package_source => 'nginx-mainline',

    www_root             => '/var/yumrepos/yumrepo',
    index_files          => [],
    autoindex            => 'on',
    rewrite_to_https     => true,
    ssl                  => true,
    auth_basic           => 'true',
    auth_basic_user_file => '/usr/local/nagios/etc/htpasswd.users',
    ssl_cert             => "/etc/puppetlabs/puppet/ssl/public_keys/$::fqdn.pem",
    ssl_key              => "/etc/puppetlabs/puppet/ssl/private_keys/$::fqdn.pem",
    vhost_cfg_prepend    => {
      'default_type'     => 'text/html',


For the above code to work, we need the required modules:

mod 'palli/createrepo', '1.1.0'
mod "puppet/nginx", "0.4.0"
mod "jamtur01/httpauth", "0.0.3"

We can then use the following declaration on our nodes to use this repository.

yumrepo {'private-repo':
  descr           => 'My Private Repo - x86_64',
  baseurl         => '',
  enabled         => 'true',
  gpgcheck        => 'false',
  metadata_expire => '1',

You now have a fully functional private repository – deploy your awesome software.

Deploying Puppet Open Source

In this guide we will go over best practices to deploy Puppet Open Source using the recommended workflow (r10k), PuppetDB, and the foreman. You can deploy Puppet server on any of their supported *nix distributions. In this tutorial we will assume it to be on CentOS 7 as this seems to have the best support. Continue reading Deploying Puppet Open Source

First puppet module published

I completed my first public module for puppet and submitted it to the puppet forge. It seems too simple to compile into a build and submit it to the forge; however, I made it public for these reasons:

  1. I needed experience with puppet code testing. This helped me at the most basic level.
  2. I felt like someone else could benefit from the code – even if it is one person.
  3. I wanted to do it.

Still, the code seems too juvenile to be submitted to the forge. All it does is take the hostname of a Digital Ocean droplet and submit its IP address as a new DNS record inside of Digital Ocean DNS. The code is located here.

I almost want to follow up with this and develop my duplicity module into reusable code for the community.

Securing PWM

In last week’s post we set up PWM insecurely. In this post, we are going to secure it down and install mysql to store the reset questions. This guide assumes you have this CentOS 7 server publicly accessible with ports 80 and 443 available to the entire world. First, we will need to install mysql, set up a database, and add a user to that database. To do that, we need to edit our manifest.pp and append the following:

 class { '::mysql::server':
     root_password           => 'My4cc0unt$$password!',
     remove_default_accounts => true,
     package_name            => 'mariadb-server',
     package_ensure          => 'installed',
     service_name            => 'mariadb',

 mysql::db { 'pwm':
     user     => 'pwm',
     password => 'pwm_passworD2!', # Can't do a password hash here :(

 class { 'mysql::bindings':
     java_enable => true,

file { '/opt/tomcat8/pwm/lib/mysql-connector-java.jar':
     ensure  => link,
     target  => '/usr/share/java/mysql-connector-java.jar',
     require => Class['mysql::bindings']

We will also need to install additional modules: Continue reading Securing PWM

Password management portal for end users

We in IT have heard it often, the #1 request coming into help desk ticket systems is password resets, account lockouts, and the like. PWM is a password reset web application written in Java for use with LDAP directories. You can configure it to work with Active Directory, OpenLDAP, FreeIPA, and others. There are already a handful of good tutorials on how to set up PWM (I think of this one in particular); however, I want to demonstrate the puppet apply command in this tutorial.


This guide assumes you have an Active Directory server with TLS set up (to change passwords) which is beyond the scope of this post. It also assumes you have a CentOS 7 instance which can communicate to the Active Directory server. It also assumes this is in an environment without a puppet master/server. The end manifest can be uploaded to a master and used that way.

Continue reading Password management portal for end users

Puppet with Mac and GNU/Linux

Puppet on Mac is a mixture of Puppet on Linux and Windows. Registry settings are called “secrets” and to make things easier, you need to install homebrew.

Enforcing a local admin is a little bit tedious. In the past few OSX releases, the have changed their password hashing algorithm several times. This causes a few case statements based on release version in order to set up one single local admin.

Continue reading Puppet with Mac and GNU/Linux

Puppet with Windows

Using Puppet on Windows workstations can be a challenge. The different architectures (x86 and x86_64) can have an impact on declaring packages. I have decided to ignore 32 bit systems and treat all as 64 bit – after all, it is 2016 and 32 bit should not be deployed.
Continue reading Puppet with Windows

Puppet as a GPO replacement

When you have a mixed client workstation environment (Windows, Linux, Mac) using GPOs only covers a portion of the environment. Sure, there are some AD plugins for Mac and Linux to let them read and apply those settings, however, those tools cost an exuberant amount of money compared to the open source version Puppet.
Continue reading Puppet as a GPO replacement

Why I went with Puppet over other CMEs

Configuration management engines (CME) have increased in popularity over the past several years. When I evaluated all the potential options, I needed one to be free in cost, work on Mac and Windows, and be easy to set up and use. At the time, only Chef, CFEngine, and Puppet had Windows clients so I tested them all out. Puppet came the victor for several reasons:
Continue reading Why I went with Puppet over other CMEs