<?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>John Leach's Blog &#187; Ruby on Rails</title>
	<atom:link href="http://johnleach.co.uk/words/archives/category/tech/ruby-on-rails/feed" rel="self" type="application/rss+xml" />
	<link>http://johnleach.co.uk/words</link>
	<description>Stuff I think, see and do</description>
	<lastBuildDate>Fri, 18 Jun 2010 22:57:41 +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>My NWRUG Ferret Talk</title>
		<link>http://johnleach.co.uk/words/archives/2009/03/24/362/my-nwrug-ferret-talk</link>
		<comments>http://johnleach.co.uk/words/archives/2009/03/24/362/my-nwrug-ferret-talk#comments</comments>
		<pubDate>Tue, 24 Mar 2009 17:12:07 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[ferret]]></category>
		<category><![CDATA[indexing]]></category>
		<category><![CDATA[inverse index]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[solr]]></category>
		<category><![CDATA[sphinx]]></category>
		<category><![CDATA[talk]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/?p=362</guid>
		<description><![CDATA[I did a short talk on Ferret, the Ruby &#8220;Information Retreival Library&#8221;, at the North West Ruby Users Group last Thursday.  We had a bit of a theme too, with Will Jessop speaking about Sphinx and Asa Calow speaking about Solr. I got to have a bit of a nosey around the Manchester BBC building [...]]]></description>
			<content:encoded><![CDATA[<p>I did a short talk on <a href="http://ferret.davebalmain.com/">Ferret</a>, the Ruby &#8220;Information Retreival Library&#8221;, at the <a href="http://nwrug.org/events/march09/">North West Ruby Users Group</a> last Thursday.  We had a bit of a theme too, with Will Jessop speaking about Sphinx and Asa Calow speaking about Solr.</p>
<p>I got to have a bit of a nosey around the Manchester BBC building too &#8211; though I was worried I&#8217;d open the wrong door and end up on TV. Didn&#8217;t fancy having to apologise to Jeremy Paxman.</p>
<p><a href="http://www.brightbox.co.uk">Brightbox</a> also sponsored some pizza, and gave away t-shirts and stickers like candy (there was no candy though).</p>
<p>My <a href="http://johnleach.co.uk/documents/talks/090319-ruby-ferret-nwrug/">slides are available here</a>, and contain a little example file system indexer. I made my slides with <a href="http://webby.rubyforge.org/">webby</a> and <a href="http://github.com/geraldb/s6/tree/master">S6</a> if you&#8217;re interested.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2009/03/24/362/my-nwrug-ferret-talk/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Leeds Ruby Thing #2, Thursday 6th March</title>
		<link>http://johnleach.co.uk/words/archives/2008/03/04/303/leeds-ruby-thing-2-thursday-6th-march</link>
		<comments>http://johnleach.co.uk/words/archives/2008/03/04/303/leeds-ruby-thing-2-thursday-6th-march#comments</comments>
		<pubDate>Tue, 04 Mar 2008 12:29:00 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[leeds]]></category>
		<category><![CDATA[nwrug]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[social]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2008/03/04/303/</guid>
		<description><![CDATA[The Leeds offshoot of the North West Ruby User Group is meeting again this Thursday, 6th March, 7:00 PM &#8211; 11:00 PM.  This time at Mr. Foley&#8217;s Cask Ale House, on The Headrow (formerly Dr. Okells). Expect unstructured discussion of Ruby, Ruby on Rails and other random stuff plus nice people, great beer and coffee [...]]]></description>
			<content:encoded><![CDATA[<p>The Leeds offshoot of the <a href="http://www.nwrug.org">North West Ruby User Group</a> is meeting again this Thursday, 6th March, 7:00 PM &#8211; 11:00 PM.  This time at <a href="http://www.yorkbrew.demon.co.uk/Mr_fowleys.html">Mr. Foley&#8217;s<br />
Cask Ale House</a>, on The Headrow (formerly Dr. Okells).</p>
<p>Expect unstructured discussion of Ruby, Ruby on Rails and other random stuff plus nice people, great beer and coffee and geeky tshirts.</p>
<p>The balcony back room of Mr Foley&#8217;s has been booked.  Announce that you&#8217;re coming on the <a href="http://upcoming.yahoo.com/event/434473/">upcoming page</a>.</p>
<p>Oh, and we now have a website: <a href="http://leedsrubything.org/">http://leedsrubything.org/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2008/03/04/303/leeds-ruby-thing-2-thursday-6th-march/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Leeds Ruby Thing, Victoria Hotel 7th Feb 2008.</title>
		<link>http://johnleach.co.uk/words/archives/2008/02/03/294/leeds-ruby-thing-victoria-hotel-7th-feb-2008</link>
		<comments>http://johnleach.co.uk/words/archives/2008/02/03/294/leeds-ruby-thing-victoria-hotel-7th-feb-2008#comments</comments>
		<pubDate>Sun, 03 Feb 2008 21:03:58 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[leeds]]></category>
		<category><![CDATA[meetup]]></category>
		<category><![CDATA[nwrug]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[pub]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[social]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2008/02/03/294/</guid>
		<description><![CDATA[Some of the people of the North West Ruby User Group (who usually meet in Manchester) have organised the first little Leeds get together.  No real name yet, so it&#8217;s the Leeds Ruby Thing for now. No clear plan yet either, but expect unstructured discussion of Ruby and Ruby on Rails at least. Thursday 7th [...]]]></description>
			<content:encoded><![CDATA[<p>Some of the people of the <a href="http://www.nwrug.org">North West Ruby User Group</a> (who usually meet in Manchester) have organised the first little Leeds get together.  No real name yet, so it&#8217;s the Leeds Ruby Thing for now.</p>
<p>No clear plan yet either, but expect unstructured discussion of Ruby and Ruby on Rails at least.</p>
<p>Thursday 7th February 2008 at 7pm in the Victoria Hotel pub. All welcome!</p>
<p>More details here: <a href="http://upcoming.yahoo.com/event/423116">http://upcoming.yahoo.com/event/423116</a></p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2008/02/03/294/leeds-ruby-thing-victoria-hotel-7th-feb-2008/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>North West Ruby User Group Talk: Building Brightbox</title>
		<link>http://johnleach.co.uk/words/archives/2008/01/28/291/north-west-ruby-user-group-talk-building-brightbox</link>
		<comments>http://johnleach.co.uk/words/archives/2008/01/28/291/north-west-ruby-user-group-talk-building-brightbox#comments</comments>
		<pubDate>Mon, 28 Jan 2008 16:23:27 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[manchester]]></category>
		<category><![CDATA[nwrug]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[talk]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2008/01/28/291/</guid>
		<description><![CDATA[Oh, btw, I&#8217;m doing a talk tomorrow at the North West Ruby User Group in Manchester about how we do the Ruby on Rails hosting at Brightbox. I&#8217;ll be talking about SANs, Centos, Ubuntu, Xen, Apache, Lighty, NGINX, MySQL and other goodies. Heck, I might even mention Ruby, which would be nice considering it&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p>Oh, btw, I&#8217;m <a href="http://upcoming.yahoo.com/event/410420/">doing a talk tomorrow</a> at the <a href="http://nwrug.org/">North West Ruby User Group</a> in Manchester about how we do the <a href="http://www.brightbox.co.uk" title="UK Ruby on Rails hosting">Ruby on Rails hosting at Brightbox.</a></p>
<p>I&#8217;ll be talking about SANs, Centos, Ubuntu, Xen, Apache, Lighty, NGINX, MySQL and other goodies.  Heck, I might even mention Ruby, which would be nice considering it&#8217;s a Ruby user group.</p>
<p>My business partner Jeremy will be nattering about the business side and various other things.</p>
<p>Update: <a href="http://www.flickr.com/photos/brightbox/2229101203/in/set-72157603820858003/">A couple of photos here</a> and <a href="http://www.flickr.com/photos/fearoffish/2230724810/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2008/01/28/291/north-west-ruby-user-group-talk-building-brightbox/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rubinius multiple instances, one process</title>
		<link>http://johnleach.co.uk/words/archives/2008/01/15/290/rubinius-multiple-instances-one-process</link>
		<comments>http://johnleach.co.uk/words/archives/2008/01/15/290/rubinius-multiple-instances-one-process#comments</comments>
		<pubDate>Mon, 14 Jan 2008 23:42:56 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[processes]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rubinius]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2008/01/15/290/</guid>
		<description><![CDATA[Rubinius has support (as of today!) for running multiple instances of it&#8217;s VM within one process, each VM on it&#8217;s own *native* thread, each VM running many ruby green threads. Each VM has it&#8217;s own heap and so each VM could load different apps that wouldn&#8217;t interfere with each other. We have plans for a [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Rubinius has support (as of today!) for running multiple instances of it&#8217;s VM within one process, each VM on it&#8217;s own *native* thread, each VM running many ruby green threads. Each VM has it&#8217;s own heap and so each VM could load different apps that wouldn&#8217;t interfere with each other. We have plans for a mod_rubinius for apache that takes full advantage of this feature. Stay tuned ;)</p></blockquote>
<p>- <a href="http://brainspl.at/">Ezra Zygmuntowi </a>on a comment on <a href="http://www.rubyinside.com/no-true-mod_ruby-is-damaging-rubys-viability-on-the-web-693.html">Ruby Inside.</a></p>
<p>Very interesting stuff.  Why bother making Rails thread safe when you have an awesome Ruby VM such as Rubinius.  I&#8217;d like to see Mongrel (or FastCGI! Bring back FastCGI!) make use of this somehow, running multiple Rails instances itself in one process and distributing requests between them.  Interested in knowing how it&#8217;d deal with memory leaks in external libraries though (like rmagick suffers from).</p>
<p>Still, you lose finer grained access to most of the nice UNIX process management stuff though then, like limiting memory usage with ulimits, but nobody seems to be using that for Ruby deployment anyway.  It&#8217;s all fiddling around with Monit and such instead (why always with the steps backward!).</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2008/01/15/290/rubinius-multiple-instances-one-process/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reliable rake task execution</title>
		<link>http://johnleach.co.uk/words/archives/2007/12/03/287/reliable-rake-task-execution</link>
		<comments>http://johnleach.co.uk/words/archives/2007/12/03/287/reliable-rake-task-execution#comments</comments>
		<pubDate>Mon, 03 Dec 2007 00:17:14 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[crontab]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rake]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tasks]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/12/03/287/</guid>
		<description><![CDATA[My News Sniffer project needs to regularly do some back-end stuff like checking a bunch of rss feeds and downloading web pages. I do this with some rake tasks, which I call using the cron daemon.  Recently I&#8217;ve been having problems where some tasks take a bit longer than usual to complete and end up [...]]]></description>
			<content:encoded><![CDATA[<p>My <a href="http://www.newssniffer.co.uk">News Sniffer</a> project needs to regularly do some back-end stuff like checking a bunch of rss feeds and downloading web pages.  I do this with some rake tasks, which I call using the cron daemon.  Recently I&#8217;ve been having problems where some tasks take a bit longer than usual to complete and end up running in parallel.  This slows things down, which means more tasks end up running in parallel and then my little virtual machine eventually falls on it&#8217;s face under memory pressure.</p>
<p>I could implement some locking in my application, but it&#8217;s always good to avoid as much new code as possible so, in the good old *NIX fashion, I cobbled together a short bash script taking advantage of existing tools. What this does is executes the given rake task in the given rails root using the Debian/Ubuntu tool <code>start-stop-daemon</code> (provided by the <code>dpkg</code> package, which is therefore always installed).  <code>start-stop-daemon</code> uses a pid file to keep track of the rake program <em>for the given task</em>, so it will never run a second concurrent instance of rake for this task.  Cron just keeps trying to run it every 5 minutes or whatever, but it only runs once concurrently.<br />
<span id="more-287"></span><br />
Before running the rake task, my script also sets the maximum amount of cpu time can be used to the given number of seconds using the <code>ulimit</code> command.  So if anything goes a bit mad, taking ages to complete and uses loads of cpu time, it will be killed and then Cron will start it again on the next period.  I should do the same for ram usage too, but haven&#8217;t done yet.</p>
<p>It&#8217;s not completely fool-proof: for one, if a rake task hangs using no cpu it will never end and never be started again but this has not happened before and is still better than <em>all</em> tasks failing to run because the machine is unresponsive.</p>
<p>It&#8217;s executed thus (I set different nice values for different tasks using the <code>nice</code> directly in my crontab):</p>
<pre><code>run-rake.sh /home/john/railsroot taskname:whatever maxcpuseconds</code></pre>
<p>And here is the script:</p>
<pre><code>#!/bin/sh
railsdir=$1
raketask=$2
pidfile=$railsdir/log/$raketask.pid
cpuseconds=$3
export RAILS_ENV=production

ulimit -t $cpuseconds
exec /sbin/start-stop-daemon -d $railsdir -b -o -m -p $pidfile --start --startas /usr/bin/rake $raketask
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/12/03/287/reliable-rake-task-execution/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Eclipse IDE</title>
		<link>http://johnleach.co.uk/words/archives/2007/10/19/282/eclipse-ide</link>
		<comments>http://johnleach.co.uk/words/archives/2007/10/19/282/eclipse-ide#comments</comments>
		<pubDate>Fri, 19 Oct 2007 15:03:20 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/10/19/282/</guid>
		<description><![CDATA[I&#8217;ve just tried out the Eclipse Integrated Development Environment. It appears to be named Eclipse due to how it consumes all your CPU and RAM, overshadowing anything else you might want to do. I tried the RadRails addon thing out for developing Rails. It has some nice features but is rather a big jump from [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://johnleach.co.uk/words/wp-content/eclipse_home_header.jpg" alt="Eclipse logo" /> I&#8217;ve just tried out the Eclipse Integrated Development Environment.  It appears to be named Eclipse due to how it consumes all your CPU and RAM, overshadowing anything else you might want to do.</p>
<p>I tried the RadRails addon thing out for developing Rails.  It has some nice features but is rather a big jump from vim, which I&#8217;ve been using up until now.  And to the best of my memory, vim has never crashed once.  Whereas Eclipse has already crashed about 10 times in 24 hours.</p>
<p><strong>UPDATE</strong>: I used Eclipse for all my Ruby on Rails development for almost two weeks but I&#8217;ve now given up.  Even with leaky old Firefox and the monolith that is OpenOffice running concurrently I would rarely notice swapping, but Eclipse has decimated my swap partition.  It&#8217;s resource requirements (mostly RAM) have turned my brand new laptop into a 486 DX66 with 4MB RAM and a broken CPU fan.  It would regularly crash too.  Any time saving it&#8217;s features might have offered were well cancelled out by all the lost work.</p>
<p>I am using the Aptana Ruby on Rails Eclipse addons, so maybe you can blame that, though the Haskell addons were misbehaving too. Ridiculous stuff.</p>
<p>I&#8217;m just going to learn how to use some of the more advanced features of VIM.  I&#8217;m giving GVIM a go too.  Oh VIM, how I missed you so.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/10/19/282/eclipse-ide/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Segfault in Ruby Ferret query parser</title>
		<link>http://johnleach.co.uk/words/archives/2007/09/13/278/segfault-in-ruby-ferret-query-parser</link>
		<comments>http://johnleach.co.uk/words/archives/2007/09/13/278/segfault-in-ruby-ferret-query-parser#comments</comments>
		<pubDate>Thu, 13 Sep 2007 20:24:28 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[crash]]></category>
		<category><![CDATA[denial-of-service]]></category>
		<category><![CDATA[dos]]></category>
		<category><![CDATA[ferret]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[segfault]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/09/13/278/</guid>
		<description><![CDATA[Whilst working with the Ruby text search engine library Ferret, I came across a segfault in the query parser. It had already been reported and fixed, but I realised it can lead to a denial of service. If you use Ferret anywhere that allows users to execute queries, those users can crash the Ruby process [...]]]></description>
			<content:encoded><![CDATA[<p>Whilst working with the Ruby text search engine library Ferret, I came across a segfault in the query parser.  It had already <a href="http://ferret.davebalmain.com/trac/ticket/208">been reported</a> and <a href="http://ferret.davebalmain.com/trac/changeset/773">fixed</a>, but I realised it can lead to a denial of service.</p>
<p>If you use Ferret anywhere that allows users to execute queries, those users can crash the Ruby process with a specially crafted query.  This was quite serious for a number of my sites (not to mention slowing development of a current app) so I applied the fix to the released 0.11.4 source and repackaged it as 0.11.4.1.</p>
<p>Obviously this isn&#8217;t in any way official, but it works for me and I&#8217;m sharing here for anyone else affected.  <a href="http://johnleach.co.uk/downloads/ruby/ferret/ferret-0.11.4.1/" title="Ferret 0.11.4.1">Gem, tgz and zip here</a> and just the <a href="http://johnleach.co.uk/downloads/ruby/ferret/ferret-0.11.4-fix-multiterm-segfault.patch" title="Ferret 0.11.4.1 segault fix patch">patch available here</a>  (derived from the author&#8217;s changeset to trunk).</p>
<p>The patch is against the release source, as the subversion repository seems to be down atm (I got the changeset from the web bases subversion viewer).</p>
<p>Get upgrading!</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/09/13/278/segfault-in-ruby-ferret-query-parser/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>local and remote subversion repositories with Capistrano 2</title>
		<link>http://johnleach.co.uk/words/archives/2007/06/17/268/local-and-remote-subversion-repositories-with-capistrano-2</link>
		<comments>http://johnleach.co.uk/words/archives/2007/06/17/268/local-and-remote-subversion-repositories-with-capistrano-2#comments</comments>
		<pubDate>Sun, 17 Jun 2007 14:40:56 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/06/17/268/</guid>
		<description><![CDATA[Peeking at the code of the upcoming Capistrano 2, I noticed you can define different scm variables for remote and local use, which is something I need (I was looking at the code in the hope it could do this :) So, say I have my code stored in a subversion repository on my local [...]]]></description>
			<content:encoded><![CDATA[<p>Peeking at the code of the upcoming <a href="http://www.capify.org/">Capistrano 2</a>, I noticed you can define different scm variables for remote and local use, which is something I need (I was looking at the code in the hope it could do this :)</p>
<p>So, say I have my code stored in a subversion repository on my local disk, say <code>file:///project/trunk</code>.  That’s fine for when Capistrano is querying the latest revision, but the remote servers need to use the repository url <code>svn+ssh://mymachine/project/trunk</code>.</p>
<p>Without modifying the code, this was impossible with Capistrano v1. With Capistrano v2, you can prefix any scm configuration variable with <code>local_</code> and it will be used for local operations:</p>
<pre><code>set :repository, "svn+ssh://mymachine/project/trunk"
set :local_repository, "file:///project/trunk"</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/06/17/268/local-and-remote-subversion-repositories-with-capistrano-2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Leeds Ruby on Rails Talk</title>
		<link>http://johnleach.co.uk/words/archives/2007/06/05/266/leeds-ruby-on-rails-talk</link>
		<comments>http://johnleach.co.uk/words/archives/2007/06/05/266/leeds-ruby-on-rails-talk#comments</comments>
		<pubDate>Tue, 05 Jun 2007 14:53:15 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[talk]]></category>
		<category><![CDATA[wylug]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/06/05/266/</guid>
		<description><![CDATA[I&#8217;m talking about Ruby on Rails at the West Yorkshire Linux User Group on Monday 11th June 2007. I&#8217;ll be covering what Rail is, how it works, and how you use it. Starts at 1900hrs at the E.C Stoner (snigger) Building at the University of Leeds. There follows a talk about Sun&#8217;s ZFS file system [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://johnleach.co.uk/words/wp-content/rails.png" alt="Ruby on Rails logo" />I&#8217;m talking about Ruby on Rails at the West Yorkshire Linux User Group on Monday 11th June 2007.  I&#8217;ll be covering what Rail is, how it works, and how you use it.  Starts at 1900hrs at the E.C Stoner (snigger) Building at the University of Leeds.  There follows a talk about Sun&#8217;s ZFS file system by Tom Hall, then we retire to The Victoria Hotel pub for some real ale and whatnot.</p>
<p>I&#8217;ll be the tall one with the curly hair&#8230; stood at the front&#8230; talking about Ruby on Rails.</p>
<p>Directions and stuff to be found on <a href="http://www.wylug.org.uk/2007/05/monthly-meeting-11-june-2007/">the WYLUG website</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/06/05/266/leeds-ruby-on-rails-talk/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>News Sniffer, Ferret and Rails</title>
		<link>http://johnleach.co.uk/words/archives/2007/04/20/263/news-sniffer-ferret-and-rails</link>
		<comments>http://johnleach.co.uk/words/archives/2007/04/20/263/news-sniffer-ferret-and-rails#comments</comments>
		<pubDate>Fri, 20 Apr 2007 12:37:41 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ferret]]></category>
		<category><![CDATA[indexing]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[newssniffer]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[searching]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/04/20/263/</guid>
		<description><![CDATA[I&#8217;ve been working on my News Sniffer project for the last few days, finishing up a two month experiment with using the Ruby Lucene implementation, Ferret, to index news articles and comments.  More info on the News Sniffer blog.  The project spanned two months due to some instability in the newer versions of Ferret, but [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on my <a href="http://www.newssniffer.co.uk">News Sniffer</a> project for the last few days, finishing up a two month experiment with using the Ruby Lucene implementation, Ferret, to index news articles and comments.  More info on the <a href="http://www.newssniffer.co.uk/blog/2007/04/20/upgrade-wym-comment-cleanup-downtime-and-improved-search/">News Sniffer blog</a>.  The project spanned two months due to some instability in the newer versions of Ferret, but the author responded to the bug reports and managed to fix all the problems so I decided to deploy.</p>
<p>Ferret offers huge improvements over the original MySQL full-text search method, and I&#8217;m looking forward to adding some fancy keyword statistics graphs in the future &#8211; perhaps showing censorship patterns in bbc comments with certain keywords.</p>
<p>Because News Sniffer is distributed across a number of servers, I used DRb (distributed Ruby) to allow them all to update one central Ferret index.  DRb seems to work very well generally, and is amazingly simple to use, but I ran into a few problems with recycled objects and invalid references whilst using Ferret across it, apparently due to the garbage collector on the service side collecting things still in use on the client side.  I think I eliminated most of them but they still crop up once in a while &#8211; I&#8217;ll be looking into this further.</p>
<p><span id="more-263"></span>I also moved from using memcached for cache fragment storage to FileStore.  This allows me to expire fragments using  regular expressions, which lets me use fragment caching more easily and more often (such as with paged listing).  FileStore is rather slower than memcached, especially when expiring using these regular expressions, but being able to use it more often outweighed the performance hit.  FileStore is obviously not distributed unless you have a shared file system, so I used DRb here too.</p>
<p>It would be nice to add regular expression expiry to memcached, but I think this goes against the original design spec for memcached.  I&#8217;m considering adding configurable memory limits to the Rails MemoryStore fragment store, where it&#8217;ll remove least recently used fragments when the limit is approached (currently it would just keep allocating ram until your OS killed your Ruby process).</p>
<p>I also found a (easily fixable on Linux/BSD) race condition in FileStore where you could theoretically retrieve a corrupted fragment when it&#8217;s used in a multi-process shared storage setup (though not a multi-thread setup, so my DRb&#8217;ed FileStore should be safe).</p>
<p>Hopefully, with the improved searching due to Ferret and the  higher performance due to FileStore, News Sniffer will now be more useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/04/20/263/news-sniffer-ferret-and-rails/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Daemontools and Ruby on Rails</title>
		<link>http://johnleach.co.uk/words/archives/2007/04/08/262/daemontools-and-ruby-on-rails</link>
		<comments>http://johnleach.co.uk/words/archives/2007/04/08/262/daemontools-and-ruby-on-rails#comments</comments>
		<pubDate>Sun, 08 Apr 2007 11:46:51 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[daemontools]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/04/08/262/</guid>
		<description><![CDATA[Dan J Bernstein&#8217;s (djb) daemontools is a set of programs to help you manage unix services. It provides a flexible, secure and convenient way of starting, stopping and sending signals to background processes. Combined with his ucspi-tcp tools, it can be used as an awesome replacement to inetd (it&#8217;s most often used in this way [...]]]></description>
			<content:encoded><![CDATA[<p>Dan J Bernstein&#8217;s (djb) <a href="http://cr.yp.to/daemontools.html" title="daemontools website">daemontools</a> is a set of programs to help you manage unix services.  It provides a flexible, secure and convenient way of starting, stopping and sending signals to background processes.  Combined with his <a href="http://cr.yp.to/ucspi-tcp.html">ucspi-tcp</a> tools, it can be used as an awesome replacement to inetd (it&#8217;s most often used in this way to run <a href="http://cr.yp.to/qmail.html">qmail</a>, a secure and high-performance mta).  It can be fiddly to set up and has a bit of a steep learning curve but I already use daemontools for various other stuff, so it was just natural for me to use it for Ruby on Rails deployment.</p>
<p><span id="more-262"></span></p>
<p>Djb has some interesting ideas about how we should be doing things on unix, namely: very differently from how we&#8217;re doing things now.  As his own software follows these rules, it tends to seem a bit odd to a new user, especially the filesystem layout.  He also doesn&#8217;t allow modified versions of his software to be distributed, so it&#8217;s a bit tricky for GNU/Linux distros to &#8220;fix&#8221; it.  Most distros get around this by distributing a source-only package, which automatically patches the code and builds you your own package &#8211; you just can&#8217;t then distribute this package to others.</p>
<p>This makes djb&#8217;s software technically non-free in the <a href="http://www.gnu.org/philosophy/free-sw.html">FSF sense</a>.  Some argue that it&#8217;s these license limitations that have kept his software so secure all these years.  I&#8217;m side stepping the issue for now &#8211; I&#8217;m either a pragmatist or I just don&#8217;t care about your freedom.  Try to decide which it is, and whether there is actually a difference.</p>
<p>Anyway, follow the docs for your distro and get daemontools up and running then I can focus on the Ruby on Rails aspect.  This post is getting a little too long and windy already.</p>
<h2>Rails</h2>
<p>So, the usual way to deploy a FastCGI RoR app is to run the spawner script to start it, then run the script every 5 minutes or so to restart the process if it crashes.  This maybe be convenient but it&#8217;s just laughable.  It delays startup on boot, leaves you high and dry for 5 minutes if ruby crashes and wastes resources checking.  And the reaper script, for restarting and stopping the process, just looks in the process list to find the pid.  More chuckling.  What decade are we in?</p>
<p>We&#8217;re going to run the RoR FastCGI process under daemontools.  It takes a little initial setup, and with multiple daemons some duplication of configs, but it will start immediately (or asap) on boot, will be restartable/reloadable without guessing pids and will restart automatically if ruby crashes.  We can even do &#8220;advanced&#8221; security stuff such as dropping secondary groups, setting resource limits and even logging that can&#8217;t be manipulated by an attacker compromising ruby.</p>
<h2>Daemontools setup</h2>
<p>Our rails app is called shop and it&#8217;s located on the filesystem at <code>/home/web/shop/current</code>.  We are going to run it as the user <code>web</code> on port 12000.  We need the <code>spawn-fcgi</code> tool from <code>lighttpd</code> too.  We&#8217;re going to run the log process as the user <code>rorlog</code>.  You need root access on the deployment box but that shouldn&#8217;t be a problem for a serious deployment.  I do have a way of configuring daemontools to allow your users to safely setup and control their own processes, but I&#8217;ll save that for another post.</p>
<ol>
<li>Make a new service directory for this service:
<pre><code>mkdir /var/lib/ror-shop</code></pre>
</li>
<li>Create the service run script (and make it executable):
<pre><code>cat &gt; /var/lib/ror-shop/run
#!/bin/sh
export RAILS_ENV=production
exec /usr/bin/spawn-fcgi -u web -g web -n -p 12000 -f /home/web/shop/current/public/dispatch.fcgi
</code></pre>
</li>
<li>Create the service log directory:
<pre><code>mkdir -p /var/lib/ror-shop/log/main</code></pre>
</li>
<li>Create the log service run script (and make it executable):
<pre><code>cat &gt; /var/lib/ror-shop/log/run
#!/bin/sh
exec setuidgid rorlog multilog t ./main
</code></pre>
</li>
<li>Symlink the new service into the daemontools services directory (usually <code>/service</code>):
<pre><code>ln -s /var/lib/ror-shop /service</code></pre>
</li>
</ol>
<p>Within 5 seconds, daemontools will see the new service and start both the ror and the log run scripts.</p>
<p>If you need to run a few processes on different ports, just make a service for each process and modify the run script to change the port.</p>
<p>By default, the logs rotate at 99999 bytes and keep 10 files archive.  See the <a href="http://cr.yp.to/daemontools/multilog.html">multilog</a> docs for arguments to change this</p>
<h2>Controlling your processes</h2>
<p>To control the process you use the <code>svc</code> command.  For example to restart the service:</p>
<pre><code>svc -t /service/ror-shop</code></pre>
<p><code>-d</code> to stop it, <code>-u</code> to start it, <code>-h</code> to reload the app, <code>-k</code> to kill it if ruby goes haywire (daemontools will restart it immediately).</p>
<p>I&#8217;m using <code>spawn-fcgi</code> to set the uid/gid because I need to preserve secondary groups in my setup and it does this.  If you don&#8217;t need this, I&#8217;d recommend using the <a href="http://cr.yp.to/daemontools/setuidgid.html">setuidguid</a> tool that comes with daemontools:</p>
<pre><code>exec setuidguid web /usr/bin/spawn-fcgi -n -p 12000 -f /home/web/shop/current/public/dispatch.fcgi</code></pre>
<p>To set some resource limits you can use the <a href="http://cr.yp.to/daemontools/softlimit.html">softlimit</a> tool.  To limit rails to 30M of ram and 300 file descriptors, use something like:</p>
<pre><code>exec softlimit -m 31457280 -o 300 setuidguid web /usr/bin/spawn-fcgi -n -p 12000 -f /home/web/shop/current/public/dispatch.fcgi</code></pre>
<p>As you can see, daemontools can be a bit tricky for a new user and a bit fiddly for a the initial setup but it is reliable, secure and flexible enough to cover most Ruby on Rails deployments for sure.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/04/08/262/daemontools-and-ruby-on-rails/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Active Resource not in Rails 1.2!</title>
		<link>http://johnleach.co.uk/words/archives/2007/02/05/252/active-resource-not-in-rails-12</link>
		<comments>http://johnleach.co.uk/words/archives/2007/02/05/252/active-resource-not-in-rails-12#comments</comments>
		<pubDate>Mon, 05 Feb 2007 12:31:26 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[active resource]]></category>
		<category><![CDATA[activeresource]]></category>
		<category><![CDATA[distributed ruby]]></category>
		<category><![CDATA[drb]]></category>
		<category><![CDATA[ferret]]></category>
		<category><![CDATA[news sniffer]]></category>
		<category><![CDATA[newssniffer]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2007/02/05/252/</guid>
		<description><![CDATA[Whilst planning some changes to my News Sniffer project, I thought I&#8217;d have a play with Active Resource. Currently, all the forum and news article downloading and scraping happens on a different machine to the web server. It has a VPN connection to the database and memcache servers, but I&#8217;d like to integrate the Ferret [...]]]></description>
			<content:encoded><![CDATA[<p>Whilst planning some changes to my <a href="http://newssniffer.newworldodour.co.uk" title="News Sniffer" target="_blank">News Sniffer project</a>, I thought I&#8217;d have a play with Active Resource.</p>
<p>Currently, all the forum and news article downloading and scraping happens on a different machine to the web server.  It has a VPN connection to the database and memcache servers, but I&#8217;d like to integrate the <a href="http://http://ferret.davebalmain.com/trac/" target="_blank">Ferret</a> text indexing system for better searching capabilities.  To centralise Ferret, I have a three options:</p>
<ol>
<li>regularly reindex new content from the database on the web server;</li>
<li><a href="http://chadfowler.com/ruby/drb.html" title="Distributed Ruby" target="_blank">DRb</a> a Ferret Object;</li>
<li>or use ActiveResource to access the models via the web service.</li>
</ol>
<p>DRb-ing a Ferret Object would be quite elegant, but using ActiveResource would also replace the need for a database and memcache connection (and I could do much better fragment caching actually).</p>
<p>Anyway, I searched high and low for some docs &#8211; lots of blog entries about how great it is, but no real api docs.  When I searched through the Rails code and found nothing either, I got suspicious.  Finally I found a couple of blog entries stating that <strong>ActiveResource was dropped from Rails 1.2</strong>.  It seems to be planned for Rails 2.0.  Not sure how I missed this.  I guess my search-foo is lacking.</p>
<p>I&#8217;ll be investigating other options.  I&#8217;d much prefer not to build a SOAP or XMLRPC interface. Ugh.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2007/02/05/252/active-resource-not-in-rails-12/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bruce Schneier whistles white noise</title>
		<link>http://johnleach.co.uk/words/archives/2006/08/17/235/bruce-schneier-whistles-white-noise</link>
		<comments>http://johnleach.co.uk/words/archives/2006/08/17/235/bruce-schneier-whistles-white-noise#comments</comments>
		<pubDate>Thu, 17 Aug 2006 12:29:00 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[bruce schneier]]></category>
		<category><![CDATA[comic]]></category>
		<category><![CDATA[eler]]></category>
		<category><![CDATA[lighttpd]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2006/08/17/235/</guid>
		<description><![CDATA[The new ELER strip is about Bruce Schneier and links to a Chuck Norris style Bruce Schneier Facts Database system I wrote. It got linked from Boingboing, Metafilter, Reddit and even Bruce Schneier&#8217;s own blog! As you might imagine, it&#8217;s getting trabigillions of hits right now. Lucky I wrote it in Ruby on Rails with [...]]]></description>
			<content:encoded><![CDATA[<p>The new <a href="http://geekz.co.uk/lovesraymond">ELER strip</a> is about Bruce Schneier and links to a Chuck Norris style <a href="http://geekz.co.uk/schneierfacts/">Bruce Schneier Facts Database</a> system I wrote.  It got linked from Boingboing, Metafilter, Reddit and even <a href="http://www.schneier.com/blog/archives/2006/08/bruce_schneier.html">Bruce Schneier&#8217;s own blog!</a></p>
<p>As you might imagine, it&#8217;s getting trabigillions of hits right now.  Lucky I wrote it in Ruby on Rails with its built in page caching which (after first render) serves as fast as the webserver can serve.  And since I&#8217;m using <a href="http://www.lighttpd.net">Lighttpd</a> too, that is very fast.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2006/08/17/235/bruce-schneier-whistles-white-noise/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Can I Compost This?</title>
		<link>http://johnleach.co.uk/words/archives/2006/08/14/233/can-i-compost-this</link>
		<comments>http://johnleach.co.uk/words/archives/2006/08/14/233/can-i-compost-this#comments</comments>
		<pubDate>Mon, 14 Aug 2006 10:29:48 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[compost]]></category>
		<category><![CDATA[composting]]></category>
		<category><![CDATA[garden]]></category>
		<category><![CDATA[kitchen]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[recycling]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubyonrails]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2006/08/14/233/</guid>
		<description><![CDATA[Louisa and I am announcing our latest project: Compost This. It&#8217;s a directory of items with information about it&#8217;s compostability. For example Tea and Flour can be put on the compost heap, but Bindweed and Walnuts cannot. And it&#8217;s not always a good idea to put Orange peel on there either. For geeks: I wrote [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.compostthis.co.uk" title="Can I compost this?"><img src="http://www.compostthis.co.uk/images/button.png" alt=""/></a><a href="http://www.louisaparry.co.uk">Louisa</a> and I am announcing our latest project: <a href="http://www.compostthis.co.uk">Compost This</a>.  It&#8217;s a directory of items with information about it&#8217;s compostability.</p>
<p>For example <a href="http://www.compostthis.co.uk/item/tea">Tea</a> and <a href="http://www.compostthis.co.uk/item/flour">Flour</a> can be put on the compost heap, but <a href="http://www.compostthis.co.uk/item/bindweed">Bindweed</a> and <a href="http://www.compostthis.co.uk/item/walnuts">Walnuts</a> cannot.  And it&#8217;s not always a good idea to put <a href="http://www.compostthis.co.uk/item/oranges">Orange peel</a> on there either.</p>
<p>For geeks: I wrote Compost This using <a href="http://www.rubyonrails.org">Ruby on Rails</a>, which is one of the best web frameworks I&#8217;ve used, and I&#8217;m really starting to love the Ruby language too.  I&#8217;ll release the code soon as an example.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2006/08/14/233/can-i-compost-this/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lighttpd and Ruby on Rails: Secure and Fast Downloading</title>
		<link>http://johnleach.co.uk/words/archives/2006/03/16/213/lighttpd-and-ruby-on-rails-secure-and-fast-downloading</link>
		<comments>http://johnleach.co.uk/words/archives/2006/03/16/213/lighttpd-and-ruby-on-rails-secure-and-fast-downloading#comments</comments>
		<pubDate>Thu, 16 Mar 2006 13:38:10 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2006/03/16/213/</guid>
		<description><![CDATA[When controlling access to files on a webserver developers often use the web application itself as a file server. The request comes in, the script checks for some session authentication variable or something, then streams the file from disk (hopefully from outside the webroot) to the browser. The problem with this from a performance standpoint [...]]]></description>
			<content:encoded><![CDATA[<p>When controlling access to files on a webserver developers often use the web application itself as a file server.  The request comes in, the script checks for some session authentication variable or something, then streams the file from disk (hopefully from outside the webroot) to the browser.</p>
<p>The problem with this from a performance standpoint is that a thread/process of the web application has to be running for the entire duration of the download.  With a busy webserver serving many concurrent downloads, this is an immense overhead.  The web server itself should be orders of magnitude faster at serving files directly than via a web application, but you can&#8217;t just stick the files in a different directory and hope nobody finds the secret urls.  The new web server on the block, <a href="http://www.lighttpd.net">Lighttpd</a>, has some clever solutions for this problem.<br />
<span id="more-213"></span></p>
<h2>mod_secdownload</h2>
<p>Lighttpd has a module called <a href="http://www.lighttpd.net/documentation/secdownload.html">mod_secdownload</a> which allows a web application to generate a time limited authenticated url to a file.</p>
<p>Basically, you stick all your files in a directory outside the web root.  Then configure lighttpd to tell it the path to this dir, a secret password and how long to keep a generated url valid.  Now you code your web application to receive a request, check the session auth stuff, then generate this time limited url (authenticated with the same secret password as lighttpd) and redirect the browser to it.  The browser then makes a new request using this url but is this time served directly by lighttpd without invoking your web application, and therefore goes super awesome fast.  Another benefit is that your web application doesn&#8217;t need to be on the same server as your files, so you can load balance your file hosting server around the globe without them needing access to your database or anything complicated like that.</p>
<p>Anyone eavesdropping on the session could get the file url, but it would only be valid for as long as you configured lighttpd.  If security is key, then configure this period to be very short.  If your web application is on a different server to the one holding the files, then you need to ensure the clocks are synced on them.  If your files aren&#8217;t sensitive and you&#8217;re just trying to prevent hot linking, then choose a larger period.</p>
<p>The lighttpd setup is well explained on the <a href="http://www.lighttpd.net/documentation/secdownload.html">mod_secdownload documentation page</a>, along with an example of how to generate urls in PHP.</p>
<p>I wrote the following Ruby on Rails helper for something I&#8217;m working on.  You should be able to modify it for your own purposes.<br />
<code> </code></p>
<pre>
   def asset_url(asset)
           secret = "mysecretpassword" # same as in lighttpd
           uri_prefix = "/asset_files/" # same as in lighttpd
           filename = "/#{asset.id}"
           t = Time.now.to_i.to_s( base=16 ) # unixtime in hex
           hash = Digest::MD5.new( "#{secret}#{filename}#{t}" )
           "#{uri_prefix}#{hash}/#{t}#{filename}"
   end</pre>
<p>In my case I&#8217;m just preventing hotlinking, so urls are valid for 10 minutes.  Since time has a habit of increasing every second, you get new urls to the same files every second which sucks for caching.  I fixed this by only generating a new URL every 5 minutes. So, before converting to hex:<br />
<code>t = t - t.modulo(300) # modulo must be half secdownload.timeout</code></p>
<h2>X-LIGHTTPD-send-file header</h2>
<p>There is another, easier option.  Have your web application do the session magic checks, then simply return a special header to lighttpd telling it serve a file from the filesystem to the browser.  Your web app terminates and lighttpd takes over.</p>
<p><code>X-LIGHTTPD-send-file: /var/assets/filename</code></p>
<p>Obviously this only works if your files are being served from the same web server as the web application.  Also, you need to be careful about sending user defined data to the header, as the web server will serve up any file it has permissions to if asked.  And you need to make sure lighttpd is configured to accept these headers too.</p>
<p>Additionally, I&#8217;ve not tried this method myself so I might have just made it all up in my head and the feature doesn&#8217;t exist.</p>
<p>More about all this can be found on the <a href="https://trac.lighttpd.net/trac/wiki/HowToFightDeepLinking">lighttpd wiki</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2006/03/16/213/lighttpd-and-ruby-on-rails-secure-and-fast-downloading/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>I changed his life through webdev</title>
		<link>http://johnleach.co.uk/words/archives/2006/02/19/209/i-changed-his-life-through-webdev</link>
		<comments>http://johnleach.co.uk/words/archives/2006/02/19/209/i-changed-his-life-through-webdev#comments</comments>
		<pubDate>Sun, 19 Feb 2006 16:37:59 +0000</pubDate>
		<dc:creator>john</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[coldfusion]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubyonrails]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://johnleach.co.uk/words/archives/2006/02/19/209/</guid>
		<description><![CDATA[A couple of months ago I was having an IM conversation with an old web developer work friend and asked him if he&#8217;d played with Ruby on Rails yet. He told me not and I enquired as to whether he&#8217;d been living in a mud hut within a rain forest for the last year. He [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of months ago I was having an IM conversation with an old web developer work friend and asked him if he&#8217;d played with <a href="http://www.rubyonrails.com/">Ruby on Rails</a> yet.  He told me not and I enquired as to whether he&#8217;d been living in a mud hut within a rain forest for the last year.  He told me not.  I pointed him in the right direction and he said he&#8217;d take a look sometime.</p>
<p>Today, after no further conversion, I got this message from him:</p>
<blockquote><p>(16:14:48) Sid: Hey John!! Just wanted to say thanks for introducing me to Ruby on Rails.. I&#8217;ve picked up on it and its changed my life. Now I&#8217;m working a contract for the government and dating a hot american chick from new york. btw &#8211; like the photo. its class.<br />
(16:16:16) Sid logged out.
</p></blockquote>
<p>He used to be a Coldfusion developer.  After finding Ruby on Rails he must look back on Coldfusion and laugh up hard matter from his lower intestine.</p>
<p>Anybody else want to comment on how I&#8217;ve changed their life?  If you only met me once and had to spend the rest of your life avoiding me it still counts.</p>
]]></content:encoded>
			<wfw:commentRss>http://johnleach.co.uk/words/archives/2006/02/19/209/i-changed-his-life-through-webdev/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
