Using Unicorn¶
This support is present in release 0.24.6 and later versions only – it is not supported in earlier releases
Alternatively see: Using Mongrel and Using Passenger
Why You’d Do This¶
Traditionally, the puppetmaster would embed a WEBrick or Mongrel Web Server to serve the puppet clients. This may work well for you, but when you start scaling out to hundreds of clients you really need to do things a bit more efficiently.
Adding Unicorn to your Puppetmaster stack brings one major advantage – seamless restarts of your puppetmasters.
What is Unicorn ?¶
http://unicorn.bogomips.org/ a HTTP server for Rack applications designed to only serve fast clients on low-latency, high-bandwidth connections and take advantage of features in Unix/Unix-like kernels.
Puppet (>0.24.6) now ships with a Rack application which can embed a puppetmaster. While it should be compatible with every Rack application server, it has only been tested with Passenger and Unicorn.
Installation Instructions for Puppet 0.25.x¶
First install Unicorn and Rack:
$ sudo gem install unicorn rack
Now copy in the config.ru file in the ext/rack directory:
$ sudo cp ext/rack/files/config.ru /etc/puppet/
Next, we need to create a configuration file for Unicorn, we’re calling ours unicorn.conf.
$ sudo touch /etc/puppet/unicorn.conf
Here’s the contents of a sample file:
worker_processes 8
working_directory "/etc/puppet"
listen '/var/run/puppet/puppetmaster_unicorn.sock', :backlog => 512
timeout 120
pid "/var/run/puppet/puppetmaster_unicorn.pid"
preload_app true
if GC.respond_to?(:copy_on_write_friendly=)
GC.copy_on_write_friendly = true
end
before_fork do |server, worker|
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
Running unicorn¶
To test that Unicorn is running Puppetmaster correctly you can fire it directly.
$ cd /etc/puppet
$ sudo unicorn -c unicorn.conf
For continued use, you’ll probably want to have something manage the unicorn process for you – this is where god comes in handy
Installing god¶
First, install god
$ sudo gem install god
You can find initscripts for god out there, but I prefer to have init spawn god, so:
$ sudo mkdir /etc/god
$ sudo echo "god:2345:respawn:/path/to/god --log-level error -D -c '/etc/god/*.god'" >> /etc/inittab
$ sudo touch /etc/god/puppetmaster.god
$ sudo telinit q
Configuring god to manage Unicorn¶
Drop the following into /etc/god/puppetmaster.god
God.watch do |w|
w.name = "puppetmaster"
w.interval = 30.seconds
w.pid_file = "/var/run/puppet/puppetmaster_unicorn.pid"
w.start = "cd /etc/puppet && /path/to/unicorn -c /etc/puppet/unicorn.conf -D"
w.stop = "kill -QUIT `cat #{w.pid_file}`"
w.restart = "kill -USR2 `cat #{w.pid_file}`"
w.start_grace = 10.seconds
w.restart_grace = 10.seconds
w.uid = "puppet"
w.gid = "puppet"
w.behavior(:clean_pid_file)
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
end
end
end
Finally, restart god to pick up the new config
$ sudo killall god
God should now be managing your Unicorn instance. You can test this by:
$ sudo god status
puppetmaster: up
Running Nginx¶
Drop this config into your Nginx setup. Requires nginx 0.7.63 or newer.
upstream puppetmaster_unicorn {
server unix:/var/run/puppet/puppetmaster_unicorn.sock fail_timeout=0;
}
server {
listen 8140;
ssl on;
ssl_session_timeout 5m;
ssl_certificate /var/lib/puppet/puppetmaster-ssl/certs/puppetmaster.pem;
ssl_certificate_key /var/lib/puppet/puppetmaster-ssl/private_keys/puppetmaster.pem;
ssl_client_certificate /var/lib/puppet/puppetmaster-ssl/ca/ca_crt.pem;
ssl_ciphers SSLv2:-LOW:-EXPORT:RC4+RSA;
ssl_verify_client optional;
root /usr/share/empty;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Client-Verify $ssl_client_verify;
proxy_set_header X-Client-DN $ssl_client_s_dn;
proxy_set_header X-SSL-Issuer $ssl_client_i_dn;
proxy_read_timeout 120;
location / {
proxy_pass http://puppetmaster_unicorn;
proxy_redirect off;
}
}