Pages

Thursday, December 22, 2016

Red Hat Satellite 6.2 - Automatic configuration of Apache vhosts with Puppet

Overview

I have a need to deploy multiple RHEL 7.3 server with Apache, PHP and mod_ssl which was going to be front ended by an external load balancer. Each server runs the same php script that accepts a URL string and does stuff with the parameters that are passed. Nothing too fancy.  There are multiple 3rd parties that are sourcing the data over the internet.

The existing setup of this "app" is that we have a VM setup for each of the 3rd party sources and everytime another source is added, a new server is built.  This does not scale, is not sustainable and is not a good use of our resources.

I'm writing this post with the assumption that the reader already has a working Satellite environment running and knows how to do basic tasks within Satellite.

Warning!
Doing this stuff on a server that already has any apache configuration on it will cause all of that configuration to be deleted and replaced with what puppet thinks should be there.

The Plan

My plan is to:

  • Use Satellite to deploy and configure the new servers. 
  • I want to setup a vhost for each of the 3rd party sources.
  • I do not want to have to make a new puppet module every time we add a new source.
  • Vhosts need to be defined in a smart class variable
  • I want to have very minimal configuration happening during the kickstart/provisioning. I'd like puppet to ensure the correct things are installed, running and configured.

Starting Out

TLDR: My first attempt failed miserably and a custom puppet module wrapper is needed.

I found the official apache puppet module off of the puppet forge ( https://forge.puppet.com/puppetlabs/apache ) and downloaded the tar.gz.  Looked at the dependencies tab and saw that this module requires the Concat and stdlib modules. I already had those downloaded for other puppet modules I'm using.  

I uploaded those modules into a custom puppet repository that I have setup in my Satellite. Added the 3 modules to a content view I called "web servers" and published a new view. Once that was complete, I published it to the "dev" life cycle environment for the web servers content view.  

Next step is to create new host groups for the web servers. In the host group, I select all the puppet modules I need, apache and stdlib. (Concat is apparently not selectable but just needs to be in the content view)

Now I'm ready to provision a server to my new host group and see what happens.  After the install was complete, puppet errored out and did not apply any kind of configuration. Not shocking since just about every puppet module downloaded from the forge needs to be modified or messed with in some way before it'll work in Satellite.  It was also not shocking that there is just about zero information on configuring apache with puppet through Satellite anywhere on the internet or on the RH access.  

I put my 15 years of google foo experience to the test and was able to find some similar things people were doing which got me on my way.

The Solution

The apache module from the puppet forge is not created to run in an environment like Satellite. Because of this, I had to create a custom puppet module that acts as a "wrapper" that actually gets the information from the Satellite and passes it to the apache module.

  • To start off, sign into somewhere that has puppet installed and create a new module. This command will ask you questions and will create an empty module folder structure with a metadata file.
puppet module generate <yourname>-httpdwrapper
  • A new directory should created, called <yourname>-httpdwrapper.  cd into it and then cd into the manifests directory. Edit the init.pp file add some class information
class httpdwrapper {
        class { '::httpdwrapper::install': }
}


  • Save the file. Then create a new file called install.pp and put the following in it.

class httpdwrapper::install (
        $myvhosts = $httpdwrapper::params::myvhosts,
        )
{
create_resources(apache::vhost, $myvhosts)
}


  • Save the file. Then back up two directories so you're in the directory that has the <yourname>-httpdwrapper directory in it and build the module.  

puppet module build <yourname>-httpdwrapper


  • A new tar.gz file will show up in yourname-httpdwrapper/pkg. Download this and upload it to the custom puppet repository in Satellite.  
  • In the Satellite UI, browse to Configure > Smart Class Parameters
  • Search for myvhosts and select it
  • Select Overwrite
  • Change Keytype to hash
  • Put in some default vhost information into the default value field. The text field can be dragged down so you can see it easier.

host1:
  priority: '10'
  vhost_name: testvhost.domain.com
  port: '80'
  docroot: "/var/www/testvhost"

  • Submit the changes.
  • Go to the content view for the web servers, add the httpdwrapper module to the view, publish and promote.
  • Go to the host group for the web servers, add httpdwrapper::install and submit.
  • Edit the host group again, this time select the parameters tab. myvhosts should be listed there. Override the default values. Now you can put in as many hosts you want as well as any other vhost config options. See https://github.com/puppetlabs/puppetlabs-apache#defined-type-apachevhost for those options. Example:

bobsbait:
  priority: '10'
  vhost_name: bobbait.example.com
  port: '443'
  docroot: "/var/www/bobsbait"
  docroot_owner: apache
  docroot_group: apache
  ssl: true
somewebsite:
  priority: '10'
  vhost_name: somewebsite.example.com
  port: '80'
  docroot: "/var/www/somewebsite"
underconstruction:
  priority: '10'
  vhost_name: underconstruction.example.com
  port: '80'
  docroot: "/var/www/underconstruction"


  • Click submit. The next time puppet agent runs on the server, it should create a new conf file for each site in /etc/httpd/conf.d and create the web root.  I'm doing the devops!


I think that the create_resources puppet function can be used to pass information in a similar fashion to all the classes within the apache module, so I should be able to just make new variables in the httpdwrapper module and then be able to change them in the UI.

Hope this helps someone figure some stuff out.