Using Nginx and Passenger to Power Your Puppet Master
Where I work, we use Nginx wherever possible, so when it came to setting up a new Puppet Master I headed to the puppet docs only to find outdated docs on doing this. Most docs are centred around using Apache with Passenger. After much Googling, I found that not many people are doing this, or if they are, they haven’t documented it. This post documents the steps required to get this all running, and is based around doing so using RHEL or CentOS 5.x.
The version of Ruby that is included with Red Hat/CentOS 5.x is ancient, and should not be used. You should start with at least Ruby 1.8.7 (Plus Rubygems) or 1.9.2. See the Puppet Labs FAQ for details on the best version to use.I recommend you use the FrameOS repo that provides Ruby 1.8.7:
1
# rpm -Uvh http://rbel.frameos.org/rbel5
Install Ruby and Rubygems:
1
# yum install -y ruby rubygems ruby-devel.x86_64
Now that’s out the way, let’s install puppet and puppet-server from yum.puppetlabs.com. You need to add the Puppet Labs yum repo which creates the file /etc/yum.repos.d/puppetlabs.repo file:
As nginx does not support dynamic module loading like Apache, and the official nginx
RPMs provided by nginx.org are not compiled with Passenger suppport, we need to build
nginx from source. I am not using the modrails.com yum repo to install the passenger enabled nginx as it relies on the default Ruby 1.8.5 and I don’t wish to use such an old version of Ruby. I’m also not using 1.9.2 as the Puppet Labs puppet packages are dependant on Ruby 1.8.x. If you wish to use Ruby 1.9.x, just install puppet as a gem (gem install puppet). This doesn’t setup the puppet user or install the RHEL/CentOS init script.
configuring additional modules
adding module in /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/nginx
checking for Math library ... found
+ ngx_http_passenger_module was configured
checking for PCRE library ... found
checking for OpenSSL library ... found
checking for zlib library ... found
creating objs/Makefile
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ md5: using OpenSSL library
+ sha1: using OpenSSL library
+ using system zlib library
nginx path prefix: "/opt/nginx"
nginx binary file: "/opt/nginx/sbin/nginx"
nginx configuration prefix: "/etc/nginx"
nginx configuration file: "/etc/nginx/nginx.conf"
nginx pid file: "/var/run/nginx.pid"
nginx error log file: "/var/log/nginx/error.log"
nginx http access log file: "/var/log/nginx/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
It’s a good idea to build a RPM for nginx so you can quickly deploy it to other pupper servers.
To do this I’m going to use Jordan Sissel’s superb fpm.
Let’s install the fpm rubygem:
1
# gem install fpm --no-rdoc --no-ri
Create a temporary location to create the RPM package:
123
# mkdir /tmp/installdir
# make
# make install DESTDIR=/tmp/installdir
Make some additional directories to add extra files to the RPM we are about to build:
Next, you need an nginx init script. I created one based on the one from the nginx wiki and updated it with correct paths and removed the auto user creation stuff. I won’t paste the whole thing here, but you can download it (and all the other files) from my GitHub repo:
Make sure the passenger_root is set to whatever is returned by:
1
# passenger-config --root
The passenger configuration is taken from the Suggested Tweaks section of the Puppet Labs Apache/Passenger document found here and adapted for Nginx using the Passenger Nginx user guide found here. The defaults are all acceptable apart from passenger_max_pool_size which by default is only 6. This sets the maximum number of rack application instances that can be simultaneously active. I’m presuming you won’t be running your puppet master on less than 1GB of RAM, so setting this to 15. Adjust this to suit your hardware/RAM.
Also, if you have installed Ruby any where else, update passenger_ruby. Feel free to update worker_processes for your hardware.
Create the nginx puppet server config /etc/nginx/conf.d/puppet.conf:
Create the puppet configuration file /etc/puppet/puppet.conf:
1234567
[main]
[agent]
server = puppet.example.com
[master]
certname = puppet.example.com
Turn puppet master off as it doesn’t need to run standalone:
1
# chkconfig puppetmaster off
Run a stand-alone puppet master to generate/sign certs etc.
123456789
# puppet master --no-daemonize --verbose
info: Creating a new SSL key for puppet.example.com
info: Creating a new SSL certificate request for puppet.example.com
info: Certificate Request fingerprint (md5): 04:AA:81:9E:49:B9:CA:2B:FD:D0:32:1B:69:CC:3E:B4
notice: puppet.example.com has a waiting certificate request
notice: Signed certificate request for puppet.example.com
notice: Removing file Puppet::SSL::CertificateRequest puppet.example.com at '/etc/puppet/ssl/ca/requests/puppet.example.com.pem'
notice: Removing file Puppet::SSL::CertificateRequest puppet.example.com at '/etc/puppet/ssl/certificate_requests/puppet.example.com.pem'
notice: Starting Puppet master version 2.7.11
Hit Ctrl+c to stop the stand-alone puppet master. You can see above that this has created a SSL key and certificate request, then signed this certificate request.
Add an nginx user:
1
# adduser nginx
Enable nginx
1
# chkconfig nginx on
Make sure everything looks good:
1
# service nginx configtest
If so, away you go:
1
# service nginx start
Now test a puppet agent run on the master:
1234
# puppet agent --server puppet --onetime --no-daemonize --verbose --noop
info: Caching catalog for puppet.example.com
info: Applying configuration version '1330615281'
notice: Finished catalog run in 0.04 seconds
One drawback of using nginx and passenger to front your Puppet master is that when there is a passenger upgrade, you will need to recompile nginx against the new passenger version and build a new RPM. Fortunately, because you are now running puppet and have been converted to fpm, this should be a trivial task, and not something you will need to do very often.