Using Mongrel

Version 13 (Daniel Pittman, 01/13/2011 08:09 pm)

1 1
# Using Mongrel with Apache
2 1
3 3 James Turnbull
Alternatively, see: 
4 3 James Turnbull
5 3 James Turnbull
* [[Using Mongrel On Debian]] 
6 3 James Turnbull
* [[Using Mongrel On Enterprise Linux]] 
7 3 James Turnbull
* [[Using Mongrel Pound]] 
8 3 James Turnbull
* [[Using Mongrel Nginx]]
9 7 Jim Blomo
* [[Using_Thin_Nginx]]
10 3 James Turnbull
* [[Using Passenger]]
11 1
12 1
Puppet daemons default to using WEBrick for http serving, but
13 1
puppetmasterd can be used with Mongrel instead. This requires
14 1
setting up a web proxy in front of Mongrel to handle the SSL
15 1
connections, and then you can start as many puppetmasterd instances
16 1
as you need. Note that Puppet uses Mongrel differently than most --
17 1
usually, you would have a mongrel\_cluster command that managed
18 1
multiple Mongrel instances. I planned to implement it this way, but
19 1
it ended up being easier in the short term to stick with
20 13 Daniel Pittman
puppetmasterd. Please contact us if you want to work on
21 13 Daniel Pittman
getting mongrel\_cluster to work with Puppet -- but we generally
22 13 Daniel Pittman
recommend folks use Passenger or Unicorn instead these days...
23 1
24 13 Daniel Pittman
Mongrel will work with any modern version of puppet; 0.23.1 is the minimum
25 13 Daniel Pittman
version with appropriate support. (Earlier
26 1
versions couldn't do certificate signing because they didn't
27 1
support the X-Client-Verify header.)
28 1
29 13 Daniel Pittman
Mongrel 1.1.5 or later is strongly recommended, and while 0.3.15 will
30 13 Daniel Pittman
theoretically work we don't test older versions of Mongrel extensively.
31 13 Daniel Pittman
32 1
This document only describes setting up Apache as a proxy in front
33 1
of Mongrel. Any other http proxy should work, as long as it
34 1
supports validating client certificates.
35 1
36 1
# Why You'd Do This
37 1
38 1
Mongrel scales much better than WEBrick, at least partially because
39 1
it allows you to run multiple processes serving the same pool of
40 1
clients on the same host. WEBrick only uses Ruby's threading, which
41 1
does not scale beyond one processor, and it appears that WEBrick
42 1
starts dropping connections beyond about 2 concurrent connections.
43 1
44 1
If you're getting connection-reset or End-of-file errors, you
45 1
should try Mongrel. As more people try it and it proves to be
46 1
stable, it will eventually become the preferred serving platform
47 1
for the master.
48 1
49 1
# Known Issues
50 13 Daniel Pittman
51 13 Daniel Pittman
We recommend Mongrel 1.1.5 or later, although it will theoretically work
52 13 Daniel Pittman
as far back as 0.3.15 or maybe 0.3.14.  We have not extensively tested between
53 13 Daniel Pittman
those versions, however, and would strongly encourage you to upgrade.
54 13 Daniel Pittman
55 13 Daniel Pittman
SLES 10 ships with Mongrel 0.3.13, which is too old to work out of the box.
56 13 Daniel Pittman
57 1
58 1
The Puppet file server (and other parts of puppet?) will not see
59 1
connections coming from the puppet client but from the reverse
60 1
proxy (ie. Apache). FileServingConfiguration (Security section)
61 1
gives more detail.
62 1
63 1
There is a problem with Apache and the certificate revocation list
64 1
(CRL) as generated by the puppet CA. If you encounter this problem,
65 1
you are likely to see lines like this in your error log:
66 1
67 4 James Turnbull
    [Mon Nov 10 08:47:20 2008] [warn] Invalid signature on CRL
68 4 James Turnbull
    [Mon Nov 10 08:47:20 2008] [error] Certificate Verification: Error (8): CRL signature failure
69 1
70 1
Puppet will also complain:
71 1
72 4 James Turnbull
    err: Could not retrieve catalog: Certificates were not trusted: tlsv1 alert decrypt error
73 1
74 1
Yet everything looks good in your puppet.conf.
75 1
76 8 Trevor Vaughan
If so, you will need to create a CRL directory and point your Apache server to this path by changing
77 1
78 8 Trevor Vaughan
    SSLCARevocationFile     /Library/Puppet/Generated/Server/SSL/ca/ca_crl.pem
79 8 Trevor Vaughan
80 8 Trevor Vaughan
To
81 8 Trevor Vaughan
82 8 Trevor Vaughan
    SSLCARevocationPath     /Library/Puppet/Generated/Server/SSL/CRL_DIRECTORY
83 8 Trevor Vaughan
84 8 Trevor Vaughan
To create this directory, you should take the following steps. For this example, we will assume that the directory will be created in the standard SSL directory that puppet uses.
85 8 Trevor Vaughan
86 8 Trevor Vaughan
    $mkdir /Library/Puppet/Generated/Server/SSL/crl
87 8 Trevor Vaughan
    $cd /Library/Puppet/Generated/Server/SSL/crl
88 8 Trevor Vaughan
    $ln -s /Library/Puppet/Generated/Server/SSL/ca/ca_crl.pem `openssl crl -in /Library/Puppet/Generated/Server/SSL/ca/ca_crl.pem -hash -noout`.0
89 8 Trevor Vaughan
90 8 Trevor Vaughan
Then, restart your Apache server.
91 8 Trevor Vaughan
92 8 Trevor Vaughan
If, for some reason, you are still getting the old error, you will need to disable CRL checking by commenting out all lines starting with 'SSLCARevocation'.
93 8 Trevor Vaughan
94 1
# Apache Configuration
95 1
96 1
Here is a complete apache configuration, intended for use only with
97 1
puppet:
98 1
99 1
    # Jeff McCune <mccune@math.ohio-state.edu>
100 1
    # 2007-09-14
101 1
    #
102 1
    # Minimal Apache Configuration for Apache+Mongrel+Puppetmaster
103 1
    #
104 1
    #  Host System Setup and Configuration:
105 1
    #  - Add puppet/puppet user/group
106 1
    #  - Use the following configuration file.
107 1
    #  - /Library/Puppet/Generated/Server is owned by puppet/puppet
108 1
    #
109 1
    #  - If you have a system which doens't provide Apache 2.2.X packages:
110 1
    #    Apache may be built with:
111 1
    #
112 1
    #    ./configure --enable-so \
113 1
    #       --enable-ssl=shared --enable-proxy=shared --enable-proxy_http=shared \
114 1
    #       --enable-proxy_balancer=shared --enable-headers=shared \
115 1
    #       --enable-authz_host=shared --enable-log_config=shared \
116 1
    #       --prefix=/Library/Puppet/Resources/httpd-2.2.4
117 1
    #
118 1
    # - Finally, start the SSL proxy with:
119 1
    #   /Library/Puppet/Resources/httpd-2.2.4/bin/httpd -f \
120 1
    #   /Library/Puppet/Versioned/Server/cluster-orange/httpd/puppetmasterd.conf
121 1
    
122 1
    Listen 8140
123 1
    PidFile /Library/Puppet/Generated/Server/balancer.pid
124 1
    User puppet
125 1
    Group puppet
126 1
    
127 1
    LoadModule proxy_module modules/mod_proxy.so
128 1
    LoadModule proxy_http_module modules/mod_proxy_http.so
129 1
    LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
130 1
    LoadModule headers_module modules/mod_headers.so
131 1
    LoadModule ssl_module modules/mod_ssl.so
132 1
    LoadModule authz_host_module modules/mod_authz_host.so
133 1
    LoadModule log_config_module modules/mod_log_config.so
134 1
    
135 1
    <Directory />
136 1
        Options FollowSymLinks
137 1
        AllowOverride None
138 1
        Order deny,allow
139 1
        Deny from all
140 1
    </Directory>
141 1
    
142 1
    <Proxy balancer://puppetmaster>
143 1
      BalancerMember http://127.0.0.1:18140 keepalive=on max=2 retry=30
144 1
      BalancerMember http://127.0.0.1:18141 keepalive=on max=2 retry=30
145 1
    </Proxy>
