# Roles-and-profiles best practices for apache vhosts?

I'm running into a lot of problems trying to figure out the "right way" to implement the roles-and-profiles model. All the examples I've found on the web are simplified, idealized examples that don't really discuss how to actually derive separate and independent "profiles" and functional modules for your server functionality.

My specific instance in this case is apache vhosts: In building a configuration for a server that manages yum repos via the "mrepo" software and provides access to them via apache, it's easy to see that you have a profile for a web server and a profile for the yum repo management via mrepo. However, where does the vhost fall in? Is it part of, or derived from, the web server profile, even though it's specific to the yum repo management? Is it part of the yum repo management profile, even though it's technically not part of the mrepo technology that is supposed to be defined by that profile?

I can see three ways to implement this:

1) the vhost is defined in a sub-profile of the web server profile:

class profile::webserver::yum {
apache::vhost { "yum":
…
}
}


2) the vhost is defined directly as part of the mrepo server profile

class profile::mrepo_server {
…
apache::vhost { "yum":
…
}
}


3) the vhost is defined as an independent profile

class profile::yum_web_access {
apache::vhost { "yum":
…
}
}


None of these seem really palatable to me. The first example (profile::webserver::yum) is the closest to acceptable, but that involves modifying the webserver profile (in a logical sense, anyway, since all the profiles are in the same module anyway) as part of building other technologies, which seems wrong.

Edit: Or maybe I'm completely off-base here? Should my webserver and mrepo_server "profiles" actually be component modules, and I really just have one profile for my yum server? ... Sigh. This is an example of how confused I am about how this model should be applied to a real problem.

Alternately, if anyone has any links to real-world implementations of the roles-and-profiles model, in an environment that was not constructed just to play nice with that model, that would be tremendously helpful in figuring this stuff out.

edit retag close merge delete

Sort by » oldest newest most voted

If you start with the role, I believe role/profile maker more sense. You role is a yum server. That's what the server does. Now we add our reusable profiles to create the role.

class role::yum_server {

include ::profile::apache
include ::profile::mrpeo
}


I'm a fan of using create_resources to add things like vhosts, users, anything you may have more than on of.

---
apache::vhosts:
yum.example.com: {}


modules/profile/manifests/apache.pp

class profile::apache {

include ::apache
include ::collectd
include ::logrotate
include ::sslcerts

collectd::plugins { 'apache': }
logrotate::simple { 'apache'': }

$myvhosts = hiera('apache::vhosts', {}) create_resources('apache::vhost',$myvhosts)

Sslcerts::Cert<||> -> Class['apache::service']
}


Keep in mind that this is just one way to do it. Profiles are where youget to be opinionated. They are your least shareable code with other people IMO. This answer might be helpful as well, https://ask.puppetlabs.com/question/5...

more

Thank you. I'm not going to use create_resources, since i feel that hides some of what's going on in a way that the other folks on my team might not follow, but having a separate web server profile is the way i ended up going.

( 2015-08-09 17:00:04 -0600 )edit

In this case, both things go together. The web server is useless without mrepo and mrepo is useless without a web server. You application stack requires both working together.

So the answer is, you configure all the components required to setup your Yum server into a single profile. For example,

class profiles::yum_server {
include apache
class { 'mrepo::params':
src_root       => '/vol/repos',
www_servername => $::fqdn, } mrepo::repo { "centos6-x86_64": ensure => present, update => "nightly", repotitle => "CentOS 6.6 64 bit", arch => "x86_64", release => "6.6", urls => { os => 'rsync://mirrors.kernel.org/centos/$release/$repo/$arch/',
extras      => 'rsync://mirrors.kernel.org/centos/$release/$repo/$arch/', scl => 'rsync://mirrors.kernel.org/centos/$release/SCL/$arch/', updates => 'rsync://mirrors.kernel.org/centos/$release/$repo/$arch/',
}
}

mrepo::repo { "epel6-x86_64":
ensure    => present,
update    => "nightly",
repotitle => "EPEL 6 64 bit",
arch      => "x86_64",
release   => "6",
urls      => {
epel         => 'rsync://rsync.mirrorservice.org/dl.fedoraproject.org/pub/$repo/$release/$arch/', } } }  Ideally, the data should not be hard coded and come from hiera instead. A more complex example, class profiles::wordpress {$mysql_root_pw = hiera('profiles::wordpress::mysql_root_pw')
$docroot = hiera('profiles::wordpress::docroot')$wp_user       = hiera('profiles::wordpress::user')
$wp_pass = hiera('profiles::wordpress::pass')$wp_group      = hiera('profiles::wordpress::group')
$db_name = hiera('profiles::wordpress::db_name')$db_user       = hiera('profiles::wordpress::db_user')
$db_pass = hiera('profiles::wordpress::db_pass') include vsftpd user {$wp_user:
ensure     => present,
password   => $wp_pass, gid =>$wp_group,
managehome => true,
}

group { $wp_group: ensure => present, } file { '/etc/ftpusers': ensure => file, } file_line { 'wordpress user access': ensure => present, path => '/etc/ftpusers', line =>$wp_user,
}

include apache
include apache::mod::php
class { 'mysql::server':
root_password => $mysql_root_pw, } class { 'mysql::bindings': php_enable => true, notify => Class['::apache::service'], } apache::vhost {$::fqdn:
docroot        => $docroot, manage_docroot => false, } class { '::wordpress': install_dir =>$docroot,
wp_owner    => $wp_user, wp_group =>$wp_group,
db_name     => $db_name, db_user =>$db_user,
db_password => $db_password, } }  And the hiera data for that profile would be, --- profiles::wordpress::mysql_root_pw: 'hohmaeluomauZohbeo7TohraeWucaiz8' profiles::wordpress::docroot: '/opt/www' profiles::wordpress::user: 'wordpress' # Password is 'wordpress' profiles::wordpress::pass: '$1$l8yDV3Ix$ttcq0gAsV57xEtAE2Ef180'
profiles::wordpress::group: 'wordpress'
profiles::wordpress::db_user: 'wordpress'
profiles::wordpress::db_name: 'wordpress'

more

Thank you for the detailed answer. After considering both, I went with ramindk's 's model; that seems to better fit how i'm thinking about the profiles (I realized we're going to have many different apps with web server front ends, so it makes sense to me for web server to be a different profile)

( 2015-08-09 16:58:55 -0600 )edit