<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>schmichael&#039;s blog &#187; nginx</title>
	<atom:link href="http://blog.schmichael.com/tag/nginx/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.schmichael.com</link>
	<description>good good study, day day up</description>
	<lastBuildDate>Wed, 16 May 2012 23:59:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Deploying Python behind Nginx Talk Slides</title>
		<link>http://blog.schmichael.com/2011/01/25/deploying-python-behind-nginx-talk-slides/</link>
		<comments>http://blog.schmichael.com/2011/01/25/deploying-python-behind-nginx-talk-slides/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 18:52:13 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[pdxpython]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[slides]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=889</guid>
		<description><![CDATA[I gave a talk on deploying Python WSGI apps behind nginx at the Portland Python User Group meeting on January 11th and finally got around to publishing the slides: schmingx. I should mention Jason Kirtland informed me after the meeting &#8230; <a href="http://blog.schmichael.com/2011/01/25/deploying-python-behind-nginx-talk-slides/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I gave a talk on deploying Python WSGI apps behind <a href="http://wiki.nginx.org/">nginx</a> at the <a href="http://wiki.python.org/moin/PortlandPythonUserGroup">Portland Python User Group</a> meeting on January 11th and finally got around to publishing the slides: <a href="https://docs.google.com/present/edit?id=0Ab7GDIugV1qCZGR6c3d6YnJfMTA1aGRtZmJxYzI&#038;hl=en">schmingx</a>.</p>
<p>I should mention <a href="http://discorporate.us/jek/">Jason Kirtland</a> informed me after the meeting that <a href="http://www.fastcgi.com/devkit/doc/fcgi-spec.html">FastCGI</a> supports <a href="http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S3.5">persistent connections (and a host of other features)</a> between a load balancer and backend app servers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2011/01/25/deploying-python-behind-nginx-talk-slides/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A Complete Noobs Guide to Hacking Nginx</title>
		<link>http://blog.schmichael.com/2010/12/28/noobs-guide-to-hacking-nginx/</link>
		<comments>http://blog.schmichael.com/2010/12/28/noobs-guide-to-hacking-nginx/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 00:38:00 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[gdb]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://blog.schmichael.com/?p=857</guid>
		<description><![CDATA[At Urban Airship our RESTful HTTP API uses PUT requests for, among other things, registering a device. Since the application registering the device is the HTTP Basic Auth username, there&#8217;s often no body (entity body in HTTP parlance). Unfortunately nginx &#8230; <a href="http://blog.schmichael.com/2010/12/28/noobs-guide-to-hacking-nginx/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>At <a href="http://urbanairship.com">Urban Airship</a> our <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services">RESTful HTTP API</a> uses PUT requests for, among other things, <a href="http://urbanairship.com/docs/push.html#registration">registering a device</a>. Since the application registering the device is the HTTP Basic Auth username, there&#8217;s often no body (<a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2">entity body</a> in HTTP parlance). Unfortunately <a href="http://wiki.nginx.org">nginx</a> (as of 0.8.54, and I believe 0.9.3) doesn&#8217;t support PUT requests without a Content-Length header and responds with a 411 Length Required response. While the <a href="http://wiki.nginx.org/HttpChunkinModule">chunkin</a> module adds Transfer-Encoding: chunked support, it doesn&#8217;t fix the empty PUT problem since HTTP requests without bodies don&#8217;t require Content-Length nor Transfer-Encoding headers.</p>
<p>So let&#8217;s hack nginx shall we?</p>
<p>I know a bit of C but am primarily a Python developer, so hacking an established C project doesn&#8217;t come easily to me. To make matters worse, as far as I can tell there&#8217;s no official public source repository (<a href="https://github.com/git-mirror/nginx">but there&#8217;s a mirror</a>) and it seems to be mainly developed by the creator, <a href="http://sysoev.ru/en/">Igor Sysoev</a>. At least the code looks clean.</p>
<p><strong>First Pass</strong></p>
<p>I had <a href="http://nginx.org/download/nginx-0.8.54.tar.gz">nginx-0.8.54.tar.gz</a> handy from compiling the source and nginx was nice enough to log an error for PUTs without Content-Length:</p>
<blockquote><p>
client sent PUT method without &#8220;Content-Length&#8221; header while reading client request headers, client: &#8230;, server: , request: &#8220;PUT / HTTP/1.1&#8243; &#8230;
</p></blockquote>
<p>So let&#8217;s use <a href="http://betterthangrep.com/">ack</a> to find it:</p>
<p><img src="http://schmichael.com/files/nginx-01-ack.png" alt="ack-grep 'client sent .* method without'" title="ack-grep 'client sent .* method without'"/></p>
<p>A quick <code>vim +1532 src/http/ngx_http_request.c</code> later and we&#8217;re looking at the problem:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>r<span style="color: #339933;">-&gt;</span>method <span style="color: #339933;">&amp;</span> NGX_HTTP_PUT <span style="color: #339933;">&amp;&amp;</span> r<span style="color: #339933;">-&gt;</span>headers_in.<span style="color: #202020;">content_length_n</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ngx_log_error<span style="color: #009900;">&#40;</span>NGX_LOG_INFO<span style="color: #339933;">,</span> r<span style="color: #339933;">-&gt;</span>connection<span style="color: #339933;">-&gt;</span>log<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
                  <span style="color: #ff0000;">&quot;client sent %V method without <span style="color: #000099; font-weight: bold;">\&quot;</span>Content-Length<span style="color: #000099; font-weight: bold;">\&quot;</span> header&quot;</span><span style="color: #339933;">,</span>
                  <span style="color: #339933;">&amp;</span>r<span style="color: #339933;">-&gt;</span>method_name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        ngx_http_finalize_request<span style="color: #009900;">&#40;</span>r<span style="color: #339933;">,</span> NGX_HTTP_LENGTH_REQUIRED<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> NGX_ERROR<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>This code returns the 411 Length Required response for PUTs lacking a Content-Length header. Remove it, recompile (<code>make -j2 &#038;&#038; sudo make install &#038;&#038; sudo service nginx restart</code>), and test:</p>
<p><code>$ curl -vk -X PUT -u '...:...' http://web-0/api/device_tokens/FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660<br />
* About to connect() to web-0 port 80 (#0)<br />
*   Trying 10.... connected<br />
* Connected to web-0 (10....) port 80 (#0)<br />
* Server auth using Basic with user '...'<br />
> PUT /api/device_tokens/FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660 HTTP/1.1<br />
> Authorization: Basic ...<br />
> User-Agent: curl/7.19.5 (i486-pc-linux-gnu) libcurl/7.19.5 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.15<br />
> Host: web-0<br />
> Accept: */*<br />
><br />
< HTTP/1.1 200 OK<br />
< Server: nginx/0.8.54<br />
< Date: Tue, 28 Dec 2010 23:06:54 GMT<br />
< Content-Type: text/plain<br />
< Transfer-Encoding: chunked<br />
< Connection: keep-alive<br />
< Vary: Authorization,Cookie,Accept-Encoding<br />
<<br />
* Connection #0 to host web-0 left intact<br />
* Closing connection #0<br />
</code></p>
<p>Success! Now create a patch <code>diff -ru nginx-0.8.54 nginx > fix-empty-put.patch</code> and <a href="http://nginx.org/pipermail/nginx-devel/2010-December/000605.html">post it to the nginx-devel mailing list</a>.</p>
<p>Now to play Minecraft for 12 hours as you wait for the Russian developers to wake up and take notice of your patch. Possibly sleep.</p>
<p><strong>Second Pass: Fixing WebDAV</strong></p>
<p>A positive <a href="http://nginx.org/pipermail/nginx-devel/2010-December/000606.html">reply from Maxim Dounin to my patch</a>! I don't use WebDAV though, but if I want this patch accepted I better make sure it doesn't break official modules.</p>
<p>This time around I wanted to work locally, so I installed nginx with the following configuration:</p>
<p><code><br />
./configure --prefix=/home/schmichael/local/nginx --with-debug --user=schmichael --group=schmichael --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_dav_module<br />
</code></p>
<p>Note that I set the prefix to a path in my home directory, turned on debugging and the dav module, and set nginx to run as my user and group. A quick symlink from /home/schmichael/local/nginx/sbin/nginx to ~/bin/nginx, and I can start and restart nginx quickly and easily. More importantly I can attach a debugger to it.</p>
<p>The importance of being able to attach a debugger became clear as soon as I tested <a href="http://wiki.nginx.org/HttpDavModule">dav support (with their standard config)</a>:<br />
<code><br />
$ curl -v -X PUT http://localhost:8888/foo<br />
* About to connect() to localhost port 8888 (#0)<br />
*   Trying ::1... Connection refused<br />
*   Trying 127.0.0.1... connected<br />
* Connected to localhost (127.0.0.1) port 8888 (#0)<br />
> PUT /foo HTTP/1.1<br />
> User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18<br />
> Host: localhost:8888<br />
> Accept: */*<br />
><br />
* Empty reply from server<br />
* Connection #0 to host localhost left intact<br />
curl: (52) Empty reply from server<br />
* Closing connection #0<br />
</code></p>
<p>My patch was causing a segfault in the dav module that killed nginx's worker process. Bumping up my error logging to <code>debug</code> level didn't give me many clues:<br />
<code><br />
2010/12/28 10:32:55 [debug] 15548#0: *1 http put filename: "/home/schmichael/local/nginx/dav/foo"<br />
2010/12/28 10:32:55 [notice] 15547#0: signal 17 (SIGCHLD) received<br />
2010/12/28 10:32:55 [alert] 15547#0: worker process 15548 exited on signal 11<br />
</code></p>
<p>Time to break out the debugger! While I've used <code>gdb --pid</code> to attach to running processes before, I'd just installed Eclipse to work on some Java code and wondered if it might make debugging a bit easier.</p>
<p>After installing plugins for C/C++, Autotools, and GDB, I could easily import nginx by creating a "New Makefile project with existing code":<br />
<img src="http://schmichael.com/files/nginx-02-import-existing.png" alt="Import existing code"/></p>
<p>Now create a new Debug Configuration:<br />
<img src="http://schmichael.com/files/nginx-03-debug-conf.png" alt="Debug Configuration"/></p>
<p><em><strong>Note</strong> on Linux systems (at least Ubuntu):</em> by default PTRACE is disabled in the kernel. Just flip the 1 to 0 in <code>/etc/sysctl.d/10-ptrace.conf</code> and run <code>sudo sysctl -p /etc/sysctl.d/10-ptrace.conf</code> to allow PTRACE.</p>
<p>Finally click "Debug" and select the nginx <em>worker</em> process from your process list:<br />
<img src="http://schmichael.com/files/nginx-04-select-process.png" alt="Select Process"/></p>
<p>By default GDB will pause the process it attaches to, so make sure to click the Resume button (or press F8) to allow nginx to continue serving requests.</p>
<p><strong>Crashing nginx</strong><br />
Now cause the segfault by running our curl command <code>curl -v -X PUT http://localhost:8888/foo</code>. This time curl won't return because gdb/Eclipse caught the segfault in the nginx child process, leaving the socket to curl open. A quick peek in Eclipse shows us exactly where the segfault occurs:<br />
<img src="http://schmichael.com/files/nginx-05-debugging.png" alt="Debugging in Eclipse"/></p>
<p>Eclipse makes it quick and easy to interactively inspect the variables. Doing that I discovered the culprit was the src variable being uninitialized. Bouncing up the stack once you can see dav's put handler expects to be given a temporary file (<code>&#038;r->request_body->temp_file->file.name</code>) full of PUT data (of which we sent none), and it copies that to the destination file (<code>path</code>).</p>
<p>Bounce up the stack again to <code>ngx_http_read_client_request_body</code> and you can see this relevant code:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>r<span style="color: #339933;">-&gt;</span>headers_in.<span style="color: #202020;">content_length_n</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></pre></div></div>

<p>nginx's core HTTP module short circuits a bit when there's no Content-Length specified. It skips the temp file creation because there's no data to put into the temp file!</p>
<p>So we have our problem:</p>
<ol>
<li>The dav module put handler expects a temp file containing the data to be saved.</li>
<li>The http module doesn't create a temp file when there's no body data.</li>
</ol>
<p>The 2 solutions I can think of are:</p>
<ol>
<li>Always create a temp file, even if it's empty.</li>
<li>Add a special case to the dav module's put handler for when the temp file doesn't exist.</li>
</ol>
<p>I really don't want to hack the core http module just to make a sub-module happy. It <em>makes sense</em> that no temporary file exists when there's no body data. Sub-modules shouldn't be lazy and expect it to exist. So I decided to try #2.</p>
<p><strong>The Fix</strong></p>
<p>You can see my <a href="https://github.com/schmichael/nginx/commit/c6051556460561bac4b0931fd9436e37b84925a3">implementation of solution #2 on GitHub</a>. Simply put, if the temp file exists, follow the existing logic. If the temp file does not exist we have a PUT with an empty body: use nginx's open wrapper to do a create or truncate (<code>O_CREAT|O_TRUNC</code>) on the destination file (since an empty PUT should create an empty file).</p>
<p>I don't know if this is the best solution or even a correct one, but it appears to work and was a fun journey arriving at it. You can <a href="http://nginx.org/pipermail/nginx-devel/2010-December/000609.html">follow the discussion on the mailing list</a>.</p>
<p><small>Updated to switch from bitbucket to github.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2010/12/28/noobs-guide-to-hacking-nginx/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Web Server Shootout Talk Accepted at OS Bridge Conference</title>
		<link>http://blog.schmichael.com/2009/04/26/web-server-shootout-talk-accepted-at-os-bridge-conference/</link>
		<comments>http://blog.schmichael.com/2009/04/26/web-server-shootout-talk-accepted-at-os-bridge-conference/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 21:00:09 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[osbridge]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=637</guid>
		<description><![CDATA[My talk, Web Server Shootout, was accepted by the Open Source Bridge Conference! I&#8217;m terribly excited, but also nervous because there&#8217;s a lot I need to do between now and the conference. Expect regular updates on how my talk is &#8230; <a href="http://blog.schmichael.com/2009/04/26/web-server-shootout-talk-accepted-at-os-bridge-conference/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My talk, <a href="http://opensourcebridge.org/sessions/119">Web Server Shootout</a>, was accepted by the Open Source Bridge Conference!  I&#8217;m terribly excited, but also nervous because there&#8217;s a lot I need to do between now and the conference.  Expect regular updates on how my talk is progressing (always tagged with osbridge [feed]).</p>
<p>The <a href="http://opensourcebridge.org/2009/04/open-source-bridge-conference-confirmed-speakers/">full list of sessions is up</a> (or <a href="http://opensourcebridge.org/events/2009/sessions">here</a>), and I&#8217;m very excited just to be attending the conference.  Congratulations to all of the speakers!</p>
<p>Some of the sessions I&#8217;m particularly excited to attend are:</p>
<ul>
<li><a href="http://opensourcebridge.org/sessions/20">An Introduction to Machine Learning by John Melesky</a> &#8211; A Portland Python User Group regular and really smart guy in general.  Looking forward to getting my feet wet with machine learning.</li>
<li><a href="http://opensourcebridge.org/sessions/100">Drop ACID and think about data by Bob Ippolito</a> &#8211; I think the Portland Python crew that went to Pycon helped convince Bob to bring his presentation to OS Bridge, and I&#8217;m glad they did!  I work with non-relational databases everyday, but I still design my apps with a relational data model in mind.  This should be interesting.</li>
<li><a href="http://opensourcebridge.org/sessions/33">The Linux Kernel Development model by Greg Kroah-Hartman</a> &#8211; Its <a href="http://en.wikipedia.org/wiki/Greg_Kroah-Hartman">Greg KH</a>!  Come on!</li>
<li><a href="http://opensourcebridge.org/sessions/95">How Idealist.org uses technology to change the world by Michel Pelletier</a> &#8211; Another Portland Pythoneer and really smart guy.  Eager to here more about open source at work in an organization.  Its always fun to watch Michel present anyway.</li>
<li><a href="http://opensourcebridge.org/sessions/36">Web Testing with Windmill by Mikeal Rogers</a> &#8211; Hardly a day goes by that I don&#8217;t tell myself I&#8217;m going to improve my test coverage and skills.  Windmill looks like an excellent testing tool to help me accomplish that.</li>
</ul>
<p>There are many many more sessions I&#8217;m excited about, but I&#8217;m too sick of copying and pasting to mention anymore right now.</p>
<p>So <a href="http://opensourcebridge.org/attend/">sign up to attend the Open Source Bridge Conference in Portland, OR this June!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2009/04/26/web-server-shootout-talk-accepted-at-os-bridge-conference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Server Quandary</title>
		<link>http://blog.schmichael.com/2008/12/27/web-server-quandary/</link>
		<comments>http://blog.schmichael.com/2008/12/27/web-server-quandary/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 07:00:48 +0000</pubDate>
		<dc:creator>Michael Schurter</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cherokee]]></category>
		<category><![CDATA[lazyweb]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://michael.susens-schurter.com/blog/?p=469</guid>
		<description><![CDATA[Apache was probably the first Linux application I learned how to configure. However, I&#8217;ve gotten a bit frustrated with it recently&#8230; The Problem A memory leak. Apache is eating up memory so quickly that I need to restart it every &#8230; <a href="http://blog.schmichael.com/2008/12/27/web-server-quandary/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://httpd.apache.org/">Apache</a> was probably the first Linux application I learned how to configure.  However, I&#8217;ve gotten a bit frustrated with it recently&#8230;</p>
<p><strong>The Problem</strong></p>
<p><em>A memory leak.</em>  Apache is eating up memory so quickly that I need to restart it every couple days or risk my entire server grinding to a halt as it starts swapping wildly.  I&#8217;ve poured over log files and <code>pmap</code> output, but I still can&#8217;t figure out where the problem lies.  Curse you monolithic in-process architecture!</p>
<p>Actually I know what my problem is, I&#8217;m running a mess of modules:</p>
<ul>
<li><code>ssl</code> &#8211; 2 certificates on 2 ports</li>
<li><code>php5</code> &#8211; blerg, who doesn&#8217;t have to run this?</li>
<li><code>suphp</code> &#8211; I suspect this is my problem, but I can&#8217;t prove it.  A client&#8217;s 3rd party web application <em>requires</em> it, but I think its easily replaceable with FastCGI.</li>
<li><code>wsgi</code> &#8211; No complaints.  Python apps are out-of-process thankfully.</li>
<li><code>proxy</code> &#8211; Again no complaints.  Can&#8217;t imagine how this module could cause any problems except it does proxy some large (multi-megabyte, not huge) POSTs at times.  I can&#8217;t imagine a memory leak could slip into this module without a lot of people noticing.</li>
</ul>
<p><strong>Solution A: Apache+FastCGI</strong></p>
<p>I love the idea of putting each web application in its own process and letting Apache just act as an HTTP router.  FastCGI seems to have all the features I need, and I&#8217;m not really worried about the CPU overhead incurred by IPC.</p>
<p>However, there are 2 competing FastCGI modules for Apache, and I have no idea what to choose.  Anecdotally the official <a href="http://www.fastcgi.com/drupal/node/3">mod_fastcgi</a> is buggy and <a href="http://www.fastcgi.com/drupal/node/2">fastcgi.com is a spam infested wasteland</a>.  However, I&#8217;ve found no authoritative source saying:<em> &#8220;fastcgi is dead, long live <a href="http://fastcgi.coremail.cn/">fcgid</a>!&#8221;</em>  (Lame excuse, I know.)</p>
<p><strong>Solution B: <a href="http://www.lighttpd.net/">Lighttpd</a></strong></p>
<p>I know Lighty is the darling of Rails sites, but whenever I stop by its site I&#8217;m greeted with a list of recently fixed <a href="http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=lighttpd">security bugs</a>, and now it seems as though <a href="http://blog.lighttpd.net/articles/2008/12/02/a-little-heads-up">they&#8217;re rewriting the core</a>!</p>
<p>I&#8217;m sure Lighty is a high quality intelligently engineered project, but it seems to be the definition of immature.  Not necessarily bad (in fact it usually means its progressing quickly!), but perhaps not as reliable as good old workhorses like Apache.</p>
<p><strong>Solution C: <a href="http://www.cherokee-project.com/">Cherokee</a></strong></p>
<p>I&#8217;ve been following Cherokee for some time now and running it locally on my workstation.  I <em>love</em> the web interface.  I&#8217;m usually a very anti-webmin, pro-vim kind of guy, but I&#8217;m sick of editing Apache&#8217;s config files.  I do it about once a month and therefore it always takes lots of double-checking the docs.  I don&#8217;t know why, but its configuration has just never felt natural to me.</p>
<p>However, the lead Cherokee developer&#8217;s bravado is by the most off-putting aspect of the project.  <a href="http://lists.octality.com/pipermail/cherokee/2008-December/009437.html">He mocks modwsgi</a> and posts simplistic benchmarks showing Cherokee to be the fastest web server, but meanwhile Cherokee churns out numerous bug patch releases in-between feature releases and has yet to reach 1.0 status.</p>
<p>It seems like an excellent project technically, but I&#8217;m afraid there will be negative consequences for the lead developers hubris.  <small>(I&#8217;m not meaning to insult the guy.  He&#8217;s probably a far better hacker than I&#8217;ll ever be.  Self-promotion just makes me uncomfortable.)</small></p>
<p><strong>Solution D: <a href="http://nginx.net/">nginx</a></strong></p>
<p>I don&#8217;t know much about nginx except that it works.  Basically all I&#8217;ve heard about it is:</p>
<ul>
<li>It works.</li>
<li>Its fast.  <em>Really</em> fast.</li>
</ul>
<p>While &#8220;working&#8221; is definitely my primary objective, nginx seems a bit bare bones for me.  I just don&#8217;t think I&#8217;m the target demographic.  I&#8217;d kind of like for my web server to handle spawning and kill of FastCGI processes.</p>
<p>nginx feels like git to me.  Those who know it: use it and love it.  Those who don&#8217;t: stand in fear and awe of its unbridled power.</p>
<p>&#8230;or maybe its just a nice simple barebones HTTP server&#8230;</p>
<p><strong>Conclusions?</strong></p>
<p>I think <strong>Solution A: FastCGI</strong> is the most sensible.  Apache has always served me well, and the memory leak is most likely due to that shoddy suphp module.</p>
<p>Moving my web applications to FastCGI is also the best way to prepare to move to one of these 2nd generation web servers.</p>
<p>However, I&#8217;m getting kind of sick of Apache, and the ambiguousness of which FastCGI solution to choose is fairly annoying.</p>
<p>So dear lazyweb, for your everyday web developer consultant looking to run a bunch of PHP and Python web applications, what HTTP server stack should I use?  (Debian Lenny packages are a plus.)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schmichael.com/2008/12/27/web-server-quandary/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>

