<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Development Doodles</title>
	<atom:link href="http://devdoodles.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://devdoodles.wordpress.com</link>
	<description>Random notes on development</description>
	<lastBuildDate>Fri, 26 Aug 2011 20:42:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='devdoodles.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://1.gravatar.com/blavatar/5673f4556351214ae11a166cc8f6d4a2?s=96&#038;d=http%3A%2F%2Fs2.wp.com%2Fi%2Fbuttonw-com.png</url>
		<title>Development Doodles</title>
		<link>http://devdoodles.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://devdoodles.wordpress.com/osd.xml" title="Development Doodles" />
	<atom:link rel='hub' href='http://devdoodles.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Http response time monitoring with Munin</title>
		<link>http://devdoodles.wordpress.com/2009/12/03/http-response-time-monitoring-with-munin/</link>
		<comments>http://devdoodles.wordpress.com/2009/12/03/http-response-time-monitoring-with-munin/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 07:38:10 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[munin]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=342</guid>
		<description><![CDATA[There&#8217;s nothing better than graphs, and for a web site there are few better things to graph than the response times for your web pages. While there are plenty of external services out there that will probe your web site &#8230; <a href="http://devdoodles.wordpress.com/2009/12/03/http-response-time-monitoring-with-munin/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=342&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s nothing better than graphs, and for a web site there are few better things to graph than the response times for your web pages.  While there are plenty of external services out there that will probe your web site and graph the results, it&#8217;s a good idea to do this on your own too.</p>
<p><a href="http://munin.projects.linpro.no/">Munin</a> is a monitoring tool that can provide graphs in plentiful for your servers.  Out of the box, or at least out of its Ubuntu box, it monitors a variety of system metrics and applications, but there is no bundled support for response-time monitoring.</p>
<p>Luckily, it&#8217;s really easy to extend Munin with new plugins, so I decided to write my own plugin for monitoring response times, which you can download from <a href="http://bitbucket.org/devdoodles/http_response_time/wiki/Home">my bitbucket repository</a>.  It will produce graphs like the one below:</p>
<p><a href="http://devdoodles.files.wordpress.com/2009/11/http_response_time-example.png"><img src="http://devdoodles.files.wordpress.com/2009/11/http_response_time-example.png?w=495&#038;h=300" alt="http_response_time_ example graph" title="http_response_time_ example graph" width="495" height="300" class="alignnone size-full wp-image-343" /></a></p>
<p>Here the plugin has been configured to monitor three URLs in the same graph.  Unlike normal Munin probes these URLs are external to the actual server running the plugin, but you could just as well monitor localhost URLs too.</p>
<p>To get the plugin up and running you first need to install Munin, if you haven&#8217;t already.  For a one-server setup under Ubuntu, with master and client both running on the same machine, you do:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install munin munin-node
</pre>
<p>This will start the munin-node service in the background, and also add the master-node cron jobs to /etc/cron.d/munin.  To install the plugin itself you add the Python script to a folder of your choice, make it executable, and then symlink it from the Munin plugin folder, like so:</p>
<pre style="background:#f5f5f5;">
sudo cp ./http_response_time_ /usr/local/bin/
sudo chmod 755 /usr/local/bin/http_response_time_
sudo ln -s /usr/local/bin/http_response_time_ /etc/munin/plugins/http_response_time_example
</pre>
<p>If you want to monitor more than one set of URLs, and thus have more than one graph, you can accomplish that by creating one symlink for each graph that you need.  The names of the symlinks are used as section titles when configuring the plugin in /etc/munin/plugin-conf.d/munin-node.  For the graph shown above, the configuration would look something like this:</p>
<pre style="background:#f5f5f5;">
[http_response_time_example]
env.url1_url http://www.djangoproject.com/
env.url1_name django
env.url1_label djangoproject.com
env.url2_url http://rubyonrails.org/
env.url2_name rails
env.url2_label rubyonrails.org
env.url3_url http://php.net/
env.url3_name php
env.url3_label php.net
</pre>
<p>The plugin requires that the following environment variables are specified for each URL to be monitored:</p>
<ul>
<li>urlX_url &#8212; the URL that should be monitored</li>
<li>urlX_name &#8212; Munin field name for the probe</li>
<li>urlX_label &#8212; legend description of the URL</li>
</ul>
<p>The &#8216;X&#8217; in the variable names above should be replaced with an incremental index for each URL, e.g. url1 and url2.  In addition, the following environment variables are also supported:</p>
<ul>
<li>graph_title &#8212; the title of the graph (default is &#8220;Response time&#8221;)</li>
<li>graph_category &#8212; the category Munin should show the graph in</li>
<li>request_timeout &#8212; the socket request timeout (same for all URLs)</li>
<li>urlX_warning &#8212; warning level for the probe (for Nagios)</li>
<li>urlX_critical &#8212; critical level for the probe (for Nagios)</li>
</ul>
<p>Note that Munin uses its own timeout when fetching plugin data.  The default value is 10 seconds, which also is the default value for the URL request timeout.  Because of this it might be appropriate to increase the Munin fetch timeout so that it equals the number of URLs being monitored times the request timeout, to make sure all probes have time to run.</p>
<p>Once you have configured the plugin to your satisfaction you need to restart the Munin node to make it discover the new plugin:</p>
<pre style="background:#f5f5f5;">
sudo /etc/init.d/munin-node restart
</pre>
<p>Happy graphing!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/342/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/342/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/342/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=342&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/12/03/http-response-time-monitoring-with-munin/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>

		<media:content url="http://devdoodles.files.wordpress.com/2009/11/http_response_time-example.png" medium="image">
			<media:title type="html">http_response_time_ example graph</media:title>
		</media:content>
	</item>
		<item>
		<title>Django performance tip: select_related()</title>
		<link>http://devdoodles.wordpress.com/2009/06/27/django-performance-tip-select_related/</link>
		<comments>http://devdoodles.wordpress.com/2009/06/27/django-performance-tip-select_related/#comments</comments>
		<pubDate>Sat, 27 Jun 2009 22:14:41 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=325</guid>
		<description><![CDATA[I was optimizing a Django application I&#8217;m working on the other day using Simon Willison&#8217;s excellent DebugFooter middleware, which adds a footer to each page showing which SQL queries were executed by Django when generating the page. I&#8217;m a bit &#8230; <a href="http://devdoodles.wordpress.com/2009/06/27/django-performance-tip-select_related/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=325&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I was optimizing a Django application I&#8217;m working on the other day using Simon Willison&#8217;s excellent <a href="http://www.djangosnippets.org/snippets/766/">DebugFooter</a> middleware, which adds a footer to each page showing which SQL queries were executed by Django when generating the page.</p>
<p>I&#8217;m a bit of a caching addict so I had already added a caching layer on top of my models, and thus I was quite surprised to find that the most important page on the site still generated 5-15 SQL queries on every access, even though the objects it was accessing supposedly were cached.</p>
<p>The objects were indeed cached, but every time I was accessing one of the ForeignKey fields on the model objects Django generated a SQL query to find the data for the related object.  This could quickly turn nasty if you follow such relationships in a loop on a high-traffic web site.</p>
<p>The solution was the <a href="http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4">select_related()</a> QuerySet method.  Borrowing from the Django documentation, a normal ORM lookup would look like this:</p>
<pre class="brush: python;">
e = Entry.objects.get(id=5)
b = e.blog
</pre>
<p>This would generate two SQL queries, one to fetch the entry object and one to fetch the blog object once it&#8217;s referred to from the entry object.  The same example with select_related() becomes:</p>
<pre class="brush: python;">
e = Entry.objects.select_related().get(id=5)
b = e.blog
</pre>
<p>This example only generates one SQL query, albeit bigger and slower than each of the individual queries in the first example because of the necessary join between the model tables to find all the data in one go.  However, this doesn&#8217;t matter if the fetched object will go directly into a cache anyway and stay there for a possibly rather long time, which was the case for me.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/325/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/325/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/325/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=325&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/06/27/django-performance-tip-select_related/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Some notes on Amazon, Tarzan, and Yii</title>
		<link>http://devdoodles.wordpress.com/2009/05/08/some-notes-on-amazon-tarzan-and-yii/</link>
		<comments>http://devdoodles.wordpress.com/2009/05/08/some-notes-on-amazon-tarzan-and-yii/#comments</comments>
		<pubDate>Fri, 08 May 2009 21:51:54 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[php framework]]></category>
		<category><![CDATA[tarzan]]></category>
		<category><![CDATA[yii]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=281</guid>
		<description><![CDATA[Today Amazon announced yet another new name for its excellent product feed API: Product Advertising API. It was formerly called the Amazon Associates Web Service, and it provides access to Amazon&#8217;s vast database of product offers and related content such &#8230; <a href="http://devdoodles.wordpress.com/2009/05/08/some-notes-on-amazon-tarzan-and-yii/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=281&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Today Amazon announced yet another new name for its excellent product feed API: <a href="https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html">Product Advertising API</a>.  It was formerly called the Amazon Associates Web Service, and it provides access to Amazon&#8217;s vast database of product offers and related content such as user reviews.  It has been around since 2004 so it&#8217;s certainly not a new service, but I recently decided it was time I tried it out.</p>
<p><strong>Choosing an API implementation</strong><br />
<a href="http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/">Implementing the API</a> manually wouldn&#8217;t be too hard, but I figured someone would have done it for me already.  Surprisingly, I did not find anything for Python that seemed mature or up-to-date.  <a href="http://pyaws.sourceforge.net/">PyAWS</a> was last touched in 2007, and <a href="http://code.google.com/p/pyecs/">pyecs</a> only implements a subset of the API operations.</p>
<p>Although I&#8217;m sure something could be built on pyecs or PyAWS, I found that both PHP and Ruby had more mature packages available, in the shape of <a href="http://tarzan-aws.com/">Tarzan</a> and <a href="http://www.caliban.org/ruby/ruby-aws/">ruby-aws</a>.  Having also wanted to look into PHP web frameworks for a while, I decided this was a good opportunity so I went with Tarzan.</p>
<p><strong>Choosing a PHP web framework</strong><br />
There&#8217;s a gazillion PHP frameworks out there, and most of them seem to have their fair share of loud-spoken supporters.  Coming from Django, naturally my first thought was that I wanted the PHP framework equivalent of it.  After some fruitless googling I decided there was no such thing, and instead I decided the selection criteria to be something fast, light-weight, and PHP5-based.  </p>
<p>With the help of posts like <a href="http://www.beyondcoding.com/2009/03/02/choosing-a-php-framework-round-2-yii-vs-kohana-vs-codeigniter/">this</a>, <a href="http://daniel.carrera.bz/2009/01/comparison-of-php-frameworks-part-i/">this</a>, and <a href="http://2tbsp.com/node/87">this</a>, I somewhat arbitrarily narrowed down the contenders to Kohana, Zend, and Yii, and ultimately picked <a href="http://www.yiiframework.com/">Yii</a> since it was the new kid on the block.</p>
<p><strong>A few snags&#8230;</strong><br />
I ran into a few snags during my brief foray into PHP land with Tarzan and Yii so I thought I&#8217;d write them down here, just in case it might help someone facing the same issues as I did, or in case I run into them again myself. <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<ul>
<li>There&#8217;s a <a href="http://code.google.com/p/tarzan-aws/issues/detail?id=134">bug</a> in the stable version on Tarzan that makes it <em>ignore</em> any Amazon Associate IDs you supply in the configuration or the class constructors.  Product links returned by the Amazon API will because of this not be tracked, which means you won&#8217;t get any revenue share from Amazon to your affiliate account.</li>
<li>Tarzan returns SimpleXML objects, but apparently it&#8217;s <a href="http://www.php.net/manual/en/function.serialize.php#function.serialize.notes">not possible to serialize PHP built-in objects</a>.  I learned this when I tried to put the data I got back from Tarzan uncasted into memcached, and got this perplexing error message on retrieval:
<p><em>unserialize() [function.unserialize]: Node no longer exists</em>
</li>
<li>I first had multiple class definitions per PHP file, and this worked fine with Yii and its autoload support.  However, when I tried to put these objects into memcached I again got confusing errors when they were unserialized, e.g.:
<p><em>YiiBase::include(BrowseNode.php) [yiibase.include]: failed to open stream: No such file or directory</em></p>
<p>The BrowseNode class was not defined in a file of its own, and I suppose that&#8217;s why it couldn&#8217;t be found.  When I moved it into a separate BrowseNode.php file, things started to work.
</li>
<li><strong>Update: this note is not quite correct, please see the comments below this post!</strong> <del datetime="2009-05-27T16:59:25+00:00">Something really weird happens when you try to use the CHtml class in Yii to output an image with an empty or missing URL.  This will make the controller action <em>execute twice</em>!  I have no idea why this happens but it took me a good while to track down the cause.  To reproduce, add the line below to a view in your Yii application and add a log statement to the corresponding controller action:</del>
<pre class="brush: php;">
</pre>
</li>
</ul>
<p><strong>Final words</strong><br />
Amazon&#8217;s product API really is a solid, fast, and comprehensive service that deserves all the praise it has received.  With the new API name, Amazon today also announced that API requests in the future will have to be <a href="http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?RequestAuthenticationArticle.html">authenticated</a> through a hash calculated for every request based on your AWS identifiers and the parameters of the request.  This requirement is phased in over a period ending on August 15, 2009.  </p>
<p>Tarzan obviously lacks support for this, but at least the author is <a href="http://groups.google.com/group/tarzan-aws/browse_thread/thread/4435c184ad334542">aware of the change</a>.  Apart from this and the annoying Associate ID bug I mentioned previously, Tarzan worked great for me and I wouldn&#8217;t hesitate to use it again, seeing that it&#8217;s actively maintained and tries to stay on top of Amazon&#8217;s evolution of services.</p>
<p>As for Yii, I did not use it enough to give a proper verdict &#8212; I barely tested the ORM support for instance &#8212; but it was easy getting started and its MVC structure seemed logical enough, although the relative youth of the framework is visible in some rough edges here and there.  Yii markets itself as a high-performance framework and although I don&#8217;t have that many reference points, the execution speed was more than satisfactory.  Would I use it again?  Probably, but I&#8217;ll check out Kohana too at some point.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/281/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/281/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/281/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=281&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/05/08/some-notes-on-amazon-tarzan-and-yii/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Django shortcomings and Facebook architecture</title>
		<link>http://devdoodles.wordpress.com/2009/04/09/django-shortcomings-and-facebook-architecture/</link>
		<comments>http://devdoodles.wordpress.com/2009/04/09/django-shortcomings-and-facebook-architecture/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 13:27:44 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[djangocon]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[presentation]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=273</guid>
		<description><![CDATA[I&#8217;ve watched two presentations lately that I enjoyed, so I thought I&#8217;d link to them here. The first one is by Cal Henderson at DjangoCon 2008. Cal is an engineering manager at Flickr, which not surprisingly is written in PHP, &#8230; <a href="http://devdoodles.wordpress.com/2009/04/09/django-shortcomings-and-facebook-architecture/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=273&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve watched two presentations lately that I enjoyed, so I thought I&#8217;d link to them here.</p>
<p>The first one is by <a href="http://www.iamcal.com/">Cal Henderson</a> at DjangoCon 2008.  Cal is an engineering manager at Flickr, which not surprisingly is written in PHP, and he delivered a keynote address on <a href="http://www.youtube.com/watch?v=i6Fr65PFqfk">why he hates Django</a>.  </p>
<p>Although made tongue-in-cheek, it contains a bunch of very valid points about Django.  One of the main ones being Django&#8217;s monolithic database approach.  This is probably also my own biggest concern with Django.  I have first-hand experience of making this design mistake for a web site that grew rather big, and it can easily turn into a major and prolonged headache.</p>
<p>The other presentation is by Aditya Agarwal, an engineering director at Facebook, at QCon SF 2008.  Aditya talks about the <a href="http://www.infoq.com/presentations/Facebook-Software-Stack">Facebook software stack</a>, which somewhat crudely described is a normal LAMP stack, albeit heavily tuned, backed by memcached and a number of backend services.  Facebook is obviously a very extreme environment but many of the design choices and observations in this presentation are valid for smaller sites too.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/273/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/273/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/273/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=273&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/04/09/django-shortcomings-and-facebook-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Installing Postfix and Dovecot on Ubuntu 8.10</title>
		<link>http://devdoodles.wordpress.com/2009/03/28/installing-postfix-and-dovecot-on-ubuntu-810/</link>
		<comments>http://devdoodles.wordpress.com/2009/03/28/installing-postfix-and-dovecot-on-ubuntu-810/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 18:54:43 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[System administration]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[imap]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=249</guid>
		<description><![CDATA[Continuing on the path of getting my VPS up and running, the time has come to install the actual mail services. For this I&#8217;ll go with the standard Ubuntu choices of Postfix as MTA and basic MDA, and Dovecot as &#8230; <a href="http://devdoodles.wordpress.com/2009/03/28/installing-postfix-and-dovecot-on-ubuntu-810/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=249&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Continuing on the path of getting my VPS up and running, the time has come to install the actual mail services.  For this I&#8217;ll go with the standard Ubuntu choices of Postfix as <a href="http://en.wikipedia.org/wiki/Mail_transfer_agent">MTA</a> and basic <a href="http://en.wikipedia.org/wiki/Mail_delivery_agent">MDA</a>, and Dovecot as IMAP server.</p>
<p><strong>Step 1 &#8212; install Postfix</strong><br />
Postfix is easily installed from the main Ubuntu repository by:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install postfix
</pre>
<p>This launches a dialog where you need to choose what kind of mail server you intend to operate, and which domain your server will maintain the mail for.  I chose <em>Internet Site</em> and entered my domain name (e.g. <em>example.com</em>).  The package installer automatically sets a number of default settings, which you can override by launching another interactive dialog:</p>
<pre style="background:#f5f5f5;">
sudo dpkg-reconfigure postfix
</pre>
<p>However, dialogs are pretty annoying so I&#8217;ll edit the settings manually instead through the convenient postconf utility, and then tell Postfix to reload its config:</p>
<pre style="background:#f5f5f5;">
sudo postconf -e 'smtpd_banner = $myhostname ESMTP $mail_name'
sudo postconf -e 'myhostname = mail.example.com'
sudo postconf -e 'mydestination = example.com, mail.example.com, hostname.example.com, localhost.example.com, localhost'
sudo postconf -e 'home_mailbox = Maildir/'
sudo postconf -e 'mynetworks ='
sudo postconf -e 'mynetworks_style = host'
sudo /etc/init.d/postfix reload
</pre>
<p>You obviously need to replace all occurrences of <em>example.com</em> with your actual domain name.  These settings control which domains this server is the final destination for, which networks to relay mail for (only this host), and what mailbox format to use.  I like <a href="http://en.wikipedia.org/wiki/Maildir">Maildir</a> since it stores each mail in a separate file, which is both robust and convenient.  See the <a href="http://www.postfix.org/BASIC_CONFIGURATION_README.html">official Postfix documentation</a> for more configuration options.</p>
<p>The /etc/aliases file controls which email aliases Postfix should use when delivering mail locally on the machine.  By default, it will contain a mapping for postmaster to root, but we should also add a mapping for root to the user who should read root&#8217;s mail (e.g. johndoe), and make that active for Postfix through the newaliases command:</p>
<pre style="background:#f5f5f5;">
sudo sh -c 'echo "root: johndoe" &gt;&gt; /etc/aliases'
sudo /usr/bin/newaliases
</pre>
<p><strong>Step 2 &#8212; create an SSL certificate</strong><br />
To use IMAP over SSL we need to create an SSL certificate to use with Dovecot.  I&#8217;ll use a self-signed certificate since this is just my personal server with few users.  First we <a href="http://www.openssl.org/docs/HOWTO/keys.txt">generate a private key</a> for the certificate and make it readable only by root, and then we <a href="http://www.openssl.org/docs/HOWTO/certificates.txt">create the certificate</a> itself:</p>
<pre style="background:#f5f5f5;">
sudo openssl genrsa -out /etc/ssl/private/dovecot.key 2048
sudo chmod 400 /etc/ssl/private/dovecot.key
sudo openssl req -new -x509 -key /etc/ssl/private/dovecot.key -out /etc/ssl/certs/dovecot.pem -days 1095
</pre>
<p>Make sure to provide the actual domain name of your mail server, e.g. <em>mail.example.com</em>, when asked about the &#8220;Common Name&#8221;.  Otherwise email clients will complain every time they connect to the server.  Since this is a self-signed certificate not backed by a Certification Authority clients will complain the first time anyway, but if you save the certificate subsequent connects will go through silently.  You can read more about openssl <a href="http://www.openssl.org/docs/apps/openssl.html">here</a>.  </p>
<p><strong>Step 3 &#8212; install Dovecot</strong><br />
Time for Dovecot.  It can act both as an IMAP server and a POP3 server, but I will only use its IMAP capability.  Who uses POP3 nowadays anyway?  Install the package and open the main config file:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install dovecot-imapd
sudo vi /etc/dovecot/dovecot.conf
</pre>
<p>Change the following options to enable IMAP over SSL, tell Dovecot to use the Maildir mailbox format, and point it to the SSL key and certificate:</p>
<pre class="brush: css;">
protocols = imaps
mail_location = maildir:~/Maildir
ssl_cert_file = /etc/ssl/certs/dovecot.pem
ssl_key_file = /etc/ssl/private/dovecot.key
</pre>
<p>That&#8217;s all!  Finally, make sure that port 993 is <a href="/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/">open in the firewall</a> and restart Dovecot with the new config:</p>
<pre style="background:#f5f5f5;">
sudo /etc/init.d/dovecot restart
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/249/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/249/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/249/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=249&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/03/28/installing-postfix-and-dovecot-on-ubuntu-810/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Installing jabberd2 and MySQL on Ubuntu 8.10</title>
		<link>http://devdoodles.wordpress.com/2009/03/19/installing-jabberd2-and-mysql-on-ubuntu-810/</link>
		<comments>http://devdoodles.wordpress.com/2009/03/19/installing-jabberd2-and-mysql-on-ubuntu-810/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 21:39:38 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[System administration]]></category>
		<category><![CDATA[jabber]]></category>
		<category><![CDATA[jabberd2]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=225</guid>
		<description><![CDATA[I mentioned in my last post that I had got a new VPS to host my &#8220;my mail and some other things&#8221; on. One of those other things is a Jabber / XMPP server for instant messaging. There are many &#8230; <a href="http://devdoodles.wordpress.com/2009/03/19/installing-jabberd2-and-mysql-on-ubuntu-810/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=225&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I mentioned in my last post that I had got a new VPS to host my &#8220;my mail and some other things&#8221; on.  One of those other things is a <a href="http://en.wikipedia.org/wiki/Jabber">Jabber / XMPP</a> server for instant messaging.  </p>
<p>There are many <a href="http://xmpp.org/software/servers.shtml">XMPP servers</a> out there, and at least three of them are available in Ubuntu&#8217;s software repository: <a href="http://jabberd.org/">jabberd14</a>, <a href="http://jabberd2.xiaoka.com/">jabberd2</a>, and <a href="http://www.process-one.net/en/ejabberd/">ejabberd</a>.  There is also the popular <a href="http://www.igniterealtime.org/projects/openfire/index.jsp">Openfire</a> server, which isn&#8217;t available in the Ubuntu repository but a breeze to install nevertheless through its web-based configuration UI.</p>
<p>My VPS does not come with a whole lot of memory, so I needed a Jabber server with a small memory footprint.  Although you can trim the Java-based Openfire down to fairly low levels of memory usage, it&#8217;s at a disadvantage compared to the C/C++ based jabberd14 and jabberd2.  The same goes for the Erlang-based ejabberd, so it came down to jabber14 or jabberd2.  Considering that jabberd14 seems pretty dead with no updates since 2007, I chose jabberd2.  This is how I installed it:</p>
<p><strong>Step 1 &#8212; add universe to sources.list</strong><br />
The universe repository component needs to be enabled in /etc/apt/sources.list, see step 4 in my <a href="/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/">last post</a> for how to do this.</p>
<p><strong>Step 2 &#8212; install MySQL</strong><br />
jabberd2 can be used with several different storage and authentication backends.  I prefer the default Ubuntu choices of MySQL for both storage and authentication, as I use MySQL for different things too and I like simplicity.  If you don&#8217;t have it installed already, get it by:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install mysql-server
</pre>
<p>Still hunting for a small memory footprint, I also switched the default MySQL config to the stock config for systems with little memory:</p>
<pre style="background:#f5f5f5;">
sudo cp /etc/mysql/my.cnf /etc/mysql/my.cnf.backup
sudo cp /usr/share/doc/mysql-server-5.0/examples/my-small.cnf /etc/mysql/my.cnf
sudo /etc/init.d/mysql restart
</pre>
<p>Somewhat disappointingly, MySQL still hogs more than 100 MB of precious memory, which is a bit funny since the config claims it&#8217;s meant to be used for systems with less than 64 MB of memory. <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />   However, if you don&#8217;t plan to use <a href="http://en.wikipedia.org/wiki/InnoDB">InnoDB</a> tables, the magic-wand solution is to add the <strong>skip-innodb</strong> directive to the [mysqld] section of /etc/mysql/my.cnf.  This alone brought the memory usage down to just <strong>15 MB</strong> after startup for me.</p>
<p><strong>Step 3 &#8212; install jabberd2</strong><br />
Get jabberd2 from universe by:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install jabberd2
</pre>
<p>For some reason it seems to start up by default even though it&#8217;s not properly set up yet, so let&#8217;s shut it down while we&#8217;re configuring it:</p>
<pre style="background:#f5f5f5;">
sudo /etc/init.d/jabberd2 stop
</pre>
<p>Then create the necessary database and tables in MySQL:</p>
<pre style="background:#f5f5f5;">
gzip -d /usr/share/doc/jabberd2/db-setup.mysql.gz
mysql -u root -p
mysql&gt; \. /usr/share/doc/jabberd2/db-setup.mysql
mysql&gt; GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'secret';
mysql&gt; quit
</pre>
<p>Replace &#8216;secret&#8217; in the grant statement above with the password you want to use for the jabberd2 user.  You&#8217;ll need this password in the steps below. </p>
<p><strong>Step 4 &#8212; configure jabberd2</strong><br />
Essentially, configuring jabberd2 for MySQL boils down to three basic steps, decently covered in the official installation guide:</p>
<ul>
<li><a href="http://www.jabberdoc.org/section04#4_1">Set host name in c2s.xml and sm.xml</a></li>
<li><a href="http://www.jabberdoc.org/section04_4#4_4_2">Configure storage in sm.xml</a></li>
<li><a href="http://www.jabberdoc.org/section04_4#4_4_3">Configure authentication in c2s.xml</a></li>
</ul>
<p>Additionally, it makes sense to also <a href="http://www.jabberdoc.org/section05#5_3">change the password</a> of the jabberd2 backbone router component in router-users.xml and each of the component configuration files.</p>
<p>Although there are <a href="http://www.jabberdoc.org/AdminGuide">other configuration</a> options available too, the above steps should be enough for a basic installation.  Start jabberd2 up again through:</p>
<pre style="background:#f5f5f5;">
sudo /etc/init.d/jabberd2 restart
</pre>
<p>At this point, you should be able to connect to the server and register with an IM client of your choice, e.g. <a href="http://www.miranda-im.org/">Miranda</a>.  Don&#8217;t forget to <a href="/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/">open up</a> the Jabber ports in your firewall: port 5222 for normal connections, 5223 for <a href="http://www.jabberdoc.org/section05#5_2">SSL connections</a>, and 5269 for server-to-server connections.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/225/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/225/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/225/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=225&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/03/19/installing-jabberd2-and-mysql-on-ubuntu-810/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Basic sshd and iptables security in Ubuntu</title>
		<link>http://devdoodles.wordpress.com/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/</link>
		<comments>http://devdoodles.wordpress.com/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/#comments</comments>
		<pubDate>Sun, 15 Mar 2009 17:16:21 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[System administration]]></category>
		<category><![CDATA[denyhosts]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[sshd]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=171</guid>
		<description><![CDATA[I recently got a new VPS for hosting my mail and some other things. The server was installed with a minimal Ubuntu 8.10 distribution, which basically meant that nothing except init, syslogd, and sshd was running after boot. Before doing &#8230; <a href="http://devdoodles.wordpress.com/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=171&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recently got a new <a href="http://en.wikipedia.org/wiki/Virtual_private_server">VPS</a> for hosting my mail and some other things. The server was installed with a minimal Ubuntu 8.10 distribution, which basically meant that nothing except init, syslogd, and sshd was running after boot.  Before doing anything else with it, here&#8217;s what I did to lock it down a bit security-wise:</p>
<p><strong>Step 1 &#8212; Add user account</strong><br />
It&#8217;s good practice to not do stuff logged in as the root user, so the first step is to add a user account from which we can <a href="https://help.ubuntu.com/community/RootSudo">sudo</a>.  Log in as root only this time and add the user (e.g. johndoe) and sudo access as follows:</p>
<pre style="background:#f5f5f5;">
useradd -m johndoe -s /bin/bash
passwd johndoe
visudo
</pre>
<p>Running visudo will edit the /etc/sudoers file with the default editor of your environment.  Add this line to allow johndoe full sudo permissions:</p>
<pre class="brush: css;">
johndoe ALL=(ALL) ALL
</pre>
<p><strong>Step 2 &#8212; Install iptables</strong><br />
Still as root, we&#8217;ll set up the iptables firewall to make sure only specifically allowed inbound network traffic is allowed to the server:</p>
<pre style="background:#f5f5f5;">
apt-get install iptables
</pre>
<p>Configuring iptables can seem pretty complex at first, but <a href="https://help.ubuntu.com/community/IptablesHowTo">here&#8217;s</a> a decent tutorial.  Firewall rules can be added directly from the command line:</p>
<pre style="background:#f5f5f5;">
iptables -F
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p icmp --icmp-type any -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 993 -j ACCEPT
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited
iptables -A FORWARD -j REJECT --reject-with icmp-host-prohibited
</pre>
<p>Essentially, the above rules allow all outbound traffic, block all inbound traffic by default, and specifically allow ssh, smtp, http, and imaps traffic, which is what I need to begin with.  To make sure the rules are persistent after e.g. a server reboot we add them as a script hook to the network interface:</p>
<pre style="background:#f5f5f5;">
iptables-save &gt; /etc/network/iptables
printf '#!/bin/sh\niptables-restore &lt; /etc/network/iptables\n' &gt; /etc/network/if-pre-up.d/iptables
chmod 754 /etc/network/if-pre-up.d/iptables
</pre>
<p><strong>Step 3 &#8212; Update sshd config</strong><br />
Now that iptables and a user account with sudo rights are set up, it&#8217;s time to leave the root shell, log in as the new user, and then edit the sshd config to lock down future ssh access a bit:</p>
<pre style="background:#f5f5f5;">
sudo vi /etc/ssh/sshd_config
</pre>
<p>Add/change the following settings:</p>
<pre class="brush: css;">
PermitRootLogin no
AllowUsers johndoe
</pre>
<p>This disallows root from logging in through ssh (console login is still allowed though) and restricts ssh access to only be allowed for the johndoe user.  Make the changes active by reloading the config:</p>
<pre style="background:#f5f5f5;">
sudo /etc/init.d/ssh reload
</pre>
<p><strong>Step 4 &#8212; Update sources.list</strong><br />
This being a very minimal install, the stock /etc/apt/sources.list file only included the main <a href="http://www.ubuntu.com/community/ubuntustory/components">repository component</a>.  To install the denyhosts package (see next step) the universe component is needed, so we need to add it to <a href="https://help.ubuntu.com/community/Repositories/CommandLine">sources.list</a>:</p>
<pre class="brush: css;">
deb http://archive.ubuntu.com/ubuntu intrepid main restricted
deb-src http://archive.ubuntu.com/ubuntu intrepid main restricted
deb http://archive.ubuntu.com/ubuntu/ intrepid-updates main restricted
deb-src http://archive.ubuntu.com/ubuntu/ intrepid-updates main restricted
deb http://archive.ubuntu.com/ubuntu/ intrepid universe
deb-src http://archive.ubuntu.com/ubuntu/ intrepid universe
deb http://archive.ubuntu.com/ubuntu/ intrepid-updates universe
deb-src http://archive.ubuntu.com/ubuntu/ intrepid-updates universe
</pre>
<p>Once done, update the package lists from the newly added sources and upgrade all currently installed packages to the latest versions:</p>
<pre style="background:#f5f5f5;">
sudo apt-get update
sudo apt-get upgrade
</pre>
<p><strong>Step 5 &#8212; Install DenyHosts</strong><br />
Even with iptables and the sshd configuration changes we made, we still allow some users to log in through ssh, which makes us vulnerable to remote brute-force attempts to gain access through these accounts.  One good way to do away with this threat is to only allow public-key authentication, or restrict access to only a list of specified IPs through iptables or /etc/hosts.deny, but if this is not practical for whatever reason the <a href="http://denyhosts.sourceforge.net/">DenyHosts</a> package comes to the rescue.</p>
<p>DenyHosts monitors the sshd authentication log to detect evil login attempts and adds suspicious IPs automatically to the /etc/hosts.deny file.  It&#8217;s available in Ubuntu from the universe repository component (see previous step), and is easily installed like this:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install denyhosts
</pre>
<p>This will automatically start a python daemon in the background, which also is persistent on reboot through a symlink in /etc/rc3.d/.  The default settings are pretty decent, but should you want to review or change them you can do so in /etc/denyhosts.conf.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/171/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/171/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/171/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=171&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/03/15/basic-sshd-and-iptables-security-in-ubuntu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Multi-language content spots with django-chunks and friends</title>
		<link>http://devdoodles.wordpress.com/2009/02/28/multi-language-content-spots-with-django-chunks-and-friends/</link>
		<comments>http://devdoodles.wordpress.com/2009/02/28/multi-language-content-spots-with-django-chunks-and-friends/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 19:34:37 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-better-chunks]]></category>
		<category><![CDATA[django-chunks]]></category>
		<category><![CDATA[multi-language]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=147</guid>
		<description><![CDATA[Update March 3: django-better-chunks has now been patched, so there is no need to use my project fork anymore. In my previous post I wrote about how to use flatpages in Django for serving static content pages. The flatpages module &#8230; <a href="http://devdoodles.wordpress.com/2009/02/28/multi-language-content-spots-with-django-chunks-and-friends/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=147&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Update March 3: django-better-chunks has now been patched, so there is no need to use my project fork anymore.</strong></p>
<p>In my <a href="http://devdoodles.wordpress.com/2009/02/26/static-content-with-django-multilingual-flatpages/">previous post</a> I wrote about how to use flatpages in Django for serving static content pages.  The flatpages module only deals with full pages however, so if you would like to include static content on a more fine-grained level, or have multiple content spots per template, you need to look elsewhere.  </p>
<p>This is where <a href="http://code.google.com/p/django-chunks/">django-chunks</a>, or one of the many projects forked from it (e.g. <a href="http://bitbucket.org/hakanw/django-better-chunks/wiki/Home">django-better-chunks</a> and <a href="http://github.com/zerok/django-flatblocks/tree/master">django-flatblocks</a>), comes to the rescue.  django-chunks allows you to for example create a content spot called &#8220;home_page_right&#8221; in admin, and then include it in your template like this:</p>
<pre class="brush: xml;">
&lt;div id=&quot;right&quot;&gt;
    {% chunk &quot;home_page_right&quot; %}
&lt;/div&gt;
</pre>
<p>The chunk tag also accepts an optional second parameter that specifies a cache timeout in seconds, e.g. 3600 for an hour&#8217;s caching.</p>
<p>So far so good, but a theme of some of my previous posts has been multi-language support, and unfortunately django-chunks is lacking this.  Luckily, <a href="http://bitbucket.org/hakanw/django-better-chunks/wiki/Home">django-better-chunks</a> was created to remedy just that.  Unluckily though, while adding language support they also <em>broke the cache support</em>.  </p>
<p>That being said, django-better-chunks is the only module I&#8217;ve found that does support multiple languages, so I felt it would be the best project for me to build on.  To fix the broken caching I&#8217;ve created <em>yet another</em> fork of this project: <a href="http://bitbucket.org/devdoodles/django-better-chunks-devdoodles/">django-better-chunks-devdoodles</a>.  Hopefully the patch can be merged into the original project at some point.  Here&#8217;s how to get django-better-chunks (or my fork) up and running:</p>
<p><strong>Step 1 &#8212; download and install</strong><br />
Download <a href="http://bitbucket.org/hakanw/django-better-chunks/wiki/Home">django-better-chunks</a> or, perhaps preferably until the caching is fixed, <a href="http://bitbucket.org/devdoodles/django-better-chunks-devdoodles/">django-better-chunks-devdoodles</a> and install in your Python/Django path.</p>
<p><strong>Step 2 &#8212; edit settings.py</strong><br />
As usual, you need to add LocaleMiddleware to your middleware classes if you want Django to <a href="http://docs.djangoproject.com/en/dev/topics/i18n/#id2">automatically choose</a> which language to use:</p>
<pre class="brush: python;">
MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.locale.LocaleMiddleware',
)
</pre>
<p>Then add contrib.sites (there by default), admin, and chunks to your installed applications:</p>
<pre class="brush: python;">
INSTALLED_APPS = (
    ...
    'django.contrib.sites',
    'django.contrib.admin',
    'chunks',
)
</pre>
<p>contrib.sites is needed since django-better-chunks connect the content chunks to a site through a ForeignKey relationship.  Admin is needed to add and edit content spots.</p>
<p>Optionally, if you want to use another caching backend for chunks than the default local-memory cache (locmem://), then you add it here too.  To use a local memcached cache on the default port instead, add:</p>
<pre class="brush: python;">
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
</pre>
<p><strong>Step 3 &#8212; activate admin in urls.py</strong><br />
Uncomment the three lines needed to activate admin in urls.py.</p>
<p><strong>Step 4 &#8212; sync database</strong><br />
Create database tables:</p>
<pre style="background:#f5f5f5;font-size:1.2em;">
python manage.py syncdb
</pre>
<p><strong>Step 5 &#8212; create spots in admin</strong><br />
At this point all that remains is to create the content spots in the Chunks section in admin (/admin/chunks/chunk/) and start using them from your templates.  Make sure to load the chunk tag library first using:</p>
<pre class="brush: xml;">
{% load chunks %}
</pre>
<p>Finally, beware that the help text in the admin UI gives as language examples &#8216;sv-se&#8217; and &#8216;de-de&#8217;, which often won&#8217;t work well with Django&#8217;s <a href="http://docs.djangoproject.com/en/dev/topics/i18n/#id2">automatic language detection</a>.  This is because Django by default almost always resolves to <em>base languages</em> (e.g. &#8216;en&#8217;) and not sublanguages (e.g. &#8216;en-us&#8217;), since most of the languages defined in the LANGUAGES setting in <a href="http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py">global_settings.py</a> are defined only as base languages.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/147/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=147&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/02/28/multi-language-content-spots-with-django-chunks-and-friends/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Static content with django-multilingual flatpages</title>
		<link>http://devdoodles.wordpress.com/2009/02/26/static-content-with-django-multilingual-flatpages/</link>
		<comments>http://devdoodles.wordpress.com/2009/02/26/static-content-with-django-multilingual-flatpages/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 00:03:52 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-multilingual]]></category>
		<category><![CDATA[flatpages]]></category>
		<category><![CDATA[multi-language]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=132</guid>
		<description><![CDATA[While working on a multilingual Django project I encountered the need to have pseudo-static pages, e.g. an about page or FAQ page, translated into multiple languages. In my earlier post I wrote about how to use the i18n tag library &#8230; <a href="http://devdoodles.wordpress.com/2009/02/26/static-content-with-django-multilingual-flatpages/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=132&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>While working on a multilingual Django project I encountered the need to have pseudo-static pages, e.g. an about page or FAQ page, translated into multiple languages.  In my <a href="/2009/02/14/multi-language-support-in-a-django-project/">earlier post</a> I wrote about how to use the i18n tag library in templates to handle translations, and although this approach would work for static pages too it would not be a perfect fit.</p>
<p>Django comes bundled with the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/">flatpages</a> application, which rather cleverly hooks into the 404 errors generated by Django when it cannot find a page and maps the requested URL to a database list.  If there&#8217;s an entry for the requested URL, it shows the page stored in the database for that URL instead of the 404 page.</p>
<p>The bundled flatpages application has no inherent multi-language support, and I was pretty close to adapting it for my needs before Google came to the rescue.  Obviously, this had already been done by someone, and it&#8217;s distributed as a part of the <a href="http://code.google.com/p/django-multilingual/">django-multilingual</a> module, which is a generic module for having translated fields in Django models.  Here&#8217;s what I did to get it up and running, based on the steps described on the <a href="http://code.google.com/p/django-multilingual/wiki/Usage">project wiki</a>.</p>
<p><strong>Step 1 &#8212; install django-multilingual</strong><br />
Check out the Subversion trunk for the project as described in the wiki, and make the checked out module available for Python somehow.  I just copied the multilingual sub-folder to my project folder as if it were my own application.</p>
<p><strong>Step 2 &#8212; edit settings.py</strong><br />
Add the list of languages you want to support to settings.py, and mark English as the default language (through its tuple index).  The LANGUAGES setting is actually already defined in <a href="http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py">global_settings.py</a>, but I don&#8217;t want to support all those languages so I override it.</p>
<pre class="brush: python;">
LANGUAGES = (
    ('en', 'English'),
    ('sv', 'Swedish'),
)
DEFAULT_LANGUAGE = 1
</pre>
<p>Add the multilingual context processor to TEMPLATE_CONTEXT_PROCESSORS.  This setting is not included by default in your settings.py file, but the first four core processors below are set as default in the global settings (for reference, see <a href="http://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors">here</a> and <a href="http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py">here</a>):</p>
<pre class="brush: python;">
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'multilingual.context_processors.multilingual',
)
</pre>
<p>Add the middleware classes in the order listed below to support language detection and for the actual mapping of 404s to flatpages to be triggered.  Curiously, the FlatpageFallbackMiddleware is not mentioned in the <a href="http://code.google.com/p/django-multilingual/wiki/Usage">official installation instructions</a>, but you can deduce that it&#8217;s needed by its mentioning in the <a href="http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/">original flatpage documentation</a> and, of course, the fact that nothing happens without it.</p>
<pre class="brush: python;">
MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.locale.LocaleMiddleware',
    'multilingual.middleware.DefaultLanguageMiddleware',
    'multilingual.flatpages.middleware.FlatpageFallbackMiddleware',
)
</pre>
<p>Add admin and the multilingual apps to INSTALLED_APPS:</p>
<pre class="brush: python;">
INSTALLED_APPS = (
    ...
    'django.contrib.admin',
    'multilingual',
    'multilingual.flatpages',
)
</pre>
<p><strong>Step 3 &#8212; activate admin in urls.py</strong><br />
Uncomment the three lines needed to activate admin in urls.py.</p>
<p><strong>Step 4 &#8212; sync database</strong><br />
Create all database tables needed for admin and flatpages:</p>
<pre style="background:#f5f5f5;font-size:1.2em;">
python manage.py syncdb
</pre>
<p><strong>Step 5 &#8212; create template</strong><br />
Create a ./flatpages/ sub-folder in your template-root directory, and create a default.html template in it.  This is the default template used for displaying the flatpages, but it can be overridden in admin (see the next step).  Its context is populated by a flatpage variable with two fields: title and content.  An example template is available <a href="http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/#flatpage-templates">here</a>.</p>
<p><strong>Step 6 &#8212; create pages in admin</strong><br />
Go to the flatpages section in your admin application (/admin/flatpages/multilingualflatpage/) and create all the pages and translations you want to serve using the flatpages application.</p>
<p><strong>Step 7 &#8212; done!</strong><br />
We&#8217;re done!  As before, you can test your work by modifying LANGUAGE_CODE in settings.py or changing the preferred-languages setting in your web browser.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/132/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=132&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/02/26/static-content-with-django-multilingual-flatpages/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
		<item>
		<title>Ubuntu, cmemcache, and python-memcached (once again)</title>
		<link>http://devdoodles.wordpress.com/2009/02/19/ubuntu-cmemcache-and-python-memcached-once-again/</link>
		<comments>http://devdoodles.wordpress.com/2009/02/19/ubuntu-cmemcache-and-python-memcached-once-again/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 22:08:19 +0000</pubDate>
		<dc:creator>devdoodles</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[System administration]]></category>
		<category><![CDATA[cmemcache]]></category>
		<category><![CDATA[python-memcached]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://devdoodles.wordpress.com/?p=119</guid>
		<description><![CDATA[I wrote earlier about my not quite satisfactory attempt to install cmemcache on Ubuntu. After stumbling upon this exhaustive guide on how to set up a full-blown Django environment under Ubuntu I thought I&#8217;d try the apt-get route for libmemcache &#8230; <a href="http://devdoodles.wordpress.com/2009/02/19/ubuntu-cmemcache-and-python-memcached-once-again/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=119&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I wrote earlier about my <a href="/2009/02/12/installing-cmemcache-on-ubuntu-810-almost/">not quite satisfactory</a> attempt to install cmemcache on Ubuntu.  After stumbling upon <a href="http://lethain.com/entry/2009/feb/13/the-django-and-ubuntu-intrepid-almanac/">this exhaustive guide</a> on how to set up a full-blown Django environment under Ubuntu I thought I&#8217;d try the apt-get route for libmemcache too.  All you need to do to get libmemcache and the necessary header files installed is:</p>
<pre style="background:#f5f5f5;">
sudo apt-get install libmemcache-dev libmemcache0
</pre>
<p>After that, the steps for installing cmemcache itself are the same as <a href="/2009/02/12/installing-cmemcache-on-ubuntu-810-almost/">before</a>.  The good news is that libmemcache and cmemcache both get installed without fuss using this approach, without any need for manual patching.  The bad news is that the test.py suite <em>still fails</em> with same error message as before.  </p>
<p>I cannot say that I fully understand the significance of this test failing.  It might be harmless, but I sure like my tests to pass successfully so cmemcache will remain on my naughty list for now.  Left with only python-memcached as a choice, I installed it instead, which was a breeze compared to cmemcache:</p>
<pre style="background:#f5f5f5;">
wget ftp://ftp.tummy.com/pub/python-memcached/python-memcached-1.43.tar.gz
tar xvfz python-memcached-1.43.tar.gz
cd python-memcached-1.43/
sudo apt-get install python-setuptools
sudo python setup.py install
</pre>
<p>python-setuptools is used by the setup.py script, so it needs to be installed before running the setup.  Once done, you can test python-memcached almost identically to cmemcache earlier (memcached needs to run in the background on localhost for this to work):</p>
<pre class="brush: python;">
&gt;&gt;&gt; import memcache
&gt;&gt;&gt; c = memcache.Client(['127.0.0.1:11211'])
&gt;&gt;&gt; c.set('testkey', 'testval')
True
&gt;&gt;&gt; c.get('testkey')
'testval'
&gt;&gt;&gt;
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/devdoodles.wordpress.com/119/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/devdoodles.wordpress.com/119/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/devdoodles.wordpress.com/119/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=devdoodles.wordpress.com&amp;blog=6514960&amp;post=119&amp;subd=devdoodles&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://devdoodles.wordpress.com/2009/02/19/ubuntu-cmemcache-and-python-memcached-once-again/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">devdoodles</media:title>
		</media:content>
	</item>
	</channel>
</rss>
