<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0">

    <channel>

        <title>Blog</title>
        <link>http://tomster.org/blog</link>
        <description>"I'm a geek -- with a life!" he insisted stubbornly...</description>

        <generator>basesyndication</generator>
        <!-- TODO
        <lastBuildDate>Mon, 30 Sep 2002 11:00:00 GMT</lastBuildDate>
        <copyright>Copyright 1997-2002 Dave Winer</copyright>
        <docs>http://backend.userland.com/rss</docs>
        <category domain="Syndic8">1765</category>
        <managingEditor>dave@userland.com</managingEditor>
        <webMaster>dave@userland.com</webMaster>
        -->

        <!-- TODO: Should there be an individual image associatable with each
        Weblog object?  I think so... -->
        <image>
            <title>Blog</title>
            <url>http://tomster.org/logo.png</url>
            <link>http://tomster.org/blog</link>
        </image>

        
            <item>
                <title>lxml on Mac OS X</title>
                <guid>http://tomster.org/blog/archive/2008/09/25/lxml-on-mac-os-x</guid>
                <link>http://tomster.org/blog/archive/2008/09/25/lxml-on-mac-os-x</link>
                <description>
&lt;p&gt;For a current project I needed to include (the most excellent Python XML library) &lt;a href="http://codespeak.net/lxml/" title="lxml homepage"&gt;lxml&lt;/a&gt;. Getting the right version to run on Mac OS X has been notoriously difficult, though. Easy-installing it was broken (and currently is, for me, as well) and while I have found multiple how-tos, they all dealt with the problem by installing it manually from sources and patching the configure process etc. pp. That would, of course, defeat the whole purpose of using buildout in the first place.
&lt;/p&gt;
&lt;p&gt;Cheeseshop to the rescue: there is a &lt;a href="http://pypi.python.org/pypi/plone.recipe.lxml/" title="Python Package Index : plone.recipe.lxml 0.2"&gt;recipe for installing lxml&lt;/a&gt; &lt;em&gt;along with the proper versions of libxml and libxslt&lt;/em&gt;, however, its default values didn't work for me. So for the record: the following buildout snippet will get you non-segfaulting lxml on (at least) Mac OS X 10.5.x and Ubuntu linux. YMMV.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;parts =
    [...]
    lxml

eggs =
    [...]
    lxml==2.1.2

[lxml]
recipe=plone.recipe.lxml
egg = 
    lxml==2.1.2

libxml2_url = 
    http://xmlsoft.org/sources/libxml2-2.7.1.tar.gz

libxslt_url =
    http://xmlsoft.org/sources/libxslt-1.1.24.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;p.s. this should be good news for all folks working with Deliverance. Perhaps now I could revisit that...
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>xml</category>
                
                
                    <category>macintosh</category>
                
                
                    <category>ubuntu</category>
                
                
                    <category>linux</category>
                

                <pubDate>Thu, 25 Sep 2008 11:33:20 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Netboot installing Ubuntu on a SunFire X2200</title>
                <guid>http://tomster.org/blog/archive/2008/06/02/netboot-installing-ubuntu-on-a-sunfire-x2200</guid>
                <link>http://tomster.org/blog/archive/2008/06/02/netboot-installing-ubuntu-on-a-sunfire-x2200</link>
                <description>
&lt;p&gt;After receiving my new toy at work &lt;a href="http://twitter.com/tomlazar/statuses/823257451" title="Twitter / Tom Lazar: Ah, my new toy arrived! A S..."&gt;three days ago&lt;/a&gt;, a &lt;a href="http://www.sun.com/servers/x64/x2200/" title="Sun Fire X2200 M2 Server"&gt;SunFire X2200&lt;/a&gt; with 16Gb RAM, today I finally got around to set it up.
&lt;/p&gt;
&lt;p&gt;Now, while my server OS of choice is definitely FreeBSD this particular machine is going to be used as a development machine for a Plone project which will eventually be hosted at a provider who doesn't support FreeBSD but instead Ubuntu. Also, the machine came without an optical drive. So after a few fruitless attempts to boot from an USB stick, I simply stuck to what I already know and chose a TFTP based route using Mac OS X's built-in tftp server.
&lt;/p&gt;
&lt;p&gt;Basically, I just followed &lt;a href="http://tomster.org/blog/installing-freebsd-on-a-soekris-4801-using-mac-os-x-as-host" title="Installing FreeBSD on a Soekris 4801 using Mac OS X as host &amp;amp;mdash; tomster.org"&gt;my previous how-to on how to install FreeBSD on a (headless, keyboardless) soekris machine&lt;/a&gt;. Only, this time, I installed the dhcp server from mac ports, instead of compiling it manually:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo port install dhcp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then I downloaded the &lt;a href="http://www.ubuntu.com/getubuntu/download" title="Download Ubuntu | Ubuntu"&gt;Ubuntu Server ISO image&lt;/a&gt; and mounted it.
&lt;/p&gt;
&lt;p&gt;In my &lt;code&gt;dhcpd.conf&lt;/code&gt; I modified the root-path and filename options thus:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;option root-path &amp;quot;/Volumes/Ubuntu-Server 8./install/netboot/&amp;quot;;
filename &amp;quot;pxelinux.0&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next modified the (existing) &lt;code&gt;/System/Library/LaunchDaemons/tftp.plist&lt;/code&gt; so that it looked like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; 
    &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;InitGroups&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;com.apple.tftpd&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;/usr/libexec/tftpd&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-i&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;/Volumes/Ubuntu-Server 8./install/netboot&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-u&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;root&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-s&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;/Volumes/Ubuntu-Server 8./install/netboot&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-l&amp;lt;/string&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;Sockets&amp;lt;/key&amp;gt;
    &amp;lt;dict&amp;gt;
        &amp;lt;key&amp;gt;Listeners&amp;lt;/key&amp;gt;
        &amp;lt;dict&amp;gt;
            &amp;lt;key&amp;gt;SockServiceName&amp;lt;/key&amp;gt;
            &amp;lt;string&amp;gt;tftp&amp;lt;/string&amp;gt;
            &amp;lt;key&amp;gt;SockType&amp;lt;/key&amp;gt;
            &amp;lt;string&amp;gt;dgram&amp;lt;/string&amp;gt;
        &amp;lt;/dict&amp;gt;
    &amp;lt;/dict&amp;gt;
    &amp;lt;key&amp;gt;inetdCompatibility&amp;lt;/key&amp;gt;
    &amp;lt;dict&amp;gt;
        &amp;lt;key&amp;gt;Wait&amp;lt;/key&amp;gt;
        &amp;lt;true/&amp;gt;
    &amp;lt;/dict&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now all I needed to do was to start both daemons...
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo /opt/local/sbin/dhcpd 
sudo service tftp start
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;...finally fire up the machine and press &lt;code&gt;F12&lt;/code&gt; at the boot prompt and Bob was my proverbial uncle.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>ubuntu</category>
                
                
                    <category>linux</category>
                

                <pubDate>Mon, 02 Jun 2008 18:10:00 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>blueprint css + jquery</title>
                <guid>http://tomster.org/blog/archive/2008/04/26/blueprint-css-jquery</guid>
                <link>http://tomster.org/blog/archive/2008/04/26/blueprint-css-jquery</link>
                <description>