146 1
    
147 1
    <VirtualHost *:8140>
148 1
        SSLEngine on
149 1
        SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
150 1
        SSLCertificateFile      /Library/Puppet/Generated/Server/SSL/host_cert.pem
151 1
        SSLCertificateKeyFile   /Library/Puppet/Generated/Server/SSL/host_key.pem
152 1
        SSLCertificateChainFile /Library/Puppet/Generated/Server/SSL/ca/ca_crt.pem
153 1
        SSLCACertificateFile    /Library/Puppet/Generated/Server/SSL/ca/ca_crt.pem
154 8 Trevor Vaughan
        # Using the technique from above.
155 8 Trevor Vaughan
        SSLCARevocationPath     /Library/Puppet/Generated/Server/SSL/crl
156 6 Todd Zullinger
        SSLVerifyClient require
157 1
        SSLVerifyDepth  1
158 1
        SSLOptions +StdEnvVars
159 1
    
160 1
        # The following client headers allow the same configuration to work with Pound.
161 1
        RequestHeader set X-SSL-Subject %{SSL_CLIENT_S_DN}e
162 1
        RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
163 1
        RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
164 1
    
165 1
        <Location />
166 1
            SetHandler balancer-manager
167 1
            Order allow,deny
168 1
            Allow from all
169 1
        </Location>
170 1
    
171 1
        ProxyPass / balancer://puppetmaster:8140/ timeout=180
172 1
        ProxyPassReverse / balancer://puppetmaster:8140/
173 1
        ProxyPreserveHost on
174 1
        SetEnv force-proxy-request-1.0 1
175 1
        SetEnv proxy-nokeepalive 1
176 1
    
177 1
        ErrorLog  /Library/Puppet/Generated/Server/balancer_error.log
178 1
        CustomLog /Library/Puppet/Generated/Server/balancer_access.log combined
179 1
        CustomLog /Library/Puppet/Generated/Server/balancer_ssl_request.log \
180 1
                      "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
181 1
    </VirtualHost>
182 1
183 1
Note that you'll have to customize it to match the name of your
184 1
puppet server. Note also the cluster member declarations -- this is
185 1
where you tell Apache how to contact the Mongrel instances -- you
186 1
need a separate line for every instance, and (of course) each
187 1
instance needs to be started on a separate port.
188 1
189 1
This configuration starts Apache on Puppet's normal server port, so
190 1
clients do not need to be reconfigured.
191 1
192 1
# Another Apache configuration
193 1
194 1
Here's another happy apache configuration, without all the OSXey
195 1
stuff ('''Note:''' You still need to load the apache modules from
196 1
the configuration above. Except for ''log\_config'' which seems to
197 1
be OS X specific):
198 1
199 1
    Listen 8140
200 1
    
201 1
    ProxyRequests Off
202 1
    
203 1
    <Proxy balancer://puppetmaster>
204 1
        BalancerMember http://127.0.0.1:18140
205 1
    </Proxy>
206 1
    
207 1
    <VirtualHost *:8140>
208 1
        SSLEngine on
209 1
        SSLCipherSuite SSLv2:-LOW:-EXPORT:RC4+RSA
210 1
        SSLCertificateFile /etc/puppet/ssl/certs/backup4.foo.com.pem
211 1
        SSLCertificateKeyFile /etc/puppet/ssl/private_keys/backup4.foo.com.pem
212 1
        SSLCertificateChainFile /etc/puppet/ssl/ca/ca_crt.pem
213 1
        SSLCACertificateFile /etc/puppet/ssl/ca/ca_crt.pem
214 9 Trevor Vaughan
        # Using the technique from above.
215 9 Trevor Vaughan
        SSLCARevocationPath     /Library/Puppet/Generated/Server/SSL/crl
216 9 Trevor Vaughan
        SSLVerifyClient require
217 6 Todd Zullinger
        SSLVerifyClient require
218 1
        SSLVerifyDepth  1
219 1
        SSLOptions +StdEnvVars
220 1
    
221 1
        RequestHeader set X-Client-DN %{SSL_CLIENT_S_DN}e
222 1
        RequestHeader set X-Client-Verify %{SSL_CLIENT_VERIFY}e
223 1
    
224 1
        <Location />
225 1
           SetHandler balancer-manager
226 1
           Order allow,deny
227 1
           Allow from all
228 1
        </Location>
229 1
    
230 1
        ProxyPass / balancer://puppetmaster:8140/
231 1
        ProxyPassReverse / balancer://puppetmaster:8140/
232 1
        ProxyPreserveHost on
233 1
    
234 1
    </VirtualHost>
235 1
236 1
# Configuring Puppet
237 1
238 1
The only change to Puppet is that you need to start puppetmasterd
239 1
with --servertype mongrel and choose a separate masterport for each
240 1
instance. You will also need to specify a separate pidfile for each
241 1
instance.
242 1
243 1
The attached example init script for RedHat systems, or this helper
244 1
script might be useful:
245 1
246 1
    #!/bin/bash
247 1
    #
248 1
    # Start a Puppet Master Server instance.
249 1
    EZPUPPET_CONFDIR="${EZPUPPET_CONFDIR:=${EZPUPPET_BASE:=/Library/Puppet}/Versioned/Server/${EZPUPPET_SERVER:=cluster-orange}/puppet}"
250 1
    
251 1
    if ! [[ "$1" -gt 0 ]]; then
252 1
      echo "ERROR: You must provide a port to run this puppet master on."
253 1
      echo "Start at 18140 and increment upward."
254 1
      echo "  The apache load balancer is configured to talk to these servers"
255 1
      echo "  so the port numbers are NOT arbitrary."
256 1
      exit 1
257 1
    fi
258 1
    
259 1
    MASTERPORT="$1"
260 1
    shift
261 1
    
262 1
    puppetmasterd \
263 1
      --confdir="${EZPUPPET_CONFDIR}" \
264 1
      --pidfile=${EZPUPPET_BASE}/Generated/Server/var/run/puppetmaster."${MASTERPORT}".pid \
265 1
      --servertype=mongrel \
266 1
      --masterport="${MASTERPORT}" \
267 1
      $*
268 1
269 1
As mentioned earlier, this would be easier if it were done with
270 1
mongrel\_start, but it will take a significant amount of work to
271 1
get all of Puppet's existing code working in that framework, and
272 1
I'm unlikely to do it except as part of contract development.
273 1
Clearly, patches that provided this would be accepted.
274 1
275 1
'''NOTE''': The current (as of at least 0.24.6)
276 1
/etc/init.d/puppetmaster script on RedHat and compatible systems
277 1
already supports multiple mongrel instances in a similar way to
278 1
above. Simply specify your Mongrel instance ports in
279 1
/etc/sysconfig/puppetmaster in BASH array format as per the
280 1
following example:
281 1
282 1
    PUPPETMASTER_PORTS=([0]=18140 [1]=18141 [2]=18142 [3]=18143 [4]=18144)
283 1
284 1
# Generating Certificates
285 1
286 1
In version 0.23.2 I found that puppetmasterd would not generate
287 1
certificates when started using Mongrel. I worked around the
288 1
problem by using puppetca to generate the certificates as part of
289 1
the install process, like this:
290 1
291 1
    puppetca --generate <DOMAIN>
292 10 Hector Rivas
293 10 Hector Rivas
# Client certificate verification 
294 10 Hector Rivas
295 10 Hector Rivas
With the apache option:
296 10 Hector Rivas
297 10 Hector Rivas
    SSLVerifyClient optional|require
298 10 Hector Rivas
299 10 Hector Rivas
you control how Apache wil check the client certification. You can either, set the different certificate request path to not require verification, or disable it (unless you have another ca server or another way of distributing the certificates). So:
300 10 Hector Rivas
301 11 Hector Rivas
 * by enabling require, you basically say - the client is already suppose to have a certificate that I could verify. If certificate is not signed in puppetmaster you will get the error:
302 11 Hector Rivas
303 11 Hector Rivas
    err: Could not request certificate: SSL_connect returned=1 errno=0 state=SSLv3 read finished A: sslv3 alert handshake failure
304 11 Hector Rivas
    
305 10 Hector Rivas
 * "optional" will simulate the behaviour of an default standalone puppetmaster (without apache).