<?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>Common Media, Inc. &#187; System Administration</title>
	<atom:link href="http://www.commonmediainc.com/category/system-administration/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.commonmediainc.com</link>
	<description>Online Communities and Web Development</description>
	<lastBuildDate>Fri, 06 May 2011 15:10:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Optimizing Apache, MySQL and PHP for content management</title>
		<link>http://www.commonmediainc.com/2010/11/02/optimizing-apache-mysql-and-php-for-content-management/</link>
		<comments>http://www.commonmediainc.com/2010/11/02/optimizing-apache-mysql-and-php-for-content-management/#comments</comments>
		<pubDate>Tue, 02 Nov 2010 18:05:12 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=205</guid>
		<description><![CDATA[We don't focus on LAMP packages like Wordpress or Drupal, but sometimes we pick them up in order to work with particular design partners. Over time, we've assembled a suite of tools to help us optimize the LAMP stack on a VPS to work well with these packages.]]></description>
			<content:encoded><![CDATA[<p>We don&#8217;t focus on LAMP packages like <a title="Wordpress" href="http://www.wordpress.org">WordPress</a> or <a title="Drupal" href="http://www.drupal.org">Drupal</a>, but sometimes we pick them up in order to work with particular design partners. While the packages are generally optimized to allow deployment on shared hosting, factors from client preference to site traffic often drive our installations to VPS hosting, where the software infrastructure is not necessarily tuned to handle them. We&#8217;ve assembled a suite of tools to help us optimize the LAMP stack on a VPS.</p>
<p>These scripts and steps were developed tuning an <a href="http://www.ubuntu.com">Ubuntu</a> 10.4 LTS (&#8220;lucid&#8221;) system installed at <a href="http://www.slicehost.com">SliceHost</a>. Generally there are two concerns: memory use (because these tools will use as much memory as they&#8217;re given, and MySQL will often throw a tantrum if it doesn&#8217;t get what it wants) and site speed.</p>
<h2>Apache</h2>
<p>The default Apache install slurps quite a lot of memory. The main culprit is the MPM configuration, which is where Apache decides how many instances to keep active and how much work they should each do before they shut down: basically controlling Apache&#8217;s process spawn rate. Default installations often have too many workers open by default, and spawn more too easily, thus using more memory than is really needed.</p>
<p>The block in <code>/etc/apache2/apache2.conf</code> where this is configured looks like this:</p>
<pre>&lt;IfModule mpm_prefork_module&gt;
    StartServers          1
    MinSpareServers       1
    MaxSpareServers       2
    MaxClients           20
    MaxRequestsPerChild   4000
&lt;/IfModule&gt;</pre>
<p>The default numbers are generally much higher; this block has been tuned. However, don&#8217;t swallow these numbers either; instead, figure your own. <code>MinSpareServers</code> is how many processes are sitting idle; a higher number may improve site response time, but too high a number will let Apache use more memory than it needs. <code>MaxSpareServers</code> caps this number.</p>
<p><code>MaxClients</code> tells Apache when to give up because it&#8217;s about to run out of memory. To figure a good setting for this, we use a script from the great folks at RimuHosting:</p>
<pre><code>
#!/bin/bash
echo "This is intended as a guideline only!"
if [ -e /etc/debian_version ]; then
    APACHE="apache2"
elif [ -e /etc/redhat-release ]; then
    APACHE="httpd"
fi
RSS=`ps -aylC $APACHE |grep "$APACHE" |awk '{print $8'} |sort -n |tail -n 1`
RSS=`expr $RSS / 1024`
echo "Stopping $APACHE to calculate free memory"
/etc/init.d/$APACHE stop &amp;&gt; /dev/null
MEM=`free -m |head -n 2 |tail -n 1 |awk '{free=($4); print free}'`
echo "Starting $APACHE again"
/etc/init.d/$APACHE start
echo "MaxClients should be around" `expr $MEM / $RSS`
</code></pre>
<h2>MySQL</h2>
<p>The best tool for tuning MySQL is the <a href="http://www.day32.com/MySQL/">MySQL Performance Primer</a> script. Download that to your home directory on the server being tuned and <code>chmod 755 tuning-primer.sh</code> to make it executable. You should also run <code>which bc</code> to see if the <code>bc</code> calculation language is installed; if it isn&#8217;t, try <code>sudo apt-get install bc</code> to get it.</p>
<p>This script prefers to have at least 48 hours of continuously-running server to work with. If you let it, it will produce a <code>my.cnf</code> configuration file with a number of suggested directive changes, generally pointed at optimizing your memory usage and MySQL performance. It&#8217;s pretty impressive.</p>
<p>If you&#8217;re serious about tuning your application to get fast results from MySQL, enable the Slow Query Log while you&#8217;re at it, but don&#8217;t expect this to be too helpful with packages like WordPress or Drupal, which don&#8217;t really let you get at the query builders directly.</p>
<h2>PHP</h2>
<p>The best thing to speed up PHP is the APC or <a href="http://pecl.php.net/package/apc">Alternative PHP Cache</a>. This caches PHP&#8217;s &#8220;opcodes&#8221;, the compiled versions of the PHP scripts, so they won&#8217;t be recompiled with each request.</p>
<p><a href="http://2bits.com/articles/installing-php-apc-gnulinux-ubuntu-gutsy-gibbon-710-and-debian.html">This is a good primer</a> for the installation on Ubuntu. One catch is that the initial APC install (the <code>sudo pecl install apc</code> part) often throws an error. If it fails, try <code>sudo pecl install apc-beta</code> and see if that works better.</p>
<p>Definitely install the cache status page somewhere when you&#8217;re done. It provides some interesting data about how the cache is speeding things up.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2010/11/02/optimizing-apache-mysql-and-php-for-content-management/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx configuration tweaks for client-side speed optimization</title>
		<link>http://www.commonmediainc.com/2010/05/06/nginx-configuration-tweaks-for-client-side-speed-optimization/</link>
		<comments>http://www.commonmediainc.com/2010/05/06/nginx-configuration-tweaks-for-client-side-speed-optimization/#comments</comments>
		<pubDate>Fri, 07 May 2010 00:02:39 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Phusion Passenger]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[browser performance]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[page speed]]></category>
		<category><![CDATA[YSlow]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=167</guid>
		<description><![CDATA[As we move more sites to an Nginx/Passenger server stack, we need to translate the server-side optimizations we use for browser-side performance from Apache configuration to Nginx. Here&#8217;s how that comes over: Gzip compression In Nginx, this is an optional module which should be built in to the software at compile time. If it&#8217;s present, [...]]]></description>
			<content:encoded><![CDATA[<p>As we move more sites to an Nginx/Passenger server stack, we need to translate <a href="http://www.commonmediainc.com/2008/03/27/y-be-slow/">the server-side optimizations we use for browser-side performance</a> from Apache configuration to Nginx. Here&#8217;s how that comes over:</p>
<h5>Gzip compression</h5>
<p>In Nginx, this is an optional module which should be built in to the software at compile time. If it&#8217;s present, you can activate it in site configuration with a block like this:</p>
<pre> gzip on;
 gzip_min_length  1100;
 gzip_buffers     4       8k;
 gzip_proxied     any;
 gzip_types       text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;</pre>
<p>Note that Nginx considers <code>text/xml</code> and <code>text/html</code> to be redundant MIME types.</p>
<h5>Long expiration dates</h5>
<p>We want to have our assets cached in the user&#8217;s browser cache as long as possible, with a few exceptions (e.g. advertising assets.) To that end, we set expiration headers:</p>
<pre>       location ~* \.(js|css|jpg|jpeg|gif|png)$ {
                if (-f $request_filename) {
                   expires                        max;
                   break;
                }
       }</pre>
<p>This uses the filename extension to determine which files get &#8220;far future&#8221; expiration dates. If you&#8217;re used to naming files without extensions, this might not work so well for you.</p>
<p>By default, Nginx doesn&#8217;t use Etags, so we can stop worrying about that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2010/05/06/nginx-configuration-tweaks-for-client-side-speed-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Surviving Django traffic spikes with Nginx and memcached</title>
		<link>http://www.commonmediainc.com/2010/05/06/surviving-django-traffic-spikes-with-nginx-and-memcached/</link>
		<comments>http://www.commonmediainc.com/2010/05/06/surviving-django-traffic-spikes-with-nginx-and-memcached/#comments</comments>
		<pubDate>Thu, 06 May 2010 23:39:22 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=165</guid>
		<description><![CDATA[Normally I wouldn&#8217;t categorize a multi-national organization with a seven-figure annual budget as a &#8220;small&#8221; client, but we didn&#8217;t build the site for the World Marathon Majors, a sort of mass-marathon trade group made up of the Boston, London, Berlin, Chicago and New York City marathons. Instead, we inherited their Django-based site from a previous [...]]]></description>
			<content:encoded><![CDATA[<p>Normally I wouldn&#8217;t categorize a multi-national organization with a seven-figure annual budget as a &#8220;small&#8221; client, but we didn&#8217;t build the site for the <a href="http://www.worldmarathonmajors.com">World Marathon Majors</a>, a sort of mass-marathon trade group made up of the Boston, London, Berlin, Chicago and New York City marathons. Instead, we inherited their <a href="http://www.djangoproject.org">Django</a>-based site from a previous partner, and our job is to keep it running, fix what breaks, and make modest upgrades.</p>
<p>The site&#8217;s traffic is flat for most of the year, but race day for any of the five events produces a spike in the traffic graph resembling a shark fin in a calm sea. Last month, with both <a href="http://www.baa.org/">Boston</a> and <a href="http://www.virginlondonmarathon.com/">London</a> on the horizon, we took steps to ensure the site and its new hosting could handle the load.</p>
<p>Because the site does not ask users to register, we recognized that we could cache complete HTML pages as they were rendered by Django and expire them after an arbitrary time span. If we kept rendered pages in the cache for ten minutes, for example, no page would be rendered more frequently than once every ten minutes, and yet news updates would never be delayed by more than ten minutes waiting for a cache refresh.</p>
<p>Because we were already using <a href="http://wiki.nginx.org/">Nginx</a> as the front-end of our server stack, we followed <a href="http://soyrex.com/blog/django-nginx-and-memcached/">this stellar write-up by Alex Holt</a> describing a simple system where Django writes to the cache, and Nginx reads from it. By using <a href="http://memcached.org/">memcached</a> for our cache rather than writing to disk or a database, we realized a little extra benefit: whenever Nginx has a cache hit, the page is returned significantly faster than if there&#8217;s a cache miss and Django has to render the page. This isn&#8217;t surprising when you think about the whole stack–of course a simple read will always be faster than a dynamic page build with multiple database queries–but gave us a nice Zen server moment. By doing less work, the server was getting more done.</p>
<p>And the whole stack survived London with flying colors. Now we just have to figure out how to unwind the site&#8217;s designed-in assumption that UK is a legitimate language code for English.  (Hint: People who speak &#8220;UK&#8221; use the Cyrillic alphabet.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2010/05/06/surviving-django-traffic-spikes-with-nginx-and-memcached/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rejecting mail for valid local users</title>
		<link>http://www.commonmediainc.com/2010/02/19/rejecting-mail-for-valid-local-users/</link>
		<comments>http://www.commonmediainc.com/2010/02/19/rejecting-mail-for-valid-local-users/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 19:33:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=153</guid>
		<description><![CDATA[Several months ago we mentioned that certain Linux distributions will, if they are running an SMTP server and accepting mail for local users, accumulate spam for &#8220;role&#8221; users who will never read their mail, e.g. mail, uucp, news, etc. I finished by suggesting, The best shortcut here is to bounce any email destined for the [...]]]></description>
			<content:encoded><![CDATA[<p>Several months ago we mentioned that certain Linux distributions will, if they are running an SMTP server and accepting mail for local users, <a href="http://www.commonmediainc.com/2009/09/14/clean-out-role-user-mailboxes/">accumulate spam for &#8220;role&#8221; users</a> who will never read their mail, e.g. <code>mail</code>, <code>uucp</code>, <code>news</code>, etc.</p>
<p>I finished by suggesting,</p>
<blockquote><p>The best shortcut here is to bounce any email destined for the role users. This will vary depending on your MTA, so I won’t detail it here.</p></blockquote>
<p>It&#8217;s true that it varies by MTA, but it turns out it&#8217;s really hard to find this information. MTAs aren&#8217;t set up to reject mail from specific addresses; they want a specific list of valid addresses and they&#8217;ll reject everything else.</p>
<p>It turns out that there&#8217;s a faster and cleaner method which is MTA-independent: lock the mailboxes for those users.</p>
<p>This could be as simple as putting an empty file in <code>/var/spool/mail/uucp</code> (for example) which is owned by <code>root</code> with 600 permissions, but that&#8217;s going to generate a bunch of error messages when your local delivery agent tries to write to a file it doesn&#8217;t have permissions for. A more elegant solution is to symlink those paths to <code>/dev/null</code>:</p>
<pre>ln -s /dev/null /var/spool/mail/uucp</pre>
<p>Now make sure the symlink has the correct ownership&#8230;</p>
<pre>chown -h uucp:mail /var/spool/mail/uucp</pre>
<p>Now all that spam will be silently delivered to the bit-bucket.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2010/02/19/rejecting-mail-for-valid-local-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clean out role-user mailboxes</title>
		<link>http://www.commonmediainc.com/2009/09/14/clean-out-role-user-mailboxes/</link>
		<comments>http://www.commonmediainc.com/2009/09/14/clean-out-role-user-mailboxes/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 14:11:11 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=119</guid>
		<description><![CDATA[I suppose the subtitle to this post could be, &#8220;why you don&#8217;t want to be a mail administrator.&#8221; The fact is, spam has made running a host which accepts email a pretty unpleasant task all around, and we strongly suggest clients we host domains for run email for that domain through Google Apps rather than [...]]]></description>
			<content:encoded><![CDATA[<p>I suppose the subtitle to this post could be, &#8220;why you don&#8217;t want to be a mail administrator.&#8221; The fact is, spam has made running a host which accepts email a pretty unpleasant task all around, and we strongly suggest clients we host domains for run email for that domain through <a href="http://www.google.com/apps/">Google Apps</a> rather than relying on POP/IMAP through our host.</p>
<p>We do still have a box which accepts incoming SMTP, though, and that means putting up with a certain amount of unsolicited commercial overhead. Every Linux box has a certain number of no-shell users set up to run daemons with limited privilege, e.g. the <code>apache</code> user. Oddly, some spammers either run the same username scans as the brute-force ssh hackers, or they think the <code>apache</code> user is actually reading its email. I found 44MB of unread email, about 5,000 messages, waiting in that inbox. <code>uucp</code> had the next biggest collection; <code>mail</code> and <code>news</code> were right up there as well.</p>
<p>That&#8217;s a lot of disk space. After a cursory glance to ensure there was nothing actually important in there, I simply used <code>sudo cp /dev/null /var/spool/mail/apache</code> to take out the trash.</p>
<p>If you are root or have appropriate <code>sudo</code> privileges, you can check another user&#8217;s mail using <code>mutt</code> or a similar command-line mail client. Just use the <code>-f</code> flag to feed mutt a mailbox path as an argument. In this case, I could check the <code>apache</code> mailbox using <code>sudo mutt -f /var/spool/mail/apache</code> . Naturally, you would want to have a talk with your company ethicist before doing this on a mailbox belonging to an actual user.</p>
<p>The best shortcut here is to bounce any email destined for the role users. This will vary depending on your MTA, so I won&#8217;t detail it here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2009/09/14/clean-out-role-user-mailboxes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moving a Rails/Mongrel site to Phusion Passenger on Ubuntu</title>
		<link>http://www.commonmediainc.com/2009/03/15/moving-a-railsmongrel-site-to-phusion-passenger-on-ubuntu/</link>
		<comments>http://www.commonmediainc.com/2009/03/15/moving-a-railsmongrel-site-to-phusion-passenger-on-ubuntu/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 18:58:30 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Phusion Passenger]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[phusion passenger]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=91</guid>
		<description><![CDATA[As I&#8217;ve noted before, several of our Rails projects are hosted using Phusion Passenger. We&#8217;ve been helping HitFix explore this option in recent weeks because it solves several minor deployment and restart frustrations they&#8217;ve been grappling with, and in the process I wrote up this walk-through for the installation. This process is actually really easy [...]]]></description>
			<content:encoded><![CDATA[<p>As <a title="Phusion Passenger, Permissions, and Rails' Session Store" href="http://www.commonmediainc.com/2008/11/25/phusion-passenger-permissions-and-rails-session-store/">I&#8217;ve noted before,</a> several of our Rails projects are hosted using <a href="http://www.modrails.com/">Phusion Passenger</a>. We&#8217;ve been <a title="Our previous post about HitFix" href="http://www.commonmediainc.com/2008/12/31/hitfix-is-in-beta/">helping</a> <a title="HitFix" href="http://www.hitfix.com">HitFix</a> explore this option in recent weeks because it solves several minor deployment and restart frustrations they&#8217;ve been grappling with, and in the process I wrote up this walk-through for the installation.</p>
<p>This process is actually really easy and the <a href="http://www.modrails.com/install.html">instructions on the Passenger site</a> and those provided during the installation process are excellent. The glitch we ran in to is that recent versions of Ubuntu and/or Apache 2.2.x use a slightly different method of loading modules and module configuration. (I haven&#8217;t run in to this method often enough to have learned whether it&#8217;s new in Apache or in Ubuntu.)</p>
<p>Instead of using one monolithic configuration file, sometimes offloading host configuration to included files, these Apaches instead globally include all modules found in the <code>mods_enabled</code> subdirectory of the Apache directory. Each module has two files, a <code>.load</code> file and a <code>.conf</code> file. The <code>.load</code> file contains only the LoadModule configuration directive; the <code>.conf</code> file contains any configuration directives.</p>
<p>Now, the actual files live in the <code>mods_available</code> subdirectory of Apache, and activating a module just means adding a symlink to the relevant files in <code>mods_enabled</code>, then restarting Apache. Deactivating it just means removing the symlink and restarting again.</p>
<p>With that in mind, here&#8217;s the Passenger process:</p>
<ul>
<li>Install Passenger on the server. This <em>should</em> be as simple as:</li>
</ul>
<p><code>sudo gem install passenger</code><br />
<code>sudo passenger-install-apache2-module</code></p>
<ul>
<li>On one system, this second command actually told me that the Apache 2 Development Headers were missing. (Passenger needs these to compile the Apache module.) I needed to run <code>sudo apt-get install apache2-prefork-dev</code> to get these headers. This didn&#8217;t work on the first attempt, but running <code>sudo apt-get update</code> once or twice finally got me a successful install of that package. Running the <code>passenger-install-apache2-module</code> script then worked successfully. Note that you will need a compiler on the system in order to generate the Apache module. You would think you could take this for granted, but apparently not.</li>
</ul>
<p>At this point, the module is built. This is where we have to adapt Phusion&#8217;s original installation instructions. Essentially, the next step is to make sure the module is loaded by Apache. Here&#8217;s how I did this:</p>
<ul>
<li>Create a file at <code>/etc/apache2/mods-available/passenger.load</code> with the following content:</li>
</ul>
<blockquote><p><code>LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so</code></p></blockquote>
<ul>
<li>Create a file at <code>/etc/apache2/mods-available/passenger.conf</code> with the following content (I think the IfModule container may be optional, but I played safe):</li>
</ul>
<blockquote><p><code>&lt;IfModule passenger_module&gt;<br />
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.0.6<br />
PassengerRuby /usr/bin/ruby1.8<br />
&lt;/IfModule&gt;</code></p></blockquote>
<ul>
<li>Create symbolic links to both those files from <code>/etc/apache2/mods-enabled/</code>, i.e.</li>
</ul>
<p><code>sudo ln -s /etc/apache2/mods-available/passenger.load /etc/apache2/mods-enabled/</code><br />
<code>sudo ln -s /etc/apache2/mods-available/passenger.conf /etc/apache2/mods-enabled/</code></p>
<p>We can restart Apache at this point without disturbing the existing site. Note that we can change which ruby is used (e.g. for <a title="Ruby Enterprise Edition" href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>) by altering the path at the <code>PassengerRuby</code> directive and restarting Apache.</p>
<p>To move a site to Passenger, you want to back up the file found at <code>/etc/apache2/sites-available/yoursite</code>, then edit it to make these changes:</p>
<ul>
<li>Change the <code>DocumentRoot</code> to the <code>public</code> directory of the app, e.g. <code>DocumentRoot /u/apps/yoursite/current/public</code></li>
<li>Comment out (with a <code>#</code>) all the lines related to the proxy, starting with the <code>Proxy balancer</code> definition and extending through all the <code>ProxyPass</code>, <code>ProxyPassReverse</code> and <code>ProxyPreserveHost</code> directives.</li>
<li>Restart Apache (<code>/etc/init.d/apache2 restart</code>). If something goes wrong, restore the backup you made of the configuration file and restart Apache again to restore the previous configuration.</li>
</ul>
<p>The final trick is to update the restart task in Capistrano to handle restarting Passenger and not Mongrel. This is actually pretty easy, particularly if you&#8217;ve already overloaded the restart task in your <code>config/deploy.rb</code> file. Just replace the line reading <code>run "mongrel_rails cluster::restart -C #{mongrel_config}"</code> with one reading <code>run "touch #{current_path}/tmp/restart.txt"</code> and we&#8217;re good to go. The start and stop tasks probably also needs tweaking to remove the mongrel commands–probably pasting the same command in for &#8220;start&#8221; will do the trick unless we feel like putting Apache commands in.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2009/03/15/moving-a-railsmongrel-site-to-phusion-passenger-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Phusion Passenger, permissions, and Rails&#8217; session store</title>
		<link>http://www.commonmediainc.com/2008/11/25/phusion-passenger-permissions-and-rails-session-store/</link>
		<comments>http://www.commonmediainc.com/2008/11/25/phusion-passenger-permissions-and-rails-session-store/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 21:16:18 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[file permissions]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[phusion passenger]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=63</guid>
		<description><![CDATA[For various reasons, we&#8217;re moving three Rails apps hosted on one VPS to use Phusion Passenger rather than the Apache/Mongrel Cluster stack (via Coda Hale) we&#8217;ve been using since we got started. The Passenger installation process really is as easy as it&#8217;s been described, particularly if you&#8217;re as comfortable with Apache configuration as we are, [...]]]></description>
			<content:encoded><![CDATA[<p>For various reasons, we&#8217;re moving three Rails apps hosted on one VPS to use <a href="http://www.modrails.com/">Phusion Passenger</a> rather than the <a href="http://httpd.apache.org">Apache</a>/<a href="http://mongrel.rubyforge.org">Mongrel</a> Cluster stack (<a href="http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/">via Coda Hale</a>) we&#8217;ve been using since we got started.</p>
<p>The Passenger installation process really is <a href="http://www.modrails.com/videos/passenger.mov">as easy as it&#8217;s been described</a>, particularly if you&#8217;re as comfortable with Apache configuration as we are, but by moving responsibility for serving your apps from Mongrel to Apache, file and process ownership becomes an issue in a way it wasn&#8217;t when Mongrel and Apache talked to each other and otherwise minded their own stores. <a href="http://www.railsgarden.com/2008/04/12/configurating-passenger-mod_rails-on-slicehost-with-ubuntu-710/">Ben Hughes hinted at this in his walk-through</a> of the Passenger installation, and we were not immune.</p>
<p>Our problem turned out to be session files. The first application we moved to Passenger (and it&#8217;s worth noting that apps running on Passenger and apps running Mongrel cluster can coexist under the same Apache) was <a href="http://www.redmine.org/">Redmine</a>, which uses file-based session store by default. If ownership of those session files creates a problem, and it did for us, <a href="http://wiki.rubyonrails.com/rails/pages/HowtoChangeSessionStore">switching to ActiveRecord session storage</a> resolves the problem.</p>
<p>For those wondering about the point of Passenger, it&#8217;s memory use. A single Mongrel instance and an app running under Passenger have comparable RAM requirements, but because Passenger is an Apache module, it can spawn new instances as requests arrive; the Mongrel cluster solution requires multiple mongrel instances to be running <em>all the time</em>. This means Mongrel apps essentially require the RAM for peak capacity <em>all the time</em>. Passenger gives that RAM back at non-peak times, which allows more apps to share the same system, allowing us to get more mileage from our VPSes. (It&#8217;s worth noting that the Phusion guys claim a 33% memory savings per instance if <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a> is also used, so that will probably be our next step when all the apps are Passenger-ized.)</p>
<p><strong>Update, 12/10:</strong> Another gotcha we found was file permissions. Again because of the permissions issues, Rails wasn&#8217;t writing to the <code>shared/logs/production.log</code> file. We didn&#8217;t notice this immediately, because the applications ran, they just didn&#8217;t log anything. The solution here was to change the ownership and permissions on the files. Specifically, we changed <em>group</em> ownership to &#8220;nobody&#8221; (the group Apache runs under) and the mode of the log file to 664.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2008/11/25/phusion-passenger-permissions-and-rails-session-store/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://www.modrails.com/videos/passenger.mov" length="18988364" type="video/quicktime" />
		</item>
		<item>
		<title>Solutions for Ruby vulnerabilities</title>
		<link>http://www.commonmediainc.com/2008/06/23/solutions-for-ruby-vulnerabilities/</link>
		<comments>http://www.commonmediainc.com/2008/06/23/solutions-for-ruby-vulnerabilities/#comments</comments>
		<pubDate>Mon, 23 Jun 2008 15:57:43 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[patching]]></category>
		<category><![CDATA[phusion passenger]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby enterprise edition]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=35</guid>
		<description><![CDATA[The recently-announced vulnerabilities in Ruby have put many of us administering Rails applications in a production space between a rock and a hard place. To recap, there are three major &#8220;lines&#8221; of Ruby interpreters, the 1.8.6 line, the 1.8.7 line, and the 1.9 line. All of these show the vulnerability, so nearly everyone needs to [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.ruby-lang.org/en/news/2008/06/20/arbitrary-code-execution-vulnerabilities/">recently-announced vulnerabilities in Ruby</a> have put many of us administering Rails applications in a production space between a rock and a hard place.</p>
<p>To recap, there are three major &#8220;lines&#8221; of Ruby interpreters, the 1.8.6 line, the 1.8.7 line, and the 1.9 line. All of these show the vulnerability, so nearly everyone needs to update their Ruby. (I&#8217;ll get to the exceptions later.) Rails introduces a new line of complication, because the 1.8.7 only works for Rails 2.1 and newer; if the Rails apps in question aren&#8217;t ready for Rails 2.1, or already running it (unlikely), the best route would be to continue to update in the 1.8.6 line. So there&#8217;s the rock: we need to update our Ruby.</p>
<p>The &#8220;hard place&#8221; is that the only patches so far released by the Ruby maintainers tend to produce segmentation faults, according to many who have tried them so far. That&#8217;s a long way of saying, &#8220;They don&#8217;t work.&#8221;</p>
<p>As a Rails-supporting sysadmin with, you&#8217;re left with several options, none of them comfortable. You can, in order of increasing riskiness:</p>
<ul>
<li>Wait out the Ruby maintainers and hope they release a working 1.8.6 patchlevel before your app is compromised.</li>
<li>Do crash-priority Rails upgrades on all your apps and switch to Rails 2.1, then move your Ruby to the 1.8.7 line.</li>
<li>Switch to an entirely different Ruby interpreter, like Rubinius or JRuby. (This hinges on the idea that Ruby is an interpreted language, and as long as the language is interpreted consistently there is room for any number of interpreters. Apparently JRuby and Rubinius are not affected by these vulnerabilities, only MRI, Matz&#8217;s Ruby Interpreter, which is the &#8220;standard&#8221; implementation.)</li>
<li>Switch to a different production stack entirely. For example, we&#8217;re currently using Apache 2.2 as a proxy for a Mongrel cluster in front of Rails 2.0.2 apps, a not-uncommon configuration. This could be the pressure we&#8217;d need to jump to <a href="http://www.modrails.com/">Phusion Passenger</a>, given that their <a href="http://www.rubyenterpriseedition.com">Ruby Enterprise Edition</a> claims to have <a href="http://blog.phusion.nl/2008/06/23/ruby-186-p230187-broke-your-app-ruby-enterprise-edition-to-the-rescue/">applied the security patches</a> to MRE 1.8.6 p111, and thus doesn&#8217;t introduce the segfault-inducing breaking features that the most-recent patchlevel does.</li>
</ul>
<p>I don&#8217;t know which way we&#8217;re going yet, but I&#8217;m not interested in waiting too long, and the upgrade to Rails 2.1 is going to happen sometime anyway, so Option #2 seems most likely for us.</p>
<p><em>Update:</em> Hongli Lai from Phusion assures us (in the comments) that Ruby Enterprise Edition can be used as a drop-in replacement for MRE without replacing the entire stack, moving REE up to the front of the line in the &#8220;different interpreter&#8221; option. Discussion seems to suggest to me that new official patches from the Ruby maintainers will not be coming in a timely fashion, but we are beginning to see &#8220;contributed&#8221; patched distributions emerge for e.g. FreeBSD and Debian.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2008/06/23/solutions-for-ruby-vulnerabilities/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rails asset hosts, SCM, and bundling</title>
		<link>http://www.commonmediainc.com/2008/04/09/rails-asset-hosts-scm-and-bundling/</link>
		<comments>http://www.commonmediainc.com/2008/04/09/rails-asset-hosts-scm-and-bundling/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 00:53:02 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[System Administration]]></category>
		<category><![CDATA[asset hosts]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/?p=30</guid>
		<description><![CDATA[Rails asset hosts not only made our client's site faster, they solved a problem with assets which weren't under revision control.]]></description>
			<content:encoded><![CDATA[<p>This afternoon we pushed another big revision to <a title="La Cucina Italiana USA, the Italian cooking magazine" href="http://www.lacucinaitalianamagazine.com">the <em>La Cucina Italiana</em> website</a>, which is now sharing a very small fraction of the thousands of <a href="http://www.lacucinaitalianamagazine.com/recipes">recipes</a> that magazine has in its archives. There will be more recipes coming online in the months to come, but most of the puzzles we had to solve are finished now.</p>
<p>One in particular was handling the photos which go with some recipes. Artful photography is <a title="An illustrated recipe" href="http://www.lacucinaitaliana.it/default.aspx?idPage=889&amp;idRicetta=6301">a hallmark of the <em>La Cucina Italiana</em> brand</a>, and the editorial team needed to be able to upload their images directly to the site. These photos wouldn&#8217;t be stored in the site database, but because they wouldn&#8217;t be part of our Subversion repository for the site, either, they had to live outside the normal site root in order to avoid being blown away by any site updates we deployed.</p>
<p>Enter <a title="A good explanation of asset hosts from when they entered Edge Rails" href="http://chadfowler.com/2007/2/18/edge-rails-goody-distributed-asset-hosts">Rails&#8217; asset hosts</a>. Rails <a title="The actual (sparse) documentation" href="http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html">allows for assets</a> (e.g. images, CSS files, or Javascript includes) to be served by a host other than that of the main site. Because the asset host definition happens at the host name level, the asset host can actually be on the same box as the main site, or it can be elsewhere in the world; you manage that at a different level of abstraction.</p>
<p>A &#8220;free&#8221; benefit of asset hosts is that by defining multiple asset hosts (<code>a0</code> through <code>a</code><em>n</em>), you can fool a user&#8217;s browser into downloading your site through a dozen or more different connections, rather than just the two it limits itself two with any single server. Rails will make each asset link use a different asset host, and the browser will open two connections to each server, not caring that they all happen to be on the same box. This gets us <a title="Running YSlow on La Cucina Italiana" href="http://www.commonmediainc.com/2008/03/27/y-be-slow/">extra YSlow points</a> (of course, we lose them again by requiring another DNS lookup for each asset host).</p>
<p>Our hangup, though, was that some assets, specifically CSS and Javascripts, <em>did</em> need to stay inside the Subversion repository and the site&#8217;s file tree.</p>
<p>Here&#8217;s the solution we came up with:</p>
<ul>
<li>Defined an Apache virtual server answering to subdomains <code>a0</code> through <code>a4</code>. (In other words, all four subdomains are the same real server, but the browser doesn&#8217;t know that; we could make them different physical servers someday.)</li>
<li>Set the site root for that server to <code>/var/www/assets/</code>.</li>
<li>Made symbolic links from <code>/var/www/assets/javascripts</code> to <code>/var/www/production/current/public/javascripts</code>, and from <code>/var/www/assets/stylesheets</code> to <code>/var/www/production/current/public/stylesheets</code>. (N.B. if you&#8217;re using Capistrano, &#8220;<code>current</code>&#8221; in your site directory is itself a symbolic link to a directory with your last site deploy.)</li>
<li>Set the upload code for recipe photos to store the uploaded images in subdirectories of <code>/var/www/assets/images</code>.</li>
</ul>
<p>This way, we get all the benefits of asset hosts for assets which are under revision control, and assets which aren&#8217;t. And the asset hosts themselves let us have assets which aren&#8217;t necessarily under revision control.</p>
<p>The free bonus here was that by using a symbolic link to the javascripts directory, <code><a href="http://code.google.com/p/bundle-fu/">bundle_fu</a></code> doesn&#8217;t have to know or understand our asset host setup; it just stores its bundled files in that same subdirectory as always, and it just works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2008/04/09/rails-asset-hosts-scm-and-bundling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Restarting Mongrel clusters with Capistrano 2</title>
		<link>http://www.commonmediainc.com/2007/12/08/restarting-mongrel-clusters-with-capistrano-2/</link>
		<comments>http://www.commonmediainc.com/2007/12/08/restarting-mongrel-clusters-with-capistrano-2/#comments</comments>
		<pubDate>Sat, 08 Dec 2007 16:18:12 +0000</pubDate>
		<dc:creator>pjmorse</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[System Administration]]></category>

		<guid isPermaLink="false">http://www.commonmediainc.com/2007/12/08/restarting-mongrel-clusters-with-capistrano-2/</guid>
		<description><![CDATA[There&#8217;s (still) a glitch between the mongrel_cluster gem and Capistrano 2 (we&#8217;re using mongrel_cluster 1.0.5 and Capistrano 2.1.0, for reference) where the application restart at the end of a cap deploy fails with an error like this: Couldn't find any pid file in '/var/www/[application]/current/tmp/pids' matching 'dispatch.[0-9]*.pid' I&#8217;m not sure what&#8217;s causing this, but the solution [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s (still) a glitch between the <code>mongrel_cluster</code> gem and Capistrano 2 (we&#8217;re using <code>mongrel_cluster</code> 1.0.5 and Capistrano 2.1.0, for reference) where the application restart at the end of a cap deploy fails with an error like this:<br />
<code></code></p>
<p><code>Couldn't find any pid file in '/var/www/[application]/current/tmp/pids' matching 'dispatch.[0-9]*.pid'</code></p>
<p>I&#8217;m not sure what&#8217;s causing this, but the solution comes at <a href="http://nubyonrails.com/articles/tips-for-upgrading-to-capistrano-2" title="Nuby on Rails: Tips for Upgrading to Capistrano 2">the end of this post</a>, under the heading &#8220;Restart Mongrel.&#8221; Due to issues with Cap 2 and <code>sudo</code>, though, the provided script fails for us. We&#8217;re running the updates as root (bad idea, but it gets around the cap <code>sudo</code> issues) so I updated the task like this:</p>
<pre>
# Restart task

set :mongrel_config, "/etc/mongrel_cluster/#{application}.yml"

namespace :deploy do

	task :restart do
		run "mongrel_rails cluster::restart -C #{mongrel_config}"
	end

end</pre>
<p>I also commented out the &#8220;:mongrel_conf&#8221; variable from our previous configuration, which it appears that Capistrano was ignoring anyway.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.commonmediainc.com/2007/12/08/restarting-mongrel-clusters-with-capistrano-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