&lt;p&gt;I'm using the &lt;a href="http://code.google.com/p/blueprintcss/" title="blueprintcss - Google Code"&gt;blueprint CSS framework&lt;/a&gt; for a new site that I'm working on and am rather enjoying the process (as far as that is humanly possible, given that it by definition involves working with CSS... &lt;em&gt;cough&lt;/em&gt;).
&lt;/p&gt;
&lt;p&gt;One of the neat features of blueprint is a compressor script that not only renders all the various CSS bits that you want according to the given column numbers and sizes for each project into one neat (and compact) CSS file, but it also lets you define &lt;em&gt;semantic classes and ids&lt;/em&gt;, so you can use something like &lt;code&gt;class=&amp;quot;navigation&amp;quot;&lt;/code&gt; instead of &lt;code&gt;class=&amp;quot;span-6 last&amp;quot;&lt;/code&gt;. And on top of that, the compressor script will also generate a PNG image that conforms to the column size and padding you've selected. This proved to be really helpful in debugging the pages. Simply add the class &lt;code&gt;showgrid&lt;/code&gt; to your outer most container &lt;code&gt;div&lt;/code&gt; and &lt;a href="http://files.bjorkoy.com/blueprint/tests/parts/grid.html" title="Blueprint Grid Tests"&gt;presto&lt;/a&gt;!
&lt;/p&gt;
&lt;p&gt;When demonstrating the layout to the client, though, I wanted a less obtrusive way of switching the grid on and off and I thus came up with little &lt;a href="http://jquery.com/" title="jQuery: The Write Less, Do More, JavaScript Library"&gt;jQuery&lt;/a&gt; script to generate a toggle switch for each page. And since jQuery will be the standard javascript library for Plone from version 3.1 onward, anyway I thought I might as well share the following snippet:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$(document).ready(function() {
    $(&amp;quot;body&amp;quot;).append(&amp;quot;&amp;lt;div id='debug'&amp;gt;turn grid: &amp;lt;a href='' id='togglegrid'&amp;gt;&amp;quot; 
    + gridstate() + &amp;quot;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;);
    $(&amp;quot;#debug&amp;quot;).css(&amp;quot;position&amp;quot;, &amp;quot;absolute&amp;quot;);
    $(&amp;quot;#debug&amp;quot;).css(&amp;quot;bottom&amp;quot;, &amp;quot;0&amp;quot;);
    $(&amp;quot;#togglegrid&amp;quot;).click(toggle_grid);
});

function toggle_grid () {
    $(&amp;quot;.container&amp;quot;).toggleClass(&amp;quot;showgrid&amp;quot;);
    $(&amp;quot;#togglegrid&amp;quot;).text(gridstate());
    return false;
}

function gridstate () {
    if ($(&amp;quot;.container&amp;quot;).hasClass(&amp;quot;showgrid&amp;quot;)) {
        return 'off';
    } else {
        return 'on';
    };
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;P.S. I'm not exactly a fan of the Javascript language but I do appreciate jQuery a lot and for the sanity that it partially restores when working with Javascript. The snippet above is a good example of that in my opinion. Javascript can't get any more &amp;quot;pythonic&amp;quot; than that IMHO ;-) (But please prove me wrong!)
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>jquery</category>
                
                
                    <category>blueprintcss</category>
                
                
                    <category>css</category>
                

                <pubDate>Sat, 26 Apr 2008 17:01:13 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Connecting Plone to Mac OS X Server with LDAP</title>
                <guid>http://tomster.org/blog/archive/2008/04/18/connecting-plone-to-mac-os-x-server-with-ldap</guid>
                <link>http://tomster.org/blog/archive/2008/04/18/connecting-plone-to-mac-os-x-server-with-ldap</link>
                <description>
&lt;p&gt;The idea is, of course, that all (or just some) of your OS X Server users can authenticate against a Plone instance using the same credentials that they use to access all the other services (usually filesharing).
&lt;/p&gt;

&lt;h1&gt;Requirements&lt;/h1&gt;
&lt;p&gt;I'm assuming a buildout based setup, so you will need to add the following bits to your &lt;code&gt;buildout.cfg&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[buildout]
parts =
    ...
    productdistros
    openldap
...
[openldap]
recipe = zc.recipe.cmmi
url = http://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-2.3.27.tgz 
extra_options= --disable-slapd --disable-backends
...
[productdistros]
recipe = plone.recipe.distros
urls =
    ...
    http://plone.org/products/ploneldap/releases/1.0/PloneLDAP-bundle-1.0.tar.gz

nested-packages =
    ...
    PloneLDAP-bundle-1.0.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will also need &lt;a href="http://python-ldap.sourceforge.net/" title="python-ldap: LDAP client API for Python"&gt;python-ldap&lt;/a&gt;, for which even &lt;a href="http://svn.kmrc.de/download/distribution" title="Index of /download/distribution"&gt;some eggs exist&lt;/a&gt;, however, I found that they didn't work on my test server (Ubuntu, 64bit) as they seem to have some &lt;code&gt;.so&lt;/code&gt; files that assume a 32bit architecture (just a wild guess on my part), so instead I just installed it via &lt;code&gt;apt-get&lt;/code&gt; (Ubuntu really has good support for Python2.4 based packages btw, no wonder it's so popular among Zopistas and Plonistas!)
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install python2.4-ldap
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can run &lt;code&gt;./bin/buildout&lt;/code&gt; and restart your instance.
&lt;/p&gt;

&lt;h1&gt;Adding the plug-in&lt;/h1&gt;
&lt;p&gt;In the ZMI, navigate to your Plone instance's &lt;code&gt;acl_users&lt;/code&gt; and add a &lt;code&gt;Plone LDAP Plugin&lt;/code&gt; from the upper right hand select box. Obviously, filling out the following form with exactly the right values is the trickiest bit of the entire operation, so I've tried to make the example values as self-evident as possible. They all assume that the FQDN of your Mac OS X server is &lt;code&gt;my.ldap.server.tld&lt;/code&gt;, so it should be a no-brainer to substitute all values according to your own setup.
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Set all three mappings (for Login Name Attribute, User ID Attribute and RDN Attribute) to &lt;code&gt;UID (uid)&lt;/code&gt;.
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;Users Base DN&lt;/code&gt; to &lt;code&gt;cn=users,dc=my,dc=ldap,dc=server,dc=tld&lt;/code&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;Groups Base DN&lt;/code&gt; to &lt;code&gt;cn=groups,dc=my,dc=ldap,dc=server,dc=tld&lt;/code&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;Manager DN&lt;/code&gt; to &lt;code&gt;uid=diradmin,cn=users,dc=my,dc=ldap,dc=server,dc=tld&lt;/code&gt;. You will obviously need to substitute &lt;code&gt;diradmin&lt;/code&gt; for the id you chose when setting up the OpenDirectory server. Hint: it's the same id you use to log into the Workgroup Manager ;-)
 &lt;/li&gt;

 &lt;li&gt;
     I have switched off encryption and SSL in my tests, so no guarantees that it will work &lt;em&gt;with&lt;/em&gt; encryption (my Plone instance is running inside a VMware Fusion instance on the OS X Server itself, so I didn't see any need to bother with encryption, for a change)
 &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Configuring the plug-in&lt;/h1&gt;
&lt;p&gt;Now you need to click on the newly created plugin at &lt;code&gt;/plone/acl_users/ldap&lt;/code&gt; and activate &lt;em&gt;all&lt;/em&gt; functionalities.
&lt;/p&gt;
&lt;p&gt;Still at &lt;code&gt;/plone/acl_users/ldap&lt;/code&gt; click on &lt;code&gt;Properties&lt;/code&gt; and &lt;code&gt;User_Management&lt;/code&gt; and move the ldap plug-in to the top in both forms.
&lt;/p&gt;
&lt;p&gt;Finally, navigate to &lt;code&gt;/plone/acl_users/ldap/acl_users&lt;/code&gt; and change the value for &lt;code&gt;User object classes&lt;/code&gt; to &lt;code&gt;posixAccount&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;You now should be able to log into the Plone site using the credentials of a OS X Server user.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>ldap</category>
                
                
                    <category>macintosh</category>
                
                
                    <category>plone</category>
                
                
                    <category>ubuntu</category>
                
                
                    <category>hints</category>
                

                <pubDate>Fri, 18 Apr 2008 19:38:43 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>nginx + mod_wsgi + python2.4</title>
                <guid>http://tomster.org/blog/archive/2008/04/16/nginx-mod-wsgi-python2.4</guid>
                <link>http://tomster.org/blog/archive/2008/04/16/nginx-mod-wsgi-python2.4</link>
                <description>
&lt;p&gt;Currently I'm having lots of fun experimenting with WSGI, &lt;a href="http://blog.repoze.org/" title="Repoze Notes : /"&gt;repoze&lt;/a&gt; and Deliverance. But while it's nice to know that it works in a development setup (i.e. deployed with paster) I needed to be sure it would work well in a production environment. And while there are already instructions floating around on how to deploy it with Apache and mod_wsgi, I wanted to know whether I could deploy WSGI-based sites using my trusted workhorse &lt;a href="http://wiki.codemongers.com/Main" title="Main - Nginx Wiki"&gt;nginx&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Since nginx is much more monolithic than Apache (which is one reason why it can be so noticably more efficient than Apache in certain situations) you can't just drop in a plugin or module. Instead, you must compile nginx from sources and add the module &lt;em&gt;at compile time&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;The projects I'm working on will be deployed on Ubuntu and FreeBSD, but of course I will want to be able to test the same setup on my OS X development machine. So I've begun my tests with Ubuntu and OS X. Since nginx is available in all three systems' packaging system, my strategy is to install nginx via its respective package (which will integrate it nicely with start- and shutdown scripts) and simply replace the nginx binary with a self-compiled version that includes mod_wsgi.
&lt;/p&gt;
&lt;p&gt;So, here it goes: download and expand the sources for nginx (currently 0.5.35) and mod_wsgi (currently version 0.0.6):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget http://sysoev.ru/nginx/nginx-0.5.35.tar.gz
wget http://hg.mperillo.ath.cx/nginx/mod_wsgi/archive/0.0.6.tar.gz
tar xzf nginx-0.5.35.tar.gz
tar xzf 0.0.6.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;*By the way, it seems to be a feature of mercurial unknown to the author of &lt;code&gt;mod_wsgi&lt;/code&gt; Manlio Perillo to provide &lt;code&gt;.tgz&lt;/code&gt; archives not only for the &lt;code&gt;tip&lt;/code&gt; but also for each &lt;code&gt;tag&lt;/code&gt;. Currently the &lt;code&gt;tip&lt;/code&gt; of &lt;code&gt;mod_wsgi&lt;/code&gt; doesn't compile on Mac OS X so I'm sticking with version 0.0.6 which has proven to be stable and contains the config fixes for Mac OS X.*
&lt;/p&gt;
&lt;p&gt;For both Ubuntu and Mac OS X we will need to explicitly tell the mod_wsgi plugin to use Python 2.4 rather than the default 2.5 version that comes with both systems, since I'm intending to run Zope based applications:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$EDITOR mod_wsgi-0.0.6/config
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Change the second line of the file to:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PYTHON='python2.4'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Ubuntu&lt;/h2&gt;
&lt;p&gt;On Ubuntu you will need to install the following packages:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install gcc
sudo apt-get install python2.4-dev
sudo apt-get install libxslt-dev
sudo apt-get install libssl-dev
sudo apt-get install libpcre3-dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To take advantage of the start- and stop mechanisms provided by the official nginx package, let's first install that:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can change into the nginx source directory and configure the build process to replace the packaged version of nginx with one that includes &lt;code&gt;mod_wsgi&lt;/code&gt; like so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd nginx-0.5.35
./configure --add-module=../mod_wsgi-0.0.6/ --prefix=/usr/local --sbin-path=/usr/sbin \
    --conf-path=/etc/nginx/nginx.conf --with-http_ssl_module
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should receive a summary that looks like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Configuration summary
  + threads are not used
  + using system PCRE library
  + using system OpenSSL library
  + md5 library is not used
  + sha1 library is not used
  + using system zlib library

  nginx path prefix: &amp;quot;/usr/local&amp;quot;
  nginx binary file: &amp;quot;/usr/sbin&amp;quot;
  nginx configuration file: &amp;quot;/etc/nginx/nginx.conf&amp;quot;
  nginx pid file: &amp;quot;/usr/local/logs/nginx.pid&amp;quot;
  nginx error log file: &amp;quot;/usr/local/logs/error.log&amp;quot;
  nginx http access log file: &amp;quot;/usr/local/logs/access.log&amp;quot;
  nginx http client request body temporary files: &amp;quot;/usr/local/client_body_temp&amp;quot;
  nginx http proxy temporary files: &amp;quot;/usr/local/proxy_temp&amp;quot;
  nginx http fastcgi temporary files: &amp;quot;/usr/local/fastcgi_temp&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Make sure, the packaged instance of nginx is not running (we won't be able to replace it, otherwise):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo /etc/init.d/nginx stop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can do the usual &lt;code&gt;make ; sudo make install&lt;/code&gt; dance.
&lt;/p&gt;
&lt;p&gt;Before starting up the instance, we still need to run &lt;code&gt;setup.py&lt;/code&gt; from the &lt;code&gt;mod_wsgi&lt;/code&gt; folder:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ../mod_wsgi-0.0.6/
sudo python2.4 setup.py --prefix=/usr/local/ --sbin-path=/usr/sbin/ --conf-path=/etc/nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can start up your instance:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo /etc/init.d/nginx start
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Mac OS X&lt;/h2&gt;
&lt;p&gt;On Mac OS X you will need to have the Developer Tools and MacPorts installed and the install the following in addition:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo port install python2.4
sudo port install libxslt # has libxml2 as auto-dependency
sudo port install py-libxml2
sudo port install nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For the configure process to find the 2.4 python libraries I found I needed to copy them to &lt;code&gt;/opt/local/lib&lt;/code&gt;, as otherwise nginx would load the libraries of the system's 2.5 version at startup time which would throw &lt;code&gt;mod_wsgi&lt;/code&gt; off track.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cp /opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/libpython2.4.dylib /opt/local/lib/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can configure it to match the nginx version from the ports collection like so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./configure --add-module=../mod_wsgi-0.0.6/ --prefix=/opt/local --conf-path=etc/nginx/nginx.conf --sbin-path=sbin/ --with-http_ssl_module
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Again, here's the summary output you should expect:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Configuration summary
  + threads are not used
  + using system PCRE library
  + using system OpenSSL library
  + md5 library is not used
  + sha1 library is not used
  + using system zlib library

  nginx path prefix: &amp;quot;/opt/local&amp;quot;
  nginx binary file: &amp;quot;/opt/local/sbin/&amp;quot;
  nginx configuration file: &amp;quot;/opt/local/etc/nginx/nginx.conf&amp;quot;
  nginx pid file: &amp;quot;/opt/local/logs/nginx.pid&amp;quot;
  nginx error log file: &amp;quot;/opt/local/logs/error.log&amp;quot;
  nginx http access log file: &amp;quot;/opt/local/logs/access.log&amp;quot;
  nginx http client request body temporary files: &amp;quot;/opt/local/client_body_temp&amp;quot;
  nginx http proxy temporary files: &amp;quot;/opt/local/proxy_temp&amp;quot;
  nginx http fastcgi temporary files: &amp;quot;/opt/local/fastcgi_temp&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can do the usual &lt;code&gt;make ; sudo make install&lt;/code&gt; dance. 
&lt;/p&gt;
&lt;p&gt;Before starting up the instance, we still need to run &lt;code&gt;setup.py&lt;/code&gt; from the &lt;code&gt;mod_wsgi&lt;/code&gt; folder:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd ../mod_wsgi-0.0.6/
sudo python2.4 setup.py --prefix=/opt/local/ --sbin-path=/opt/local/sbin/ --conf-path=/opt/local/etc/nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we're finally ready to fire up our new instance. While testing and developing I can't be bothered to use &lt;code&gt;launchctl&lt;/code&gt; so I chose a more pedestrian approach:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo killall nginx ; sudo /opt/local/sbin/nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now you can take a look at the sample &lt;code&gt;nginx.conf&lt;/code&gt; file provided in the &lt;code&gt;examples&lt;/code&gt; directory of mod_wsgi to take the provided WSGI demos for a spin and, of course, to serve as a starting point to get your own apps running. Next I'll be looking at getting &lt;code&gt;repoze.plone&lt;/code&gt; and &lt;code&gt;repoze.grok&lt;/code&gt; running behind nginx+mod_wsgi, so stay tuned.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>wsgi</category>
                
                
                    <category>repoze</category>
                
                
                    <category>python</category>
                
                
                    <category>ubuntu</category>
                
                
                    <category>nginx</category>
                
                
                    <category>linux</category>
                
                
                    <category>hints</category>
                

                <pubDate>Wed, 16 Apr 2008 12:28:22 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Today is Naked CSS Day</title>
                <guid>http://tomster.org/blog/archive/2008/04/09/today-is-naked-css-day</guid>
                <link>http://tomster.org/blog/archive/2008/04/09/today-is-naked-css-day</link>
                <description>
&lt;p&gt;Out of a whim I decided to join today's &lt;a href="http://naked.dustindiaz.com/" title="CSS Naked Day"&gt;CSS Naked Day&lt;/a&gt;. After all, as a Plone Site there is no need to be ashamed :-)
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>


                <pubDate>Wed, 09 Apr 2008 15:27:03 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Deliverance á la WSGI for Plone</title>
                <guid>http://tomster.org/blog/archive/2008/04/08/deliverance-a-la-wsgi-for-plone</guid>
                <link>http://tomster.org/blog/archive/2008/04/08/deliverance-a-la-wsgi-for-plone</link>
                <description>
&lt;p&gt;&lt;a href="http://www.openplans.org/projects/deliverance/project-home" title="Deliverance - deliverance"&gt;Deliverance&lt;/a&gt; is the New Kid on the Block[tm] in the Plone world. I find the whole concept very intriguing and have decided to give it a try on both of my current new projects. (No risk, no fun, eh!?)
&lt;/p&gt;
&lt;p&gt;One of the two projects is smaller in scope where I am both the Zope/Plone developer &lt;em&gt;and&lt;/em&gt; the HTML/CSS handyman and the other a larger affair together with another Zopista and an external web agency with up to five more people, none of which is experienced with - or much interested in - Plone, so I am curious, how Deliverance will hold up in these two quite different scenarios.
&lt;/p&gt;
&lt;p&gt;Now, if you just want to dip your toes into the proverbial water, I suggest you check out &lt;a href="http://pypi.python.org/pypi/plone.recipe.deliverance" title="Python Package Index : plone.recipe.deliverance 1.0rc1"&gt;Martin Aspeli's Deliverance recipe&lt;/a&gt; (does that man ever sleep?) However, Martin's recipe, along with any other tutorial that I found floating about, uses deliverance in its so-called &lt;a href="http://www.openplans.org/projects/deliverance/using-the-proxy" title="Using the proxy - deliverance"&gt;proxy mode&lt;/a&gt; where a second daemon is fired up that mediates between the web- and application server. This is not optimal, of course, as it pretty much defeats the whole point of the &lt;a href="http://www.python.org/dev/peps/pep-0333/" title="PEP 333 -- Python Web Server Gateway Interface v1.0"&gt;WSGI&lt;/a&gt; concept, so I set out to create a setup, where Plone would be themed by Deliverance configured as a WSGI middleware. Forthwith my notes:
&lt;/p&gt;
&lt;p&gt;I conducted my test on Mac OS X 10.5.2 with Python 2.4.5 installed via Macports. I didn't use &lt;code&gt;virtualenv&lt;/code&gt; (although I should have) but had to make sure throughout the whole process, that python2.4 was used (as opposed to Leopard's default 2.5.1). To do that, I installed easy_install and setuptools explicitly for 2.4:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python2.4 ez_setup.py
sudo python ez_setup.py -U setuptools
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Before dealing with Deliverance I set up a WSGI enabled Plone instance. The &lt;a href="http://svn.repoze.org/buildouts/repoze.plone/trunk" title="Revision 886: /buildouts/repoze.plone/trunk"&gt;buildout provided by repoze.plone&lt;/a&gt; proved to be the best candidate to do so (believe me!)
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;svn co http://svn.repoze.org/buildouts/repoze.plone/trunk repoze.plone
cd repoze.plone
python2.4 bootstrap.py
./bin/buildout
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I then fired up the new instance as per instructions:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./bin/supervisord
./bin/addzope2user admin admin
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I then could add a Plone instance &lt;code&gt;foo&lt;/code&gt; at &lt;code&gt;localhost:8080&lt;/code&gt; just as always. I then stopped the zope instance so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./bin/supervisorctl stop zope
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and then restarted it using &lt;code&gt;paster&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./bin/paster serve etc/zope2.ini
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and sure enough, &lt;code&gt;localhost:8080/foo&lt;/code&gt; was still there!
&lt;/p&gt;
&lt;p&gt;Now the only thing missing was Deliverance itself. To make it available for the instance, I simply easy_installed it into my system (this is the part, where next time I'll use &lt;code&gt;virtualenv&lt;/code&gt;!):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo easy_install-2.4 Deliverance
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This enabled me to add the following snippet to &lt;code&gt;etc/zope2.ini&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[filter:deliverance]
paste.filter_app_factory = deliverance.wsgimiddleware:make_filter
theme_uri = file:///%(here)s/layout.html
rule_uri = file:///%(here)s/rules.xml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To use the deliverance as a filter in the WSGI stack I just had to add it somewhere. I chose to add it just after zope2 itself, so that my pipeline section looked like so:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[pipeline:main]
pipeline = egg:Paste#cgitb
           egg:Paste#httpexceptions
           egg:repoze.retry#retry
           egg:repoze.tm#tm
           egg:repoze.vhm#vhm_xheaders 
           errorlog
           deliverance
           zope2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Before restarting zope (or rather 'reserving it with paster') I had to add the rulefiles mentioned in the filter declaration. Eager as I was at this point, I simply borrowed the trivial default rule and theme from Martin's recipe, spiced it up a little with &lt;a href="http://svn.repoze.org/www/trunk/static.repoze.org/themes/maintainable/rules.xml"&gt;one of repoze.org's own rule files&lt;/a&gt; and created a &lt;code&gt;etc/rules.xml&lt;/code&gt; file that looked like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;rules xmlns:xi=&amp;quot;http://www.w3.org/2001/XInclude&amp;quot; 
    xmlns=&amp;quot;http://www.plone.org/deliverance&amp;quot;&amp;gt;
    &amp;lt;prepend theme=&amp;quot;//head&amp;quot; content=&amp;quot;//head/link&amp;quot; nocontent=&amp;quot;ignore&amp;quot; /&amp;gt; 
    &amp;lt;prepend theme=&amp;quot;//head&amp;quot; content=&amp;quot;//head/style&amp;quot; nocontent=&amp;quot;ignore&amp;quot; /&amp;gt; 
    &amp;lt;append theme=&amp;quot;//head&amp;quot; content=&amp;quot;//head/script&amp;quot; nocontent=&amp;quot;ignore&amp;quot; /&amp;gt;    
    &amp;lt;append theme=&amp;quot;//head&amp;quot; content=&amp;quot;//head/meta&amp;quot; nocontent=&amp;quot;ignore&amp;quot; /&amp;gt;
    &amp;lt;append-or-replace 
        theme=&amp;quot;//head&amp;quot; 
        content=&amp;quot;//head/title&amp;quot;
        nocontent=&amp;quot;ignore&amp;quot; /&amp;gt;
    &amp;lt;append-or-replace theme=&amp;quot;//div[@id='content']&amp;quot;
        content=&amp;quot;//div[@id='region-content']&amp;quot;
        nocontent=&amp;quot;ignore&amp;quot; /&amp;gt;
&amp;lt;/rules&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and a &lt;code&gt;etc/layout.html&lt;/code&gt; file that looked like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML PUBLIC &amp;quot;-//W3C//DTD HTML 4.01 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/html4/loose.dtd&amp;quot;&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-15&amp;quot;&amp;gt;
&amp;lt;title&amp;gt;The Theme&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;A theme&amp;lt;/h1&amp;gt;
&amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;address&amp;gt;&amp;lt;/address&amp;gt;
&amp;lt;!-- hhmts start --&amp;gt;Last modified: Fri Mar 16 09:33:37 CDT 2007 &amp;lt;!-- hhmts end --&amp;gt;
&amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.1//EN&amp;quot;
    &amp;quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&amp;quot;&amp;gt;

&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xml:lang=&amp;quot;en&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;layout&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I could stop the foreground paster process, fire it up again, hit reload in my browser and voila! Bob was my proverbial Uncle!
&lt;/p&gt;
&lt;p&gt;Next, I'll give &lt;code&gt;mod_wsgi&lt;/code&gt; a try. But, of course, &lt;em&gt;not&lt;/em&gt; the one for Apache but... yup, there's a &lt;a href="mod_wsgi"&gt;mod_wsgi for nginx&lt;/a&gt;, too, yay! Stay tuned...
&lt;/p&gt;
&lt;p&gt;P.S. I'd like to take this opportunity to thank &lt;a href="http://repoze.org/index.html" title="Repoze"&gt;Chris, Tres and Paul&lt;/a&gt; for their efforts to connect Zope and Plone with non-techies and non-Zopistas. I'm very confident that you guys are creating some serious groundwork here that will benefit us immensely during &lt;a href="http://limi.net/articles/thank-you-plone-community" title="Thank you, Plone Community! &amp;amp;mdash limi.net"&gt;the next eight years&lt;/a&gt;! Rock on!
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>zope</category>
                
                
                    <category>repoze</category>
                
                
                    <category>wsgi</category>
                
                
                    <category>plone</category>
                
                
                    <category>deliverance</category>
                

                <pubDate>Tue, 08 Apr 2008 18:01:42 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Using the OKI C9800 on a Mac</title>
                <guid>http://tomster.org/blog/archive/2008/04/04/using-the-oki-c9800-on-a-mac</guid>
                <link>http://tomster.org/blog/archive/2008/04/04/using-the-oki-c9800-on-a-mac</link>
                <description>
&lt;p&gt;Earlier this week I bought a printer for the new project I'm working on. A &lt;a href="http://www.c9800.co.uk/" title="OKI C9800 Colour Laser Printer"&gt;big, bad-ass OKI 9800 A3  color printer&lt;/a&gt; for the price of a small car -- not my money -- the client's money ;-).
&lt;/p&gt;
&lt;p&gt;Since we're a Mac-only shop here, I made sure it's got postscript3 and ethernet, so that connectivity wouldn't be a problem. Well, it was. Of course. Long story short: if we used the offical, OKI supplied PPD, the printer wouldn't print. It only could be coaxed into printing when using the generic postscript PPD -- which of course knew nothing about the A3 paper size or any of the other nifty features.
&lt;/p&gt;
&lt;p&gt;After spending three days(!) with the OKI hotline (spent mainly with re-stating our problem and configuration to various operators) I finally hit gold. In the form of a friendly, competent and female(!) operator (Hallo, Frau Walther!) who didn't just resort to OKI's ticket database but (gasp!) to her &lt;em&gt;memory&lt;/em&gt;. She actually &lt;em&gt;remembered&lt;/em&gt; a similar case a while back, told me to hold, came back 30 seconds later and ever since we're able to print here!
&lt;/p&gt;
&lt;p&gt;Turns out, that &lt;strong&gt;OKI has been delivering a faulty PPD - ever since march 2005!&lt;/strong&gt; In the end it's just a single &lt;code&gt;%&lt;/code&gt; character that's missing. I have to ask myself: WTF did they not update that file? Anyway, I'm posting this so that any other fellow OKI users can find this (because until now googling for the error &lt;code&gt;Missing filter &amp;quot;application/vnd.cups-postscript 0 fierycupsfilter&amp;quot;&lt;/code&gt; didn't deliver any results. Hopefully, this will have changed).
&lt;/p&gt;
&lt;p&gt;Below you can find a diff of the the PPD or, for your convenience, you can download a &lt;a href="/geek/mac/OKI%20C9800/view"&gt;patched version right here from tomster.org&lt;/a&gt;.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@@ -2947,5 +2947,5 @@

 *% PPD Last Modified 2005.03.10
 *% OS 10.2 PPD DB version 4/10/03 JDF
-*cupsFilter: &amp;quot;application/vnd.cups-postscript 0 fierycupsfilter&amp;quot;
+*% cupsFilter: &amp;quot;application/vnd.cups-postscript 0 fierycupsfilter&amp;quot;
 *% End of PPD file
&lt;/code&gt;&lt;/pre&gt;

</description>
                <author>Tom Lazar</author>

                
                    <category>rant</category>
                
                
                    <category>macintosh</category>
                
                
                    <category>hints</category>
                

                <pubDate>Fri, 04 Apr 2008 12:03:31 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>URL-dependent skinswitching in Plone 3</title>
                <guid>http://tomster.org/blog/archive/2008/04/02/url-dependent-skinswitching-in-plone-3</guid>
                <link>http://tomster.org/blog/archive/2008/04/02/url-dependent-skinswitching-in-plone-3</link>
                <description>
&lt;p&gt;I was just about to explain to somebody via email how to switch skins per url in Plone 3 when I realised I should rather blog it and send him the link instead of just explain it to him privately, so here it goes...
&lt;/p&gt;
&lt;p&gt;Add a file &lt;code&gt;skinswitcher.py&lt;/code&gt; to the top-level of your product with the following contents:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def setskin(site, event):
    if event.request.URL.find('127.0.0.1') &amp;gt; -1 \
        or event.request.URL.startswith('https'):
        site.changeSkin('NuPlone', event.request)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;then include the following snippet in your top-level &lt;code&gt;configure.zcml&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;subscriber
    for=&amp;quot;Products.CMFPlone.interfaces.IPloneSiteRoot
         zope.app.publication.interfaces.IBeforeTraverseEvent&amp;quot;
    handler=&amp;quot;.skinswitcher.setskin&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This particular example simply enables the &lt;code&gt;NuPlone&lt;/code&gt; skin when the site is accessed via &lt;code&gt;https&lt;/code&gt; or &lt;code&gt;127.0.0.1&lt;/code&gt; (instead of &lt;code&gt;localhost&lt;/code&gt;) and otherwise uses the default skin which is my usecase 99% of the time but it should be easy now to modify &lt;code&gt;skinswitcher.py&lt;/code&gt; to your particular needs.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>plone</category>
                
                
                    <category>hints</category>
                

                <pubDate>Wed, 02 Apr 2008 10:02:30 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Site wide maintenance message</title>
                <guid>http://tomster.org/blog/archive/2008/03/21/site-wide-maintenance-message</guid>
                <link>http://tomster.org/blog/archive/2008/03/21/site-wide-maintenance-message</link>
                <description>
&lt;p&gt;When doing maintenance work on a deployment site it is always a good idea (and in good taste) to show visitors a human-readable page explaining that you'll be back soon[tm] instead of letting them see ugly tracebacks etc.
&lt;/p&gt;
&lt;p&gt;Easy, right? Just put a static HTML file and configure it as the site root and you're done, right? Well, not quite. Because that will show the page to all visitors of the root of your site, but everybody else will get a &lt;code&gt;404&lt;/code&gt;. 
&lt;/p&gt;
&lt;p&gt;Well, regular expressions and &lt;a href="http://nginx.net/" title="nginx"&gt;nginx&lt;/a&gt; to the rescue. The following configuration snippet displays the same &lt;code&gt;index.html&lt;/code&gt; page to &lt;em&gt;any&lt;/em&gt; request, not just the front page. I now keep it commented out in all my config files to be able to quickly turn on a maintenance message if something requires some fixing:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    listen 80;
    server_name foobar.tld;

    root /usr/local/www/foobar/;
    index  index.html index.htm;
    location ^~ /index.html {
    }
    location / {
        rewrite &amp;quot;^/(.+)$&amp;quot; / last;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The crucial part is the (empty) &lt;code&gt;^~ /index.html&lt;/code&gt; location that simply exists to stop an endless recursion that would take place otherwise. It also means, that your HTML file must be named &lt;code&gt;index.html&lt;/code&gt; and reside in &lt;code&gt;/usr/local/www/foobar/&lt;/code&gt; on the file system.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>nginx</category>
                
                
                    <category>hints</category>
                

                <pubDate>Fri, 21 Mar 2008 22:56:26 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>nginx and varnish on Mac OS X</title>
                <guid>http://tomster.org/blog/archive/2008/03/16/nginx-and-varnish-on-mac-os-x</guid>
                <link>http://tomster.org/blog/archive/2008/03/16/nginx-and-varnish-on-mac-os-x</link>
                <description>
&lt;p&gt;Any non-trivial deployment of Plone usually consists of at least a web server 'sitting in front of' it, often enough accompanied by some sort of caching service. For my own purposes I have settled on &lt;a href="http://nginx.net/" title="nginx"&gt;nginx&lt;/a&gt; for the former and &lt;a href="http://varnish.projects.linpro.no/" title="Varnish - Trac"&gt;varnish&lt;/a&gt; for the latter[1].
&lt;/p&gt;
&lt;p&gt;They have proven to be a reasonably good team for me, especially in combination with &lt;a href="http://plone.org/products/cachefu/releases/1.1.1" title="CacheFu 1.1.1"&gt;recent versions of CacheFu&lt;/a&gt;, Plone's de facto default caching product. By 'reasonably good' I mean, that varnish and CacheFu in their 'normal' setup (i.e. with the 'official' &lt;a href="http://varnish.projects.linpro.no/browser/trunk/varnish-cache/etc/zope-plone.vcl" title="/trunk/varnish-cache/etc/zope-plone.vcl - Varnish - Trac"&gt;Plone .vcl config&lt;/a&gt;) offer a reasonable trade-off between performance and potentially stale content.
&lt;/p&gt;
&lt;p&gt;I noticed this behaviour particularly when looking at Zope's access log (i.e. &lt;code&gt;var/log/primary-Z2.log&lt;/code&gt;) while accessing my latest Plone installation at &lt;a href="http://wahlcomputer.ccc.de/" title="Einführung &amp;amp;mdash; CCC Wahlcomputer"&gt;wahlcomputer.ccc.de&lt;/a&gt;. There was much too much going on, as theoretically there shouldn't be any requests reaching the backend until some content had changed. In essence, the site behaved much slower than it would need to by answering unnecessarily to requests that varnish should be able to satisfy.
&lt;/p&gt;
&lt;p&gt;However, in order to debug the caching and purging of content in detail I needed a local Mac OS X based setup that mirrored that on the FreeBSD box serving the site as closely, as possible. I habitually took notes while setting it up on my desktop machine and am now retracing my steps as I attempt to duplicate it on my Macbook (Just like a bug isn't fixable until it's reproducible, I never consider my admin work done until I have been able to do it at least twice). I'm confident that somebody out there will find the following notes useful, too (even if it's just myself six months^wweeks down the road)...
&lt;/p&gt;
&lt;p&gt;Since I'm a happy user of the &lt;a href="http://www.macports.org/" title="The MacPorts Project -- Home"&gt;macports collection&lt;/a&gt; already anyway, I let it do the 'heavy lifting' of actually installing &lt;code&gt;nginx&lt;/code&gt; and &lt;code&gt;varnish&lt;/code&gt;. In addition I provided a &lt;code&gt;launchd&lt;/code&gt; startup item for varnish and also added a host entry for &lt;code&gt;wahlcomputer&lt;/code&gt; to enable virtual hosting for nginx and varnish. Here it goes: 
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo port install nginx
sudo port install varnish
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;DNS&lt;/h2&gt;
&lt;p&gt;Before continuing the setup I first wanted to make sure that I could use the domain name &lt;code&gt;wahlcomputer&lt;/code&gt; to access my machine. Instead of doing it 'properly' by adding a new record to OpenLDAP and thus possibly opening up what could amount to yet another can of worms I simply tried to edit ye' good ol' &lt;code&gt;/etc/hosts&lt;/code&gt; file and added the following line:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;127.0.0.1   wahlcomputer
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And sure enough, even in the days of 'OpenLDAP FTW!!' Mac OS X still honours entries made to the hosts file so I could move on.
&lt;/p&gt;

&lt;h2&gt;nginx&lt;/h2&gt;
&lt;p&gt;Next, I configured the freshly installed &lt;code&gt;nginx&lt;/code&gt;. As the port already comes with a &lt;code&gt;launchd&lt;/code&gt; start up item, I just needed to load it:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo launchctl load /opt/local/etc/LaunchDaemons/org.macports.nginx/org.macports.nginx.plist
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It's my practice to leave the default files as untouched as possible and put all my configurations into separate files, that I simply include:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo mv /opt/local/etc/nginx/nginx.conf.default  /opt/local/etc/nginx/nginx.conf
sudo mkdir /opt/local/etc/nginx/includes
sudo touch /opt/local/etc/nginx/includes/wahlcomputer.conf
sudo mkdir /opt/local/var/log/nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To make &lt;code&gt;nginx&lt;/code&gt; aware of those files I added the following line just before the final closing &lt;code&gt;}&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;include etc/nginx/includes/*.conf;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here's its contents in its full, unabridged glory (and &lt;a href="http://plope.com/Members/chrism/vhm_victory" title="plope - Vanquishing the Virtual Host Monster"&gt;VHM gore&lt;/a&gt;):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;server {
    server_name wahlcomputer.ccc.de wahlcomputer;
    location / {
        proxy_pass http://127.0.0.1:8071/VirtualHostBase/http/wahlcomputer:80/foo/VirtualHostRoot/;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For the changes to take effect, I needed to restart &lt;code&gt;nginx&lt;/code&gt; like so (why, oh why, does &lt;code&gt;launchctl&lt;/code&gt; with all its bells and whistles not have a simple &lt;code&gt;reload&lt;/code&gt; or &lt;code&gt;restart&lt;/code&gt; command?!):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo launchctl stop org.macports.nginx
sudo launchctl start org.macports.nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now visiting &lt;code&gt;http://wahlcomputer/&lt;/code&gt; showed the front page of the Plone site and I could move on to &lt;code&gt;varnish&lt;/code&gt;:
&lt;/p&gt;

&lt;h2&gt;varnish&lt;/h2&gt;
&lt;p&gt;Unlike &lt;code&gt;nginx&lt;/code&gt;, the varnish port (currently) does &lt;em&gt;not&lt;/em&gt; come with a startup item, so I made my very own (by blatantly copying from the &lt;code&gt;nginx&lt;/code&gt; setup):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo mkdir /opt/local/etc/varnish
sudo touch /opt/local/etc/varnish/default.vcl
sudo mkdir /opt/local/etc/LaunchDaemons/org.macports.varnish
sudo touch /opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist
sudo chown root:wheel /opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist
sudo chmod 644 /opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist
sudo ln -s /opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist /Library/LaunchDaemons/
sudo mkdir /opt/local/var/varnish
sudo chown -R _www /opt/local/var/varnish
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Looking at &lt;code&gt;varnishd&lt;/code&gt;'s &lt;a href="http://www.digipedia.pl/man/varnishd.1.html" title="&amp;quot;man varnishd (1"&gt;man page&lt;/a&gt;  - HTTP accelerator daemon - Linux Manual - Digipedia&amp;quot;) I saw that there are some options that must be passed in upon start up. I did this by adding them to the &lt;code&gt;ProgramArguments&lt;/code&gt; array in the &lt;code&gt;/opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist&lt;/code&gt; file:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;Disabled&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
    &amp;lt;key&amp;gt;KeepAlive&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
    &amp;lt;key&amp;gt;Debug&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;varnishd&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;OnDemand&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
    &amp;lt;key&amp;gt;GroupName&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;staff&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;UserName&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;_www&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;/opt/local/sbin/varnishd&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-a&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;localhost:6081&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-T&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;localhost:6082&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;-f&amp;lt;/string&amp;gt;
        &amp;lt;string&amp;gt;/opt/local/etc/varnish/default.vcl&amp;lt;/string&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now all that was missing was to add some directives to the currently still empty file &lt;code&gt;/opt/local/etc/varnish/default.vcl&lt;/code&gt;. It ended up being too long to quote here in its entirety, instead I will simply point you to &lt;a href="http://bitubique.com/tutorials/accelerate-plone-with-varnish" title="Accelerate Plone with Varnish &amp;amp;mdash; Bitubique"&gt;a nice variation of the 'official zope-plone.vcl that I found that sports some neat enhancements&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Finally I could start up varnish:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo launchctl load /opt/local/etc/LaunchDaemons/org.macports.varnish/org.macports.varnishd.plist
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the nginx &lt;code&gt;wahlcomputer.conf&lt;/code&gt; file all I needed to change was the port number from 8071 (the Zope instance) to 6081 (varnish).
&lt;/p&gt;
&lt;p&gt;By keeping a &lt;a href="http://www.monkey.org/cgi-bin/man2html?tail" title="tail manual page"&gt;tail&lt;/a&gt; on the access logs of nginx and my Zope instance and looking at the response headers with &lt;a href="http://getfirebug.com/" title="Firebug - Web Development Evolved"&gt;firebug&lt;/a&gt; I can now start to tweak my setup to my heart's content. Stay tuned.
&lt;/p&gt;
&lt;p&gt;[1] A bit of an explanation is perhaps necessary as to why even bother with &lt;em&gt;two&lt;/em&gt; types of machinery in front of Plone. The short answer is 'separation of concerns'. While varnish could theoretically take over most of the features that I use nginx for (namely, URL-rewriting, logging and static content delivery) I still would need it for SSL/HTTPS. Also, the logging feature of varnish requires an extra &lt;code&gt;varnishlog&lt;/code&gt; process anyway.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>varnish</category>
                
                
                    <category>cache-fu</category>
                
                
                    <category>nginx</category>
                
                
                    <category>zope</category>
                
                
                    <category>hints</category>
                
                
                    <category>plone</category>
                
                
                    <category>macintosh</category>
                

                <pubDate>Sun, 16 Mar 2008 19:24:56 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Chaosradio Express on Plone and Zope</title>
                <guid>http://tomster.org/blog/archive/2008/03/16/chaosradio-express-on-plone-and-zope</guid>
                <link>http://tomster.org/blog/archive/2008/03/16/chaosradio-express-on-plone-and-zope</link>
                <description>
&lt;p&gt;&lt;a href="http://twitter.com/tomlazar/statuses/766201924"&gt;Two weeks ago&lt;/a&gt; I sat down with &lt;a href="http://tim.geekheim.de/"&gt;Tim Pritlove&lt;/a&gt; and he interviewed me about Plone and Zope for his &lt;a href="http://chaosradio.ccc.de/chaosradio_express.html"&gt;Chaosradio Express podcast&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;I thoroughly enjoyed the experience, largely due to the fact that Tim proved to be an excellent host. He gave me enough leeway to ramble while at the same time providing enough structure for the process to let me relax and be myself. Thanks Tim!
&lt;/p&gt;
&lt;p&gt;In the end we talked over one and a half hours and I can only assume that one has to have a genuine interest in the content matter to listen to it all the way through but afterwards I still felt that I had left much unsaid.
&lt;/p&gt;
&lt;p&gt;I tried to be honest and upfront about Zope and Plone's weaknesses while still conveying that they both are truly great systems with even greater communities. The interview was conducted in German, though, so I figure the percentage of the audience of this blog that will find it interesting is probably rather small, but nonetheless, &lt;a href="http://chaosradio.ccc.de/cre078.html"&gt;here's the link to the episode&lt;/a&gt;.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>zope</category>
                
                
                    <category>chaos</category>
                
                
                    <category>podcasting</category>
                
                
                    <category>plone</category>
                

                <pubDate>Sun, 16 Mar 2008 16:07:56 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>The state of the Union^WLinguaPlone</title>
                <guid>http://tomster.org/blog/archive/2008/03/07/the-state-of-the-union-wlinguaplone</guid>
                <link>http://tomster.org/blog/archive/2008/03/07/the-state-of-the-union-wlinguaplone</link>
                <description>
&lt;p&gt;Today I made an offer to a prospective client for a multi-lingual, Plone based website. Since &lt;a href="http://plone.org/products/plone/releases/2.0.5" title="Plone 2.0.5"&gt;it's been a while&lt;/a&gt; since I've had any hands-on experience with Plone's de-facto standard product for managing multi-lingual content &lt;a href="http://plone.org/products/linguaplone"&gt;LinguaPlone&lt;/a&gt; I decided I'd best take the current offerings for a spin before I make any (legally binding!) promises.
&lt;/p&gt;
&lt;p&gt;On first sight, things regarding multi-lingual content are currently a bit confusing. While there is a stable release of LinguaPlone that offers support for Plone 3.0, there have also been recent developments in Plone itself that have broken LinguaPlone (for instance &lt;a href="http://permalink.gmane.org/gmane.comp.web.zope.plone.user/81897" title="gmane.comp.web.zope.plone.user"&gt;3.0.5 didn't seem to fare particularily well &lt;/a&gt;in this regard).
&lt;/p&gt;
&lt;p&gt;As always, when feeling uncertain or confused about something Plone related, I turned to &lt;code&gt;#plone&lt;/code&gt;, where luckily &lt;code&gt;jensens&lt;/code&gt; and &lt;code&gt;baekholt&lt;/code&gt; were online at the moment and it soon transpired, that things aren't actually quite as bleak as it seemed and further testing on my part today confirmed that. So, without further ado, here's the lodown:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     use &lt;a href="http://plone.org/products/plone/releases/3.0.6"&gt;Plone &amp;gt;= 3.0.6&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     install &lt;a href="http://pypi.python.org/pypi/plone.browserlayer" title="Python Package Index : plone.browserlayer 1.0rc2"&gt;plone.browserlayer&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     use &lt;a href="http://svn.plone.org/svn/plone/LinguaPlone/trunk/" title="Revision 19688: /LinguaPlone/trunk"&gt;LinguaPlone 2.1/svn&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     use &lt;a href="http://plone.org/products/plonelanguagetool/releases/2.1"&gt;PloneLanguageTool &amp;gt;= 2.1&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;em&gt;don't use&lt;/em&gt; the default Language selector portlet provided by Plone
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last item requires a bit of explanation. In its current implementation the default language selector portlet &lt;em&gt;only switches the language of the interface, but doesn't actually change the context to the translated version in the selected language&lt;/em&gt;. This, obviously still needs to be fixed, but is just cosmetical in nature. And if the offer that I just sent out will be accepted, I might even do it myself ;-)
&lt;/p&gt;
&lt;p&gt;Other than the non-working language selector all the scenarios I played through today worked like a charm, though. To switch languages I needed to manually enter the URL of an object that I knew to be of the target language, but since the new version of PLT keeps content and language interface always in sync, nothing else was required (and the fix for the selection tool shouldn't involve much else, either for that reason). 
&lt;/p&gt;
&lt;p&gt;LinguaPlone has come a long way to tackle a truly ambitious problem and I'm very sure, as of today, that Plone will prove to be one of the best solutions for managing multi-lingual content on the web. Again.
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>plone</category>
                
                
                    <category>linguaplone</category>
                

                <pubDate>Fri, 07 Mar 2008 19:23:39 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Skin dependent resources</title>
                <guid>http://tomster.org/blog/archive/2008/03/05/skin-dependent-resources</guid>
                <link>http://tomster.org/blog/archive/2008/03/05/skin-dependent-resources</link>
                <description>
&lt;p&gt;For the soon-to-be-released &lt;a href="http://wahlcomputer.ccc.de"&gt;Voting machines info site of the CCC&lt;/a&gt; I'm using the current trunk of &lt;a href="http://plone.org/products/nuplone" title="NuPlone"&gt;NuPlone&lt;/a&gt; for both its public facing pages, as well as for the editors. 
&lt;/p&gt;
&lt;p&gt;NuPlone has a neat new feature called &lt;em&gt;multiresolution layout&lt;/em&gt;, which is great, especially for editors. Basically it means, if you have a bigger screen or wider window you get a three column layout, if not, the layout is based on two columns (you can test that feature here at &lt;a href="http://tomster.org/blog/" title="Blog &amp;amp;mdash; tomster.org"&gt;tomster.org&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;However, for the CCC site the feature proved to be more confusing than useful for public visitors, so I wanted to make sure that the JS resource, responsible for that feature was only rendered, if the NuPlone skin was used.
&lt;/p&gt;
&lt;p&gt;The initial idea, was to include an empty &lt;code&gt;multi-resolution.js&lt;/code&gt; file with the &lt;code&gt;Wahlcomputer&lt;/code&gt; skin but it turns out, it's possible to evaluate the name of the current skin in the conditional expression of a resource. In this case I used the following snippet inside &lt;code&gt;jsregistry.xml&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;javascript cacheable=&amp;quot;True&amp;quot; 
    compression=&amp;quot;safe&amp;quot; 
    cookable=&amp;quot;True&amp;quot;
    enabled=&amp;quot;True&amp;quot; 
    expression=&amp;quot;python:portal.getCurrentSkinName()=='NuPlone'&amp;quot; 
    id=&amp;quot;multi-resolution.js&amp;quot; 
    inline=&amp;quot;False&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Instead of the default empty expression I used &lt;code&gt;python:portal.getCurrentSkinName()=='NuPlone'&lt;/code&gt; and bingo!
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>plone</category>
                
                
                    <category>note-to-myself</category>
                
                
                    <category>hints</category>
                

                <pubDate>Wed, 05 Mar 2008 19:31:03 +0000</pubDate>

                
            </item>
        
        
            <item>
                <title>Launchd in a nutshell</title>
                <guid>http://tomster.org/blog/archive/2008/02/27/launchd-in-a-nutshell</guid>
                <link>http://tomster.org/blog/archive/2008/02/27/launchd-in-a-nutshell</link>
                <description>
&lt;p&gt;Today I needed to make a &lt;a href="http://fetchmail.berlios.de/fetchmail-man.html" title="&amp;quot;Manual Page - fetchmail(man"&gt;fetchmail&lt;/a&gt; process automatically start on a &lt;a href="http://www.apple.com/xserve/" title="Apple - Xserve"&gt;Mac OS X Server&lt;/a&gt; &lt;a href="http://gruentuchernst.de/eng/berlin1/index.html"&gt;instance&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Now, ever since Version 10.4 this is the domain of &lt;a href="http://en.wikipedia.org/wiki/Launchd" title="launchd - Wikipedia, the free encyclopedia"&gt;launchd&lt;/a&gt;. But compared to &lt;a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/configtuning-rcd.html" title="Using rc under FreeBSD"&gt;what I'm used to in FreeBSD&lt;/a&gt;, &lt;a href="http://developer.apple.com/macosx/launchd.html" title="Getting Started with launchd"&gt;Apple's own introduction to launchd&lt;/a&gt; seemed rather daunting.
&lt;/p&gt;
&lt;p&gt;My reasong was something along the lines of &amp;quot;If I can't use something as straightforward as &lt;code&gt;rc&lt;/code&gt; I might as well get out the big guns and use &lt;a href="http://cr.yp.to/daemontools.html"&gt;daemontools&lt;/a&gt;&amp;quot; (which already e.g. takes care of my &lt;a href="http://tomster.org/geek/freebsdcookbook/ar01s03.html"&gt;IMAP Server&lt;/a&gt; and, of course, my &lt;a href="http://cr.yp.to/djbdns.html" title="djbdns: Domain Name System tools"&gt;name servers&lt;/a&gt;.)
&lt;/p&gt;
&lt;p&gt;Well, to make a long story short, once I got over the fact, that I need to &lt;em&gt;write XML to configure startup items&lt;/em&gt; everything else went rather smoothly. In the end, to have &lt;code&gt;fetchmail&lt;/code&gt; launched automatically at startup I needed the following markup in &lt;code&gt;/Library/LaunchDaemons/fetchmail.plist&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE plist PUBLIC &amp;quot;-//Apple//DTD PLIST 1.0//EN&amp;quot; &amp;quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;quot;&amp;gt;
&amp;lt;plist version=&amp;quot;1.0&amp;quot;&amp;gt;
&amp;lt;dict&amp;gt;
    &amp;lt;key&amp;gt;Disabled&amp;lt;/key&amp;gt;
    &amp;lt;false/&amp;gt;
    &amp;lt;key&amp;gt;GroupName&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;staff&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;KeepAlive&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
    &amp;lt;key&amp;gt;Label&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;fetchmail&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;Program&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;/usr/bin/fetchmail&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;ProgramArguments&amp;lt;/key&amp;gt;
    &amp;lt;array&amp;gt;
        &amp;lt;string&amp;gt;--fetchmailrc=/Users/diradmin/.fetchmailrc&amp;lt;/string&amp;gt;
    &amp;lt;/array&amp;gt;
    &amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;
    &amp;lt;true/&amp;gt;
    &amp;lt;key&amp;gt;Umask&amp;lt;/key&amp;gt;
    &amp;lt;integer&amp;gt;7&amp;lt;/integer&amp;gt;
    &amp;lt;key&amp;gt;UserName&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;diradmin&amp;lt;/string&amp;gt;
    &amp;lt;key&amp;gt;WorkingDirectory&amp;lt;/key&amp;gt;
    &amp;lt;string&amp;gt;/Users/diradmin/&amp;lt;/string&amp;gt;
&amp;lt;/dict&amp;gt;
&amp;lt;/plist&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Since the fetchmail process won't be launched via a logged in user, I needed to point it explicitly to the config file I developed for it using the &lt;code&gt;ProgramArguments&lt;/code&gt; key.)
&lt;/p&gt;
&lt;p&gt;Next, I needed to make sure that the abovementioned file had the right ownership and permissions:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo chown root:wheel /Library/LaunchDaemons/fetchmail.plist
sudo chmod 644 /Library/LaunchDaemons/fetchmail.plist
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unlike with &lt;code&gt;rc&lt;/code&gt; or &lt;code&gt;daemontools&lt;/code&gt;, however, just because I now had a perfectly fine config file sitting in its proper place didn't mean anything would happen next time the machine booted. No, I still needed to explicitly tell &lt;code&gt;launchd&lt;/code&gt; to use this item using its companion &lt;code&gt;launchctl&lt;/code&gt; command:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo launchctl load fetchmail.plist
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To test the item I then proceeded to manually start it:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo launchctl start fetchmail
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note, that this time I didn't state &lt;code&gt;fetchmail.plist&lt;/code&gt; as above but rather &lt;code&gt;fetchmail&lt;/code&gt;, which refers to the &lt;code&gt;Label&lt;/code&gt; key in the XML.
&lt;/p&gt;
&lt;p&gt;And sure enough, &lt;code&gt;fetchmail&lt;/code&gt; was now up and running and was doing its thing. Since I had set &lt;code&gt;KeepAlive&lt;/code&gt; to &lt;code&gt;&amp;lt;true/&amp;gt;&lt;/code&gt; I could kill it and not even a second later, it was back up and running (with a new PID, of course). Nice. Just like &lt;code&gt;daemontools&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;While I'm glad that this all went rather smoothly for me I must say that I much prefer &lt;code&gt;rc&lt;/code&gt; and &lt;code&gt;daemontools&lt;/code&gt;, though. &lt;code&gt;launchd&lt;/code&gt; seems over-engineered. I find that snippet above positively ugly. Even for XML. I mean, come on, what's this supposed to be: &lt;code&gt;&amp;lt;key&amp;gt;RunAtLoad&amp;lt;/key&amp;gt;&amp;lt;true/&amp;gt;&lt;/code&gt;?
&lt;/p&gt;
&lt;p&gt;But to be fair, Apple specifically designed &lt;code&gt;launchd&lt;/code&gt; to handle more than just start up items but to replace &amp;quot;init, rc, the init.d and rc.d scripts, SystemStarter (Mac OS X), inetd and xinetd, atd, crond and watchdogd&amp;quot;, to quote its &lt;a href="http://en.wikipedia.org/wiki/Launchd" title="launchd - Wikipedia, the free encyclopedia"&gt;Wikipedia entry&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;Anyway, from now on I'm probably just going to use the snippet above as boilerplate and get over with it ;-)
&lt;/p&gt;
&lt;p&gt;Oh, and &lt;a href="http://twitter.com/timbray/statuses/764015594" title="Twitter / Tim Bray: @tomlazar: Er I mean blog n..."&gt;Tim&lt;/a&gt;? Sorry about the XML bashing. I got nothing against XML per se. In fact I wouldn't know what to do without it. I just don't think it's a good choice for configuration files that are created and read by humans. (And perhaps, neither do you.) Even &lt;a href="http://grok.zope.org/" title="Grok - A Smashing Web Framework &amp;amp;mdash; Grok"&gt;Zope is moving away from ZCML&lt;/a&gt; ;-)
&lt;/p&gt;


</description>
                <author>Tom Lazar</author>

                
                    <category>xml</category>
                
                
                    <category>rant</category>
                
                
                    <category>macintosh</category>
                

                <pubDate>Wed, 27 Feb 2008 23:29:27 +0000</pubDate>

                
            </item>
        

    </channel>
</rss>


