<?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>Unwinding the Stack &#187; php</title>
	<atom:link href="http://thestaticvoid.com/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://thestaticvoid.com</link>
	<description>Explorations in Computing</description>
	<lastBuildDate>Thu, 22 Jul 2010 20:25:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Replacing Apache with Yaws</title>
		<link>http://thestaticvoid.com/post/2009/08/04/replacing-apache-with-yaws/</link>
		<comments>http://thestaticvoid.com/post/2009/08/04/replacing-apache-with-yaws/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 02:35:25 +0000</pubDate>
		<dc:creator>James Lee</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[trac]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[yaws]]></category>

		<guid isPermaLink="false">http://thestaticvoid.com/?p=139</guid>
		<description><![CDATA[After some time running with the Apache worker model, I noticed it was not much better on memory than prefork. It would spawn new threads as load increased, but didn&#8217;t give up the resources when load decreased. I know it does this for performance, but I am very tight on memory. And I know Apache [...]]]></description>
			<content:encoded><![CDATA[<p>After some time running with the Apache <a href="http://thestaticvoid.com/post/2009/07/27/reducing-memory-footprint-of-apache-services/">worker</a> model, I noticed it was not much better on memory than prefork.  It would spawn new threads as load increased, but didn&#8217;t give up the resources when load decreased.  I know it does this for performance, but I am very tight on memory.  And I know Apache is very tunable, so I could probably change that behavior, but tuning is boring.  Playing with new stuff is fun!  This was the perfect opportunity for me to look at lightweight web servers.</p>
<p>I toyed around with <a href="http://www.lighttpd.net/">lighttpd</a> and read the documentation for <a href="http://nginx.net/">nginx</a>.  Both seem to do what I need them to do, but I was more interested in the equally fast and light <a href="http://yaws.hyber.org/">Yaws</a>.  I&#8217;ve been really into <a href="http://en.wikipedia.org/wiki/Erlang_(programming_language)">Erlang</a> lately (more on that in another post), so this was a great opportunity to see how a real Erlang application works.</p>
<h3>Installation</h3>
<p>Naturally, Yaws isn&#8217;t included in OpenSolaris yet, but Erlang is!  So it was fairly easy to whip together a <a href="http://thestaticvoid.com/wsvn/specs/trunk/yaws.spec">spec file</a> and <a href="http://thestaticvoid.com/wsvn/specs/trunk/ext-sources/http-yaws.xml">SMF manifest</a> for the program.  Then it was as easy as:</p>
<pre class="terminal">
$ <kbd>pkgtool build-only --download --interactive yaws.spec</kbd>
$ <kbd>pfexec pkg install yaws</kbd>
</pre>
<p>I&#8217;ve set the configuration to go to <tt>/etc/yaws/yaws.conf</tt> and the service can be started with <tt>svcadm enable yaws</tt>.  When I&#8217;m completely satisfied with the package, I&#8217;ll upload it to <a href="http://jucr.opensolaris.org/">SourceJuicer</a>.</p>
<h3>Configuration</h3>
<p>I run two virtual hosts: thestaticvoid.com and iriverter.thestaticvoid.com.  Those two domains also have &#8220;.org&#8221; counterparts which I want to redirect to the &#8220;.com&#8221; domain.  The <tt>yaws.conf</tt> syntax to handle this case is very simple:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">pick_first_virthost_on_nomatch = true<br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> localhost<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port = 80<br />
&nbsp; &nbsp; &nbsp; &nbsp; listen = 0.0.0.0<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;redirect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; / = thestaticvoid.com<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/redirect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> thestaticvoid.com<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port = 80<br />
&nbsp; &nbsp; &nbsp; &nbsp; listen = 0.0.0.0<br />
&nbsp; &nbsp; &nbsp; &nbsp; docroot = /docs/thestaticvoid.com<br />
&nbsp; &nbsp; &nbsp; &nbsp; dir_listings = true<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> iriverter.thestaticvoid.com<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port = 80<br />
&nbsp; &nbsp; &nbsp; &nbsp; listen = 0.0.0.0<br />
&nbsp; &nbsp; &nbsp; &nbsp; docroot = /docs/iriverter.thestaticvoid.com<br />
&nbsp; &nbsp; &nbsp; &nbsp; dir_listings = true<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> iriverter.thestaticvoid.org<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; port = 80<br />
&nbsp; &nbsp; &nbsp; &nbsp; listen = 0.0.0.0<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;redirect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; / = iriverter.thestaticvoid.com<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/redirect<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Should be pretty self-explanatory, but the nice thing is the <tt>pick_first_virthost_on_nomatch</tt> directive combined with the localhost block so that if anyone gets to this site by any other address, they&#8217;ll be redirected to the canonical thestaticvoid.com.  I did actually run into a bug with the redirection putting extra slashes in the URL, but squashed that bug pretty quickly with a bit of help from the Yaws mailing list.  That whole problem is summarized in <a href="http://thread.gmane.org/gmane.comp.web.server.yaws.general/2188">this thread</a>.</p>
<h4>PHP</h4>
<p>Yaws handles PHP execution as a special case.  All you have to do is add a couple lines to the configuration above:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">php_exe_path = /usr/php/bin/php-cgi<br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server</span> thestaticvoid.com<span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; allowed_scripts = php<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Reload the server (<tt>svcadm refresh yaws</tt>) and PHP, well, won&#8217;t work just yet.  This actually took me an hour or two to figure out.  OpenSolaris&#8217; PHP is compiled with the <tt>--enable-force-cgi-redirect</tt> option which means PHP will refuse to execute unless it was invoked by an Apache <tt>Action</tt> directive.  Fortunately, you can disable this security measure by setting <tt>cgi.force_redirect = 0</tt> in your <tt>/etc/php/5.2/php.ini</tt>.</p>
<h4>Trac</h4>
<p>Trac needs a little work to get running in Yaws.  It&#8217;s requires an environmental variable, <tt>TRAC_ENV</tt>, set to tell it where to find the project database.  The easiest way to do that is to copy <tt>/usr/share/trac/cgi-bin/trac.cgi</tt> to the document root, modify it to set the environmental variable, and enable CGI scripts in Yaws by setting <tt>allowed_scripts = cgi</tt>.</p>
<p>But I decided to set up an appmod, so that <tt>trac.cgi</tt> could be left where it was, unmodified.  Appmods are Erlang modules which get run by Yaws whenever the configured URL is requested.  Here&#8217;s the one I wrote for Trac:</p>
<div class="codecolorer-container erlang default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>trac<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>out<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">APPMOD</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/trac&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">TRAC_ENV</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/trac/iriverter&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">SCRIPT</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/usr/share/trac/cgi-bin/trac.cgi&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">include_lib</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;yaws/include/yaws_api.hrl&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #ff3c00;">out</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Pathinfo</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>pathinfo<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Env</span> <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;SCRIPT_NAME&quot;</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">APPMOD</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">,</span> <span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;TRAC_ENV&quot;</span><span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">TRAC_ENV</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; yaws_cg<span style="color: #ff4e18;">i</span>:<span style="color: #ff3c00;">call_cgi</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #6bb810;">,</span> undefined<span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">SCRIPT</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pathinfo</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Env</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></div></div>
<p>All appmods must define the out/1 function which takes an <tt>arg</tt> record which contains information about the current request.  At the end of the function, the Yaws API is used to execute the CGI script with the extra environmental variables.  This is compiled (<tt>erlc -o /var/yaws/ebin -I/usr/lib trac.erl</tt>) and enabled in the Yaws configuration by adding <tt>appmods = &lt;/trac, trac&gt;</tt> to a <tt>server</tt> section.  Then whenever someone requests <tt>/trac/foo/bar</tt>, Trac runs properly!</p>
<p>I also set up URL rewriting so that instead of requesting something like <tt>http://i.tsv.c/trac/wiki</tt>, all you see is <tt>http://i.tsv.c/wiki</tt>.  This involves another Erlang module, a rewrite module.  It looks like:</p>
<div class="codecolorer-container erlang default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>rewrite_trac<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>arg_rewrite<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">include_lib</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;yaws/include/yaws_api.hrl&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #ff3c00;">arg_rewrite</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Req</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>req<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span>abs_path<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">http_request</span><span style="color: #6bb810;">.</span>path<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">try</span> yaws_ap<span style="color: #ff4e18;">i</span>:<span style="color: #ff3c00;">url_decode_q_split</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">DecPath</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Query</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">case</span> <span style="color: #45b3e6;">DecPath</span> <span style="color: #014ea4;">==</span> <span style="color: #ff7800;">&quot;/&quot;</span> <span style="color: #186895;">orelse</span> <span style="color: #014ea4;">not</span> <span style="color: #ff4e18;">filelib</span>:<span style="color: #ff3c00;">is_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>docroot <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">DecPath</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #109ab8;">&#123;</span>req <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">http_request</span><span style="color: #109ab8;">&#123;</span>path <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#123;</span>abs_path<span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/trac&quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">catch</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit:_ <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></div></div>
<p>This module runs as soon as a request comes into the server and allows you to modify many variables before the request is handled.  This is a simple one which says: if the request is &#8220;/&#8221; or the requested file doesn&#8217;t exist, append the request to the Trac appmod, otherwise pass it through unaltered.  It&#8217;s enabled in the Yaws server by adding <tt>	arg_rewrite_mod = rewrite_trac</tt> to <tt>yaws.conf</tt>.  The Trac appmod must also be modified to make sure <tt>SCRIPT_NAME</tt> is now </tt>/</tt> so the application generates links without containing <tt>/trac</tt>.</p>
<h4>WordPress</h4>
<p>WordPress works perfectly once PHP is enabled in Yaws.  WordPress permalinks, however, do not.  A little background:  WordPress normally relies on Apache's mod_rewrite to execute <tt>index.php</tt> when it gets an request like <tt>/post/2009/07/27/suexec-on-opensolaris/</tt>.  mod_rewrite sets up the environmental variables such that WordPress is able to detect how it was called and can process the page accordingly.</p>
<p>Without mod_rewrite, the best it can do is rely on requests like <tt>/index.php/post/2009/07/27/suexec-on-opensolaris/</tt> and use the <tt>PATH_INFO</tt> variable, which is the text after <tt>index.php</tt>.  I think that looks ugly, having <tt>index.php</tt> in every URL.  You would think that simply rewriting the URL, just as was done with Trac, would solve the problem, but WordPress is too smart, and always sends you to a canonical URL which it thinks must include <tt>index.php</tt>.</p>
<p>After more experimentation than I care to explain, I discovered that if I set the <tt>REQUEST_URI</tt> variable to the original request (the one not including <tt>index.php</tt>), WordPress was happy.  This was a tricky exercise in trying to set an environmental variable from the rewrite module.  But, as we saw with the Trac example, environmental variables can be set from appmods.  And I found that data can be passed from the rewrite module to the appmod through the <tt>arg</tt> record!  Here's my solution:</p>
<div class="codecolorer-container erlang default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>rewrite_blog<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>arg_rewrite<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">include_lib</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;yaws/include/yaws_api.hrl&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #ff3c00;">arg_rewrite</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Req</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>req<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span>abs_path<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">http_request</span><span style="color: #6bb810;">.</span>path<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">try</span> yaws_ap<span style="color: #ff4e18;">i</span>:<span style="color: #ff3c00;">url_decode_q_split</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span><span style="color: #45b3e6;">DecPath</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Query</span><span style="color: #109ab8;">&#125;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">case</span> <span style="color: #45b3e6;">DecPath</span> <span style="color: #014ea4;">==</span> <span style="color: #ff7800;">&quot;/&quot;</span> <span style="color: #186895;">orelse</span> <span style="color: #014ea4;">not</span> <span style="color: #ff4e18;">filelib</span>:<span style="color: #ff3c00;">is_file</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>docroot <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">DecPath</span><span style="color: #109ab8;">&#41;</span> <span style="color: #186895;">of</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">case</span> <span style="color: #ff4e18;">string</span>:<span style="color: #ff3c00;">str</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Path</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/wsvn&quot;</span><span style="color: #109ab8;">&#41;</span> <span style="color: #014ea4;">==</span> <span style="color: #ff9600;">1</span> <span style="color: #186895;">of</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewPath</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_RepCount</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> <span style="color: #ff4e18;">regexp</span>:<span style="color: #ff3c00;">sub</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Path</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;^/wsvn(<span style="color: #000099; font-weight: bold;">\.</span>php)?&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/wsvn.php&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #109ab8;">&#123;</span>req <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">http_request</span><span style="color: #109ab8;">&#123;</span>path <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#123;</span>abs_path<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">NewPath</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #6bb810;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #109ab8;">&#123;</span>opaque <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#91;</span><span style="color: #109ab8;">&#123;</span><span style="color: #ff7800;">&quot;REQUEST_URI&quot;</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#93;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; req <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Req</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">http_request</span><span style="color: #109ab8;">&#123;</span>path <span style="color: #014ea4;">=</span> <span style="color: #109ab8;">&#123;</span>abs_path<span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/blog&quot;</span> <span style="color: #014ea4;">++</span> <span style="color: #45b3e6;">Path</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><span style="color: #109ab8;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">end</span><span style="color: #6bb810;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">catch</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit:_ <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Arg</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #186895;">end</span><span style="color: #6bb810;">.</span></div></div>
<p>Nevermind the extra <a href="http://thestaticvoid.com/wsvn/">WebSVN</a> rewriting code.  Notice I set the <tt>opaque</tt> component of the <tt>arg</tt>.  Then in the appmod:</p>
<div class="codecolorer-container erlang default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="erlang codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #014ea4;">-</span><span style="color: #5400b3;">module</span><span style="color: #109ab8;">&#40;</span>blog<span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">export</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#91;</span>out<span style="color: #014ea4;">/</span><span style="color: #ff9600;">1</span><span style="color: #109ab8;">&#93;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">define</span><span style="color: #109ab8;">&#40;</span><span style="color: #6941fd;">SCRIPT</span><span style="color: #6bb810;">,</span> <span style="color: #ff7800;">&quot;/docs/thestaticvoid.com/wordpress/index.php&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">include_lib</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;yaws/include/yaws.hrl&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<span style="color: #014ea4;">-</span><span style="color: #5400b3;">include_lib</span><span style="color: #109ab8;">&#40;</span><span style="color: #ff7800;">&quot;yaws/include/yaws_api.hrl&quot;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span><br />
<br />
<span style="color: #ff3c00;">out</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #109ab8;">&#41;</span> <span style="color: #6bb810;">-&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Pathinfo</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>pathinfo<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #45b3e6;">Env</span> <span style="color: #014ea4;">=</span> <span style="color: #45b3e6;">Arg</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">arg</span><span style="color: #6bb810;">.</span>opaque<span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #109ab8;">&#123;</span>ok<span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">GC</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">_Groups</span><span style="color: #109ab8;">&#125;</span> <span style="color: #014ea4;">=</span> yaws_ap<span style="color: #ff4e18;">i</span>:<span style="color: #ff3c00;">getconf</span><span style="color: #109ab8;">&#40;</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; yaws_cg<span style="color: #ff4e18;">i</span>:<span style="color: #ff3c00;">call_cgi</span><span style="color: #109ab8;">&#40;</span><span style="color: #45b3e6;">Arg</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">GC</span><span style="color: #ff9600;">#</span><span style="color: #d400ed;">gconf</span><span style="color: #6bb810;">.</span>phpexe<span style="color: #6bb810;">,</span> ?<span style="color: #6941fd;">SCRIPT</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Pathinfo</span><span style="color: #6bb810;">,</span> <span style="color: #45b3e6;">Env</span><span style="color: #109ab8;">&#41;</span><span style="color: #6bb810;">.</span></div></div>
<p>I pull the data from the <tt>arg</tt> record and pass it to the <tt>call_cgi/5</tt> function.  Also of note here is the special way to invoke the PHP CGI.  The location of the <tt>php-cgi</tt> executable is pulled from the Yaws configuration and passed as the second argument to <tt>call_cgi/5</tt> so Yaws knows what to do with the files.  You can surely imagine this as a way to execute things other than PHP which do not have a <tt>#!</tt> at the top.  Or emulating suEXEC with a custom wrapper <img src='http://thestaticvoid.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Overall, this probably seems like a lot of work to get things working that are trivial in other servers, but I'm finding that the appmods are really powerful, and the Yaws code itself is very easy to understand and modify.  Plus you get the legendary performance and fault-tolerance of Erlang.</p>
]]></content:encoded>
			<wfw:commentRss>http://thestaticvoid.com/post/2009/08/04/replacing-apache-with-yaws/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>suEXEC on OpenSolaris</title>
		<link>http://thestaticvoid.com/post/2009/07/27/suexec-on-opensolaris/</link>
		<comments>http://thestaticvoid.com/post/2009/07/27/suexec-on-opensolaris/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 03:24:59 +0000</pubDate>
		<dc:creator>James Lee</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[opensolaris]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[suexec]]></category>

		<guid isPermaLink="false">http://thestaticvoid.com/?p=96</guid>
		<description><![CDATA[One nice thing about having all dynamic content being generated by CGI is that you can use suEXEC to run the scripts as a different user. This is primarily used for systems where you have multiple untrusted users who run sites in one HTTP server. Then no one can interfere with anyone else. It can [...]]]></description>
			<content:encoded><![CDATA[<p>One nice thing about having all dynamic content being generated by CGI is that you can use <a href="http://httpd.apache.org/docs/2.2/suexec.html">suEXEC</a> to run the scripts as a different user.  This is primarily used for systems where you have multiple untrusted users who run sites in one HTTP server.  Then no one can interfere with anyone else.  It can also be used simply for separating the application from the server.</p>
<p>I&#8217;m the only user on my server so I don&#8217;t necessarily have any of these security concerns, but I have enabled suEXEC for convenience.  For example, WordPress will allow you to modify the stylesheets from the admin interface as long as it can write to them.  With suEXEC, the admin interface can run as my Unix user, so I can edit the files from both the web interface and the command line without having wide-open permissions or switching to root.</p>
<p>Same applies for <a href="http://iriverter.thestaticvoid.com/">Trac</a> where I can manage the project with the web interface or <tt>trac-admin</tt> on the command line.  The same effect could pretty much be obtained by using Unix groups properly:</p>
<pre class="terminal"># <kbd>groupadd wordpress</kbd>
# <kbd>usermod -G wordpress webservd</kbd>
# <kbd>usermod -G wordpress jlee</kbd>  <span class="comment"># my username</span>
# <kbd>chgrp -R wordpress /docs/thestaticvoid.com</kbd>  <span class="comment"># virtualhost document root</span>
# <kbd>chmod -R g+ws /docs/thestaticvoid.com</kbd>  <span class="comment"># make directory writable and always owned by
                                           the wordpress group</pre>
<p>Then <tt>umask 002</tt> would have to be set in Apache&#8217;s and my profile so any files that get created can be written to by the other users in the group.  That&#8217;s all well and good, but it seems like a bit of work and I don&#8217;t like the idea of messing with the default umask.</p>
<p>On to suEXEC.  First, let&#8217;s show the current user that PHP executes as.  Create a file <tt>test.php</tt> containing <code class="codecolorer php default"><span class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #990000;">exec</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span></code>.  Accessing the script from your web browser should show something like <tt>uid=80(webservd) gid=80(webservd)</tt>.</p>
<p>Next, in OpenSolaris, the <tt>suexec</tt> binary must be enabled:</p>
<pre class="terminal"># <kbd>cd /usr/apache2/2.2/bin/</kbd>  <span class="comment"># go one directory further into the amd64 dir
                              if you're running 64-bit</span>
# <kbd>mv suexec.disabled suexec</kbd>
# <kbd>chown root:webservd suexec</kbd>
# <kbd>chmod 4750 suexec</kbd>
# <kbd>./suexec -V</kbd>
 -D AP_DOC_ROOT="/var/apache2/2.2/htdocs"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="webservd"
 -D AP_LOG_EXEC="/var/apache2/2.2/logs/suexec_log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=100
 -D AP_USERDIR_SUFFIX="public_html"
</pre>
<p>These variables were set at compile time and cannot be changed.  They ensure that certain conditions must be met in order to use the binary.  That&#8217;s very important because it&#8217;s setuid root.  The first thing I had to do was move everything from my old document root to the one specified above in <tt>AP_DOC_ROOT</tt>.  Then you can add <code class="codecolorer apache default"><span class="apache"><span style="color: #00007f;">SuexecUserGroup</span> jlee jlee</span></code> (with whatever username and group you want the scripts to run as) to your <code class="codecolorer apache default"><span class="apache">&lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;</span></code> section of the Apache configuration.  At this point if you try to execute <tt>test.php</tt> you&#8217;ll probably see one of a couple errors in the suEXEC log (<tt>/var/apache2/2.2/logs/suexec_log</tt>):</p>
<ul>
<li><tt>[2009-07-27 11:08:02]: uid: (1000/jlee) gid: (1000/jlee) cmd: php-cgi<br />
[2009-07-27 11:08:02]: command not in docroot (/usr/php/bin/php-cgi)</tt><br />
In this case, <tt>php-cgi</tt> is going to have to be moved to the document root:</p>
<pre class="terminal">$ <kbd>cp /usr/php/bin/php-cgi /var/apache2/2.2/htdocs/</kbd>
$ <kbd>pfexec vi /etc/apache2/2.2/conf.d/php-cgi.conf</kbd>  <span class="comment"># modify the ScriptAlias appropriately</span>
$ <kbd>svcadm restart http</kbd></pre>
</li>
<li><tt>[2009-07-27 11:11:07]: uid: (1000/jlee) gid: (1000/jlee) cmd: php-cgi<br />
[2009-07-27 11:11:07]: target uid/gid (1000/1000) mismatch with directory (0/2) or program (0/0)</tt><br />
Make sure everything that <tt>suexec</tt> is to execute is owned by the same user and group as specified in the <code class="codecolorer apache default"><span class="apache"><span style="color: #00007f;">SuexecUserGroup</span></span></code> line of your Apache configuration.</li>
</ul>
<p>Now, running <tt>test.php</tt> should give the correct results: <tt>uid=1000(jlee) gid=1000(jlee)</tt>.  Done!</p>
<p>As a side note, I lose all frame of reference while I write so I can&#8217;t remember if I&#8217;m writing this for <strong>you</strong> or <strong>me</strong>, explaining what I&#8217;ve <strong>done</strong> or what you <strong>should do</strong>.  Sorry <img src='http://thestaticvoid.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://thestaticvoid.com/post/2009/07/27/suexec-on-opensolaris/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reducing Memory Footprint of Apache Services</title>
		<link>http://thestaticvoid.com/post/2009/07/27/reducing-memory-footprint-of-apache-services/</link>
		<comments>http://thestaticvoid.com/post/2009/07/27/reducing-memory-footprint-of-apache-services/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 23:34:57 +0000</pubDate>
		<dc:creator>James Lee</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[cgi]]></category>
		<category><![CDATA[opensolaris]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://thestaticvoid.com/?p=57</guid>
		<description><![CDATA[An interesting thing happened when I set up this blog. It first manifested itself as a heap of junk mail in my inbox. Then no mail at all. I had run out of memory. WordPress requires me to run MySQL and that extra 12M pushed me over the 256M cap in my OpenSolaris 2009.06 zone. [...]]]></description>
			<content:encoded><![CDATA[<p>An interesting thing happened when I set up this blog.  It first manifested itself as a heap of junk mail in my inbox.  Then no mail at all.  I had run out of memory.  WordPress requires me to run MySQL and that extra 12M pushed me over the 256M cap in my <a href="http://entic.net/">OpenSolaris 2009.06 zone</a>.  As a result SpamAssassin could not spawn, and ultimately Postfix died.  So I sought out to try to reduce my memory footprint.</p>
<p>Let&#8217;s take a look at where things were when I got started:</p>
<pre class="terminal">$ <kbd>prstat -s rss -Z 1 1 | cat</kbd>
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
 13488 webservd  183M   92M sleep   59    0   0:00:28 0.0% trac.fcgi/1
 13479 webservd   59M   41M sleep   59    0   0:00:14 0.0% trac.fcgi/1
 13489 webservd   59M   41M sleep   59    0   0:00:14 0.0% trac.fcgi/1
  4463 mysql      64M   12M sleep   59    0   0:02:39 0.0% mysqld/10
 19296 root       13M 8444K sleep   59    0   0:00:25 0.0% svc.configd/16
 19619 named      11M 5824K sleep   59    0   0:03:51 0.0% named/7
 13473 root       64M 4352K sleep   59    0   0:00:00 0.0% httpd/1
 19358 root       12M 3688K sleep   59    0   0:00:54 0.0% nscd/31
 19294 root       12M 3180K sleep   59    0 244:37:22 0.0% svc.startd/13
 13476 webservd   64M 2940K sleep   59    0   0:00:00 0.0% httpd/1
 13486 webservd   64M 2924K sleep   59    0   0:00:00 0.0% httpd/1
 13745 root     6248K 2832K cpu1    59    0   0:00:00 0.0% prstat/1
 13721 root     5940K 2368K sleep   39    0   0:00:00 0.0% bash/1
 13485 webservd   64M 2252K sleep   59    0   0:00:00 0.0% httpd/1
 13482 webservd   64M 2168K sleep   59    0   0:00:00 0.0% httpd/1
ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE
    39       60  494M  246M    96% 244:47:13 0.1% case
Total: 60 processes, 149 lwps, load averages: 0.61, 0.62, 0.52</pre>
<p>First thing I noticed is the 174M that <a href="http://iriverter.thestaticvoid.com/">Trac</a> was taking up.  I was running it as a FastCGI service for speed.  The problem with that is it remains resident even when it&#8217;s not processing any requests, which is most of the time.  One option I tried was setting <tt>DefaultMaxClassProcessCount 1</tt> in my <tt>/etc/apache2/2.2/conf.d/fcgid.conf</tt> file.  This effectively limits Trac to only one process at a time, which greatly reduces the memory utilization, but means it can only service one request at a time.  That&#8217;s not an option.</p>
<p>Fortunately, my zone seems to have good, fast processors and disks, so I can put up with running it as standard CGI service.  Easy enough to make the switch, just move some things around in my Apache configuration:</p>
<div class="codecolorer-container apache default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="apache codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00007f;">ScriptAlias</span> /trac /usr/share/trac/cgi-bin/trac.cgi<br />
<span style="color: #adadad; font-style: italic;">#ScriptAlias /trac /usr/share/trac/cgi-bin/trac.fcgi</span><br />
<span style="color: #adadad; font-style: italic;">#DefaultInitEnv TRAC_ENV &quot;/trac/iriverter&quot;</span><br />
<br />
&lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/trac&quot;</span>&gt;<br />
&nbsp; &nbsp; <span style="color: #00007f;">SetEnv</span> TRAC_ENV <span style="color: #7f007f;">&quot;/trac/iriverter&quot;</span><br />
&nbsp; &nbsp; <span style="color: #00007f;">Order</span> <span style="color: #00007f;">allow</span>,<span style="color: #00007f;">deny</span><br />
&nbsp; &nbsp; <span style="color: #00007f;">Allow</span> from <span style="color: #0000ff;">all</span><br />
&lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;</div></div>
<p>So things are looking much better, but I&#8217;m still not happy with it:</p>
<pre class="terminal">$ <kbd>prstat -s rss -Z 1 1 | cat</kbd>
   PID USERNAME  SIZE   RSS STATE  PRI NICE      TIME  CPU PROCESS/NLWP
 15362 webservd   74M   31M sleep   59    0   0:00:00 0.0% httpd/1
 15388 webservd   69M   30M sleep   59    0   0:00:00 0.0% httpd/1
 15366 webservd   66M   22M sleep   59    0   0:00:00 0.0% httpd/1
...
ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE
    39       58  254M  113M    44% 244:46:20 0.2% case </pre>
<p>Now Apache is being a hog, and that&#8217;s only a few of the <tt>httpd</tt> processes.  By default on Unix, Apache uses the <a href="http://httpd.apache.org/docs/2.2/mod/prefork.html">prefork MPM</a> which serves each request from its own process. It likes to keep around a handful of children for performance, so it doesn&#8217;t have to swawn a new one each time.  The problem is if your request involves PHP, each <tt>httpd</tt> process will load its own instance of the PHP module and it doesn&#8217;t let it go when it&#8217;s finished.  I get this.  It&#8217;s all for performance.  My initial reaction was: wouldn&#8217;t be nice if Apache was threaded so requests can all share the same PHP code.  That&#8217;s when I was introduced to the <a href="http://httpd.apache.org/docs/2.2/mod/worker.html">worker MPM</a>.  It serves requests from threads so it&#8217;s efficient, but also has a couple of children for fault tolerance.  This is easy to switch to in OpenSolaris:</p>
<pre class="terminal"># <kbd>svcadm disable http</kbd>
# <kbd>svccfg -s http:apache22 setprop httpd/server_type=worker</kbd>
# <kbd>svcadm refresh http</kbd>
# <kbd>svcadm enable http</kbd></pre>
<p>I also copied <tt>/etc/apache2/2.2/samples-conf.d/mpm.conf</tt> into <tt>/etc/apache2/2.2/conf.d/</tt> which includes some sane defaults like only spawning two servers to start with.  This was good:</p>
<pre class="terminal">$ <kbd>prstat -s rss -Z 1 1 | cat</kbd>
...
ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE
    39       50  125M   75M    29% 244:46:23 0.3% case</pre>
<p>75M makes me feel safe, like I could take the occasional spam bomb.  What I forgot to mention is that mod_php <a href="http://www.php.net/manual/en/faq.installation.php#faq.installation.apache2">isn&#8217;t supported</a> with the worker MPM since any of its extensions might not be thread-safe.  This is okay, because PHP can be run as a CGI program which has the additional benefit of being memory efficient (at the cost of speed) since it&#8217;s only loaded when it&#8217;s executed.  All I had to do was create a file <tt>/etc/apache2/2.2/conf.d/php-cgi.conf</tt> containing:</p>
<div class="codecolorer-container apache default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="apache codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;<span style="color: #000000; font-weight:bold;">IfModule</span> worker.c&gt;<br />
&nbsp; &nbsp; <span style="color: #00007f;">ScriptAlias</span> /php-cgi /usr/php/bin/php-cgi<br />
<br />
&nbsp; &nbsp; &lt;<span style="color: #000000; font-weight:bold;">Location</span> <span style="color: #7f007f;">&quot;/php-cgi&quot;</span>&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00007f;">Order</span> <span style="color: #00007f;">allow</span>,<span style="color: #00007f;">deny</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00007f;">Allow</span> from <span style="color: #0000ff;">all</span><br />
&nbsp; &nbsp; &lt;/<span style="color: #000000; font-weight:bold;">Location</span>&gt;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #00007f;">Action</span> php-cgi /php-cgi<br />
&nbsp; &nbsp; <span style="color: #00007f;">AddHandler</span> php-cgi .php<br />
&nbsp; &nbsp; <span style="color: #00007f;">DirectoryIndex</span> index.php<br />
&lt;/<span style="color: #000000; font-weight:bold;">IfModule</span>&gt;</div></div>
<p>I&#8217;ll be the first to admit, running Trac and WordPress as CGI have made them noticeably slower, but I&#8217;d rather them run slower for as much action that they get and know that my mail will get to me.  If you&#8217;re faced with similar resource constraints, you may want to consider these changes.  There may be other ways I can tweak Apache, such as unloading unused modules, but I&#8217;m not ready to face that yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://thestaticvoid.com/post/2009/07/27/reducing-memory-footprint-of-apache-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
