Foreman is a complete lifecycle management tool for physical and virtual servers. We give system administrators the power to easily automate repetitive tasks, quickly deploy applications, and proactively manage servers, on-premise or in the cloud.
Requirements
For HA I recommend at least 8 nodes making the assumption that some of the components are still SPOF:
foreman-ha – 10.0.0.20 – Floating IP for LB1/2
foremanlb01 – 10.0.0.18 – Active LB node
foremanlb02 – 10.0.0.19 – Passive LB node
foremanui01 – 10.0.0.16 – Foreman and Puppet master node
foremanui02 – 10.0.0.17 – Foreman and Puppet master node
foremandb01 – 10.0.0.15 – PostgreSQL database for Foreman UI (SPOF)
memcached01 – 10.0.0.14 – Caching instance for Foreman UI (SPOF)
puppetdb01 – 10.0.0.13 – PuppetDB to point to Puppet 01/02 (SPOF)
puppetca01 – 10.0.0.12 – Puppet CA node to manage certificate requests (SPOF)
I won’t get into details how to cluster SPOF components but it should be quite easy to achieve. All nodes are running CentOS 7.2 minimal to save on space.
Installation
Install Puppet, Foreman and EPEL repo on all nodes.
[main]# Where Puppet's general dynamic and/or growing data is keptvardir= /var/lib/puppet
# The Puppet log directory.# The default value is '$vardir/log'.logdir= /var/log/puppet
# Where Puppet PID files are kept.# The default value is '$vardir/run'.rundir= /var/run/puppet
# Where SSL certificates are kept.# The default value is '$confdir/ssl'.ssldir= /var/lib/puppet/ssl
# Allow services in the 'puppet' group to access key (Foreman + proxy)privatekeydir=$ssldir/private_keys {group= service }hostprivkey=$privatekeydir/$certname.pem {mode= 640 }# Puppet 3.0.x requires this in both [main] and [master] - harmless on agentsautosign=$confdir/autosign.conf {mode= 664 }show_diff=truereports= foreman
# Use specified CA serverca_server= foreman-ha.example.com
dns_alt_names= foreman,puppet,foreman.example.com,foreman-ha.example.com,puppetca01.example.com
environmentpath= /etc/puppet/environments
basemodulepath= /etc/puppet/environments/common:/etc/puppet/modules:/usr/share/puppet/modules
[agent]# The file in which puppetd stores a list of the classes# associated with the retrieved configuration. Can be loaded in# the separate ``puppet`` executable using the ``--loadclasses``# option.# The default value is '$statedir/classes.txt'.classfile=$statedir/classes.txt
# Where puppetd caches the local configuration. An# extension indicating the cache format is added automatically.# The default value is '$confdir/localconfig'.localconfig=$vardir/localconfig
# Disable the default schedules as they cause continual skipped# resources to be displayed in Foreman - only for Puppet >= 3.4default_schedules=falsereport=truepluginsync=truemasterport= 8140
environment= production
certname= puppetca01.example.com
server= foreman-ha.example.com
listen=falsesplay=falsesplaylimit= 1800
runinterval= 1800
noop=falseconfigtimeout= 120
usecacheonfailure=true[master]autosign=$confdir/autosign.conf {mode= 664 }ca=truessldir= /var/lib/puppet/ssl
certname= foreman-ha.example.com
parser= current
strict_variables=false
Run Puppet master
Let Puppet create the CA certificate
1
puppet master --no-daemonize --verbose
If successful Ctrl+C and run Puppet master service. It is recommended that you run Puppet via proper web-server (Apache+mod_passenger for example). So next we install them.
Install Apache HTTPd + mod_passenger
Install Apache HTTPd and mod_passenger
1
yum -y install httpd mod_passenger
Web server configuration
Create a configuration file for Puppet master to run over HTTP. We’re going to do SSL Offloading at LB level.
Apache HTTPd configuration
1234567891011121314151617181920212223242526272829
Listen *:8139
<VirtualHost *:8139>
ServerName puppet-http
## Vhost docroot DocumentRoot "/etc/puppet/rack/public/"## Directories, there should at least be a declaration for /etc/puppet/rack/public/ <Directory "/etc/puppet/rack/public/">
AllowOverride None
Require all granted
PassengerEnabled On
Order deny,allow
Deny from all
Allow from foreman-ha.example.com foremanlb01.example.com foremanlb02.example.com 127.0.0.1 ::1
</Directory>
## Logging ErrorLog "/var/log/httpd/puppet-http_error.log" ServerSignature Off
CustomLog "/var/log/httpd/puppet-http_access.log" combined
## Custom fragment# Obtain Authentication Information from Client Request Headers SetEnvIf X-Client-Verify "(.*)"SSL_CLIENT_VERIFY=$1 SetEnvIf X-SSL-Client-DN "(.*)"SSL_CLIENT_S_DN=$1</VirtualHost>
[main]# Where Puppet's general dynamic and/or growing data is keptvardir= /var/lib/puppet
# The Puppet log directory.# The default value is '/log'.logdir= /var/log/puppet
# Where Puppet PID files are kept.# The default value is '/run'.rundir= /var/run/puppet
# Where SSL certificates are kept.# The default value is '/ssl'.ssldir= /var/lib/puppet/ssl
show_diff=truedns_alt_names=foreman.example.com,foreman-ha.example.com
[agent]pluginsync=truereport=trueignoreschedules=falsedaemon=trueca_server= puppetca01.example.com
certname= foremanlb01.example.com
environment= production
server= foreman-ha.example.com
listen=falsesplay=truesplaylimit= 600
runinterval= 1800
noop=falseconfigtimeout= 120
usecacheonfailure=true[master]autosign=$confdir/autosign.conf {mode= 664 }ca=truessldir= /var/lib/puppet/ssl
parser= current
strict_variables=falsemasterport= 8139
Run Puppet agent
Puppet Agent initial run
1
puppet agent -t --waitforcert 30
On the CA server sign the certificate request
Puppet CA certificate request management
12
puppet cert list -a
puppet cert --allow-dns-alt-names sign foremanlb01.example.com
Configure Apache HTTPd
Force Foreman to run over HTTPS
123456789101112131415
<VirtualHost *:80>
ServerName foreman
ServerAlias foreman-ha.example.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} </IfModule>
## Logging ErrorLog "/var/log/httpd/foreman_error.log" ServerSignature Off
CustomLog "/var/log/httpd/foreman_access.log" combined
</VirtualHost>
<Proxy balancer://foreman>
BalancerMember http://foremanui01.example.com:80 route=F1
BalancerMember http://foremanui02.example.com:80 route=F2
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:443>
ServerName foremanlb01.example.com
ServerAlias foreman-ha.example.com
## Logging ErrorLog "/var/log/httpd/foreman-error_ssl.log" ServerSignature Off
CustomLog "/var/log/httpd/foreman-access_ssl.log" combined
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"env=BALANCER_ROUTE_CHANGED
## Request header rules## as per http://httpd.apache.org/docs/2.2/mod/mod_headers.html#requestheader RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
#RequestHeader unset X-Forwarded-For <Location "/balancer-manager">
SetHandler balancer-manager
ProxyPass "!"# Probably a good option is to restrict access to the manager to a set of nodes </Location>
## SSL directives SSLEngine on
SSLCertificateFile "/var/lib/puppet/ssl/certs/foremanlb01.example.com.pem" SSLCertificateKeyFile "/var/lib/puppet/ssl/private_keys/foremanlb01.example.com.pem" SSLCACertificatePath "/etc/pki/tls/certs" SSLCACertificateFile "/var/lib/puppet/ssl/certs/ca.pem" SSLProtocol ALL -SSLv2 -SSLv3
SSLCipherSuite EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA
SSLHonorCipherOrder on
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +StdEnvVars +ExportCertData
SSLProxyEngine On
ProxyPreserveHost On
# Direct all Foreman requests to the default set of workers. ProxyPass / balancer://foreman/
ProxyPassReverse / balancer://foreman/
</VirtualHost>
As already mentioned Foreman UI nodes will act as Puppet masters aswell. Install Puppet and point it to the CA server so we obtain a valid SSL certificate. Then install Foreman with all the plugins you need disabling Puppet CA module installation.
[main]# Where Puppet's general dynamic and/or growing data is keptvardir= /var/lib/puppet
# The Puppet log directory.# The default value is '$vardir/log'.logdir= /var/log/puppet
# Where Puppet PID files are kept.# The default value is '$vardir/run'.rundir= /var/run/puppet
# Where SSL certificates are kept.# The default value is '$confdir/ssl'.ssldir= /var/lib/puppet/ssl
# Allow services in the 'puppet' group to access key (Foreman + proxy)privatekeydir=$ssldir/private_keys {group= service }hostprivkey=$privatekeydir/$certname.pem {mode= 640 }# Puppet 3.0.x requires this in both [main] and [master] - harmless on agentsautosign=$confdir/autosign.conf {mode= 664 }show_diff=truereports= foreman
hiera_config=$confdir/hiera.yaml
dns_alt_names= foremanui01.example.com,foreman,puppetmaster,foreman-ha.example.com
environmentpath= /etc/puppet/environments
basemodulepath= /etc/puppet/environments/common:/etc/puppet/modules:/usr/share/puppet/modules
[agent]# The file in which puppetd stores a list of the classes# associated with the retrieved configuration. Can be loaded in# the separate ``puppet`` executable using the ``--loadclasses``# option.# The default value is '$statedir/classes.txt'.classfile=$statedir/classes.txt
# Where puppetd caches the local configuration. An# extension indicating the cache format is added automatically.# The default value is '$confdir/localconfig'.localconfig=$vardir/localconfig
# Disable the default schedules as they cause continual skipped# resources to be displayed in Foreman - only for Puppet >= 3.4default_schedules=falsereport=truepluginsync=truemasterport= 8140
environment= production
certname= foremanui01.example.com
server= foreman-ha.example.com
listen=falsesplay=truesplaylimit= 600
runinterval= 1800
noop=falseconfigtimeout= 120
usecacheonfailure=true[master]autosign=$confdir/autosign.conf {mode= 664 }external_nodes= /etc/puppet/node.rb
node_terminus=execca=falsessldir= /var/lib/puppet/ssl
certname= foremanui01.example.com
parser= current
storeconfigs=truestoreconfigs_backend= puppetdb
strict_variables=false
This is a copy of the configuration I’m using in production. As you can see I use PuppetDB for catalog storage.