Monthly Archives: June 2010

Summer Odds And Ends

June 30, 2010 » Life

Summer is here and I thought I’d post some recent photos from around the house.

Melvin the Toad
Melvin The Toad Lives In Our Backyard

Garden Herbs Drying
Garden Herbs Drying

Homemade Butter
Homemade Butter

Darcy Making Flour Tortilla Chips
Darcy Making Flour Torilla Chips

Home Fried Flour Tortilla Chips
Home Fried Flour Tortilla Chips

For those concerned, the chips were immediately consumed with homemade salsa.

They were delicious.

Tags: , , ,

Auto-Generated Github User Page With py-github

June 29, 2010 » Geek

Update (2010-06-30)

So I got antsy about this and I upgraded to using pystache instead of my homebrew templating system. This was my first run in with mustache, and I have to say I like it, even though I used the bare minimum feature set.

New code is at

Github has a cool feature called “Github Pages” that let you host static content on a subdomain of github, e.g.

They also provide an auto-generator for project pages that has a nice clean format which I really like. So I decided to make my user page match the look and feel of the project pages. And to boot I wanted to be able have it auto-generate since I want it to be “hands free”, otherwise I’ll forget to update it.

To make this happen I whipped up my template and then grabbed the excellent py-github from Dustin Sallings, which I have used before.

Without furthur ado I’ll just show you the source. It’s not complicated, just some API calls then search replace on a template file. If you want to use it, be sure to get the most recent version from

Throw in a cron job and you are set. Beware of lot’s of “page build” notices from Github though.

# -*- coding: utf-8 -*-

import github.github as github
import yaml
import time
from datetime import datetime

def repo_date_to_epoch ( date ):
  epoch = time.mktime(
  return int( epoch )

def main ():

  print "Loading settings...."
  f = open( 'settings.yaml' )
  settings = yaml.load( f )

  gh = github.GitHub()

  print "Fetching user information..."
  user = settings['username'] )

  print "Fetching repository information..."
  repos = gh.repos.forUser( settings['username'] )

  print "Sorting repositories..."
  repos = sorted( repos, cmp=lambda a, b: repo_date_to_epoch( b.pushed_at ) - repo_date_to_epoch( a.pushed_at ) )

  print "Loading template..."
  f = open( 'index.html.tpl' )
  template =

  print "Mangling template..."
  template = template.replace( '<% username %>', settings['username'] )
  template = template.replace( '<% fullname %>', )
  template = template.replace( '<% email %>', )
  template = template.replace( '<% following %>', str( user.following_count ) )
  template = template.replace( '<% followers %>', str( user.followers_count ) )
  template = template.replace( '<% publicrepos %>', str( user.public_repo_count ) )

  repo_string = ''

  for repo in repos:
    if repo.private:

    repo_string = repo_string + '

' + + '' try: repo_string = repo_string + ' - ' + repo.homepage + '' except AttributeError: pass repo_string = repo_string + '

' repo_string = repo_string + "Forks: " + str( repo.forks ) + " - Watchers: " + str( repo.watchers ) + ' | ' if repo.has_issues: repo_string = repo_string + ' Issues |' if repo.has_wiki: repo_string = repo_string + ' Wiki |' if repo.has_downloads: repo_string = repo_string + ' Downloads |' repo_string = repo_string + '
Last Push: ' + datetime.fromtimestamp( repo_date_to_epoch( repo.pushed_at ) ).ctime() try: repo_string = repo_string + '
' + repo.description + '< /pre>'
    except AttributeError:
      repo_string = repo_string + '

' pass repo_string = repo_string + "
\n" template = template.replace( '<% repos %>', repo_string ) ga = """ """ if False != settings['google_analytics']: template = template.replace( '<% google_analytics %>', ga ) template = template.replace( '<% ga_code %>', settings['google_analytics'] ) else: template = template.replace( '<% google_analytics %>', '' ) print "Writing file..." f = open( 'index.html', 'w' ) f.write( template ) f.close() print "Done!" if __name__ == "__main__": main()

Wow. You actually scrolled through all of that. Amazing.

Thursday Quote: Harold Ableson

June 24, 2010 » Geek

“Computer Science is a terrible name for this business. First of all it’s not a science. It might be engineering or it might be art.”

– Harold Ableson
EE & CS Professor at MIT
Overview and Introduction to Lisp

MongoDB + node.js On WebFaction

June 18, 2010 » Geek

Following a suggestion from Kloanor on a Hacker News article I got a WebFaction account to play around with node.js on.

tl;dr It’s not too hard to set up.

Getting Ready

All of this software will be installed in my home directory, so there are a few things we need to do. First, I created a sources directory so that I would have my hands on exact copies of the installed software in the future, as well as a clean place to unpack and build them.

[[email protected] ~]$ mkdir sources
[[email protected] ~]$

Second, we need to create two custom applications for MongoDB and node.js using the WebFaction control panel.

This is pretty easy, just go to “Domains/Websites > Applications > Add New“. Now give it a name (I used mongodb_master) and select “Custom app (listening on port)” as the App Type.

Creating The Custom Application

Hit create and write down the port number it provides. Do this again for node.js. You can also take a moment to map these applications to a website and domain.

The Custom Applications


MongoDB is actually supported to some extent, with install instructions provided in the WebFaction Doc’s. I did this slightly different, so I’ll detail my version here.

Acquiring MongoDB

You can get MongoDB at You’ll need the 32-Bit Linux version. At the time of this writing the most current stable release was 1.4.3.

[[email protected] ~]$ cd sources
[[email protected] sources]$ wget
--2010-06-18 18:43:29--
Connecting to||:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 23709740 (23M) [application/x-tar]
Saving to: “mongodb-linux-i686-1.4.3.tgz”

100%[==============>] 23,709,740   202K/s   in 1m 55s

2010-06-18 18:45:29 (201 KB/s) - “mongodb-linux-i686-1.4.3.tgz” saved [23709740/23709740]

[[email protected] sources]$

Installing MongoDB

MongoDB comes pre-compiled, so installing it is as easy as unpacking and moving some directories.

[[email protected] sources]$ tar -zxf mongodb-linux-i686-1.4.3.tgz
[[email protected] sources]$ cd mongodb-linux-i686-1.4.3/
[[email protected] mongodb-linux-i686-1.4.3]$ ls
bin  GNU-AGPL-3.0  include  lib  README  THIRD-PARTY-NOTICES
[[email protected] mongodb-linux-i686-1.4.3]$ mv bin ~/
[[email protected] mongodb-linux-i686-1.4.3]$ mv lib ~/
[[email protected] mongodb-linux-i686-1.4.3]$ mv include ~/

Configuring MongoDB

In this case, MongoDB is configured at run time. But it will need a data directory. I chose to put this at ~/var/mongo/master/. You don’t have to do anything special, just make sure the directory exists, and is empty.

That’s it! MongoDB is installed. We’ll come back and fire it up after we get node.js installed.

Installing node.js

node.js is almost as easy as MongoDB. And while not documented anywhere, it does run just fine. The major point of contact here is a forum topic that details how to get it running. Again, I’m going to deviate a bit, but I’ll end up in roughly the same place.

Acquiring node.js

You can get node.js at It’s distributed as source, so there is nothing to pick and choose from. At the time of this writing the most current version was 0.1.98.

[[email protected] ~]$ cd sources
[[email protected] sources]$ wget
--2010-06-18 18:57:14--
Connecting to||:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3770749 (3.6M) [application/octet-stream]
Saving to: “node-v0.1.98.tar.gz”

100%[===========>] 3,770,749    151K/s   in 25s

2010-06-18 18:57:39 (147 KB/s) - “node-v0.1.98.tar.gz” saved [3770749/3770749]

[[email protected] sources]$

Easier done than said.

Installing node.js

You have to compile node.js, but this went perfectly clean for me. Just make sure you set the prefix when you configure, or you’ll have to do it all again.

[[email protected] sources]$ tar -zxf node-v0.1.98.tar.gz
[[email protected] sources]$ cd node-v0.1.98/
[[email protected] node-v0.1.98]$ ./configure --prefix=$HOME
Checking for program g++ or c++          : /usr/bin/g++                                                            
Checking for fdatasync(2) with c++       : yes
'configure' finished successfully (5.495s)
[[email protected] node-v0.1.98]$ make
Waf: Entering directory `/home/littlef/sources/node-v0.1.98/build'                                                         
DEST_OS: linux                                                                                                     
Waf: Leaving directory `/home/littlef/sources/node-v0.1.98/build'
'build' finished successfully (5m33.731s)
[[email protected] node-v0.1.98]$ make install

Configuring node.js

Nothing to configure! It should be ready, like, right now.

Running Your New Software

Okay, everything is installed. Let’s get stuff running.

Running MongoDB

Running MongoDB should only take two options. --dbpath and --port.

Go ahead and fire it up, then shut it down with ctrl-c.

[[email protected] ~]$ mongod --dbpath ~/var/mongo/master/ --port 39381
Fri Jun 18 19:11:24 Mongo DB : starting : pid = 3293 port = 39361 dbpath = ~/var/mongo/master master = 0 slave = 0  32-bit

** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see for more

Fri Jun 18 11:11:24 db version v1.2.2, pdfile version 4.5
Fri Jun 18 11:11:24 git version: nogitversion
Fri Jun 18 11:11:24 sys info: Linux biber 2.6.26-2-amd64 #1 SMP Thu Feb 11 00:59:32 UTC 2010 i686 BOOST_LIB_VERSION=1_40
Fri Jun 18 11:11:24 waiting for connections on port 39361
^CFri Jun 18 11:11:27 got kill or ctrl c signal 2 (Interrupt), will terminate after current cmd ends
Fri Jun 18 11:11:27 now exiting
Fri Jun 18 11:11:27  dbexit:
Fri Jun 18 11:11:27      shutdown: going to flush oplog...
Fri Jun 18 11:11:27      shutdown: going to close sockets...
Fri Jun 18 11:11:27      shutdown: waiting for fs...
Fri Jun 18 11:11:27      shutdown: closing all files...
Fri Jun 18 11:11:27      closeAllFiles() finished
Fri Jun 18 11:11:27      shutdown: removing fs lock...
Fri Jun 18 11:11:27  dbexit: really exiting now
[[email protected] ~]

That’s great, but we can’t just stay logged in to SSH all the time. Let’s nohup it, background it and forget about it.

[[email protected] ~]$ nohup mongod --dbpath ~/var/mongo/master/ --port 39381 &
[1] 3299
nohup: ignoring input and appending output to `nohup.out
[[email protected] ~]$

Now we can query it by setting the port on mongo

[[email protected] ~]$ mongo --port 39381 noderegator
MongoDB shell version: 1.2.2
url: noderegator
connecting to:
type "exit" to exit
type "help" for help
> show collections
> exit
[[email protected] ~]$ 

Running node.js

Before we can actually run node.js, we need to write a little application. In my case this will go in ~/webapps/noderegator_nodejs/app.js. Place yours wherever you set up your custom application for node.

Be sure to change the port number to the one issued to your application by WebFaction.

var http = require( 'http' ),
     sys = require( 'sys' );

  function( request, response ) {
    sys.puts( 'Request!' );
    response.writeHead( 200, { 'Content-Type': 'text/plain' } );
    response.end( 'Hello World\n');
).listen( 35408 );
sys.puts( 'Server running on port 35408' );

Now let’s fire that up and see it in the browser. ctrl-c to quit.

[[email protected] ~]$ cd webapps/noderegator_nodejs/
[[email protected] noderegator_nodejs]$ node app.js
Server running on port 35408
[[email protected] noderegator_nodejs]$ 

If you got an nginx 503 error when you tried to visit the site, check that your port numbers are set up correctly.

All Done

That’s it, that’s all you need to know. Enjoy MongoDB and node.js on WebFaction. I hope it all goes well for you.

Forking TACO 2.0

June 17, 2010 » Geek

Update (2010-06-30)

Abine has posted their own view of the events, which I would recommend as a follow up read to this post. I sort of agree with what they say there, but don’t take this as an endorsement.

The link is at the bottom of this post.

A few days ago my Firefox updated an extension that has been a useful favorite for quite a while, TACO. What I saw when it was finished surprised me and made me upset.

What The What?!

You see, TACO has always been a quiet, understated background application. It sits there, humming softly in the dark keeping my advertising opt-out cookies up to date. It has no UI, it has no configuration, it just works.

This new TACO though, was flashy, shiny and filled with buttons and features. It even had a built in app store!

I Kid You Not

I freaked out, I moved quickly and I removed TACO 3.0. I checked the page on and found that others were not happy with the new TACO either. It had become a commercial affair by the folks at Abine. More on them later.

So what’s a geek to do? Why, fork it of course. I hopped online and grabbed TACO 2.0, unpacked it and took a look. This classic version didn’t have much to it, and what’s more it was licensed under the Apache 2.0 License. Fork’s Away!

I quickly set up my git repo, made some slight changes and let people know about my new Beef Taco in a review on the old TACO 2.0 page.

“Beef Taco”, Get It?

There, crisis averted. I have a new project to keep track of, but maybe this will help out anyone else who cringes at 3.0.

Later that evening I got an email from Rob Shavell, one of the founders of Abine. I expected an uncomfortable reply from Abine, if they noticed me at all, but Rob was totally cool. He even got my joke with the name of the new extension.

Hello. I have to compliment you on the beef taco name. I’m personally apologizing for our upgrade that you, judging by your actions, didn’t want / need. Even though we’re trying to offer the same type of downgrade, I’m sure a lot of users will appreciate your fork.

That’s pretty neat, and they are okay with my fork. I suppose maybe I can take some of the support load off of them, so that the paranoids like me will leave them alone.

But it gets better, we traded a few more emails talking about my fork, the new direction of 3.0 and the reaction in general, when he sent me this gem.

4. we’ll send you all new opt-outs we add so you can easily stay in sync..

Are you kidding me? You’re going to help my fork? That is awesome. At that moment Abine won my trust back, completely. These guys seem to really be trying to do something with their startup, but they also care about privacy in general.

Sure enough, I had a list of new opt-out cookies in about an hour. That is how you show you care about your users.

I went back and took another look at 3.0, and while it doesn’t appeal to me as a proficient user, there are a lot of features in there that are pretty cool, and you can tell they put a lot of work into it.

Stuff like telling me how many data breach incidents an advertiser has had, or the sort of “complete threat panel” thing. That’s some cool stuff.

Back Off Microsoft!

Detailed Privacy Panel – Pretty Cool

I think that TACO 3.0 is only going to get better, and is going to have real appeal to novice users.

Who knows, it may even be pressed back into service in my browser someday. Until then, I’ll maintain Beef Taco, with a little less beef now then before.

Some Links For You