Welcome to my blog!
Hello! My name is Ryan Tucker, and you’ve found my awesome blog. If you’re new here, feel free to read more about me…
Conditional redirection with lighttpd: evolving my webtmp folder
Very often, I need to quickly host a file for use in a forum post or on IRC. My usual approach has been to mount a "temporary" directory from my web server on my desktop, over ssh. However, I recently started using Dropbox to keep my important files synced: with this, I can access my school work from school without having to resort to ssh heroics or remembering to carry a flash drive with me (let's not get started on keeping it synchronized). Dropbox offers 2GB of storage for free, and they include a handy Public folder you can use to share files. Nice.
My little temporary directory, in practice, isn't very temporary. I rarely delete anything from it; indeed, the oldest image is nearing two years old. I also keep throughput test files there, and I kinda need those to be on my server. However, I hate remembering multiple long URLs, especially ones like http://www.hoopycat.com/~rtucker/tmp/moooar.PNG and http://dl.dropbox.com/u/3597105/system-fullpower.png. I also want to be able to transparently move files around as my needs change. And, most importantly, I want my stuff under the hoopycat.com domain for maximum flexibility.
So, I set up a dedicated hostname: http://drop.hoopycat.com/.
Here's the flow:
- A request is received for
http://drop.hoopycat.com/filename. (Note: requests for/get redirected tohttp://hoopycat.com/). - If filename exists in
~rtucker/public_html/tmp, serve it up. - If it doesn't, issue a HTTP redirect to
http://dl.dropbox.com/u/3597105/filename.
Easy enough, and it works darn well. I do no checks for the file's existence on Dropbox, so their 404 page gets served up for totally bogus URLs. This is not a big deal in practice.
The configuration of lighttpd is simple, using mod_magnet and a small Lua script. To lighttpd.conf or a conf-available/ file of your choice, add:
Code:
server.modules += ( "mod_magnet" ) | |
| |
$HTTP["host"] == "drop.hoopycat.com" { | |
server.document-root = "/home/rtucker/public_html/tmp/" | |
url.redirect += ( "^/$" => "http://hoopycat.com/" ) | |
magnet.attract-physical-path-to = ( "/etc/lighttpd/conditional-redirect.lua" ) | |
} |
Then, create /etc/lighttpd/conditional-redirect.lua with the following script, borrowed from an example at http://redmine.lighttpd.net/projects/lighttpd/wiki/AbsoLUAtion:
Code:
local filename = lighty.env["physical.path"] | |
local stat = lighty.stat( filename ) | |
if not stat then | |
local static_name = string.match( filename, "tmp/([^/]+)$" ) | |
lighty.header["Location"] = "http://dl.dropbox.com/u/3597105/" .. static_name | |
return 302 | |
end |
Remember to replace the dl.dropbox.com URL with yours (and change everything else, too).
Assuming DNS is set up correctly and mod_magnet is installed (it's lighttpd-mod-magnet in Ubuntu 8.04), a restart of lighttpd should yield good results!
A backported whois client for Ubuntu 8.04 LTS (Hardy)
I still run Ubuntu Hardy (8.04 LTS) on servers, since I'm willing to trade some newer features for package stability. Alas, once in awhile, this stability becomes a problem: the standard whois client uses a set of compiled-in mappings to determine how to route whois queries, and this falls out of date surprisingly fast:
Code:
$ whois 109.74.207.9 | |
Unknown AS number or IP network. Please upgrade this program. |
I've opened a Launchpad bug with the hopes that this gets SRU'd at some point, but I'm not confident enough in my packaging abilities to go forward with this myself (yet). So, at least in the interim, I've created a Personal Package Archive with whois 4.7.36, backported from the Lucid Lynx (10.04) repo. If you're interested in this, you can configure your system to use it in place of the normal whois:
- Add the repository to your
/etc/apt/sources.list:
Code:
deb http://ppa.launchpad.net/rtucker/whois-delegation-backport/ubuntu hardy main | |
deb-src http://ppa.launchpad.net/rtucker/whois-delegation-backport/ubuntu hardy main |
- Add the public key to your apt keyring:
Code:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15B7BC85 |
- Run
sudo apt-get updateandsudo apt-get upgrade!
You can find more information and instructions at the Launchpad page for this PPA: https://launchpad.net/~rtucker/+archive/whois-delegation-backport. Also, be aware that, in the (unlikely) event of a security problem in the whois package, it may not get fixed in a timely manner if you're using this PPA. You have been warned.
Enjoy!
The Dehumidifier Always Tweets Twice: Recent dehumidifier news
I can tell you're delighted to hear of the state of dehumidification in the basement. Winter is here, which is known for being bone dry. Thus, the dehumidifier's going to be taking it easy much of the winter, but it will still be ready to act when snow thaws and the basement gets damp!
The dehumidifier has every right to take it easy, now that it has taken the blogosphere by storm! Yes, the About Dehumidifiers blog wrote about our humble dehumidifier today, specifically with regards its Twitter support. Very cool.
In software news, the blog widget (on the right edge of this page) and the !d command on the Linode IRC channel now include a rough estimate of how much time is left on the tank. This is not an exact science, but the estimates will probably improve in the spring. I've also been playing with the capacitance-to-percentage conversion code. Anything to liven it up, I suppose.
Oh, and those random characters after the Twitter updates? Twitter started filtering duplicate status texts a little while back, resulting in no updates going through for awhile. Adding random text was a quick, 15-second fix, but it has worked well so far. Maybe I'll do something else in the future...
Revisited: Asterisk and FreePBX under Ubuntu 9.10 and Lighttpd on a Linode VPS
I originally wrote this howto for Ubuntu 9.04 (Jaunty) a few months before Ubuntu 9.10 (Karmic) was released. I happen to have a spare system lying around right now, so I figure I might as well update this for 9.10!
Summary of major changes since the 9.04 document
- Kernel package: It appears
linux-image-serverno longer installs a Xen-aware kernel, so I now uselinux-image-ec2. - Zaptel replaced with DAHDI: Digium replaced Zaptel with DAHDI for Asterisk 1.6, which now ships with Ubuntu. This requires a change in package names, in addition to the usual changes one would expect between 1.4 and 1.6.
- More links to the Linode Library: Since I wrote the original post in August, Linode has really fleshed out their documentation. I've harmonized some of the "opening moves" with their getting-started documentation to reduce confusion.
- Now using upstart for spawning the FastCGI handlers: I figured there was a less cheesy way to do that.
Some concerns
I'm occasionally seeing the boot process locking up for awhile with nasty-looking kernel bug errors:
Code:
[ 66.572527] BUG: soft lockup - CPU#1 stuck for 61s! [invoke-rc.d:1215] | |
[ 132.080097] BUG: soft lockup - CPU#1 stuck for 61s! [invoke-rc.d:1215] | |
[ 197.578163] BUG: soft lockup - CPU#1 stuck for 61s! [invoke-rc.d:1215] | |
[ 263.072534] BUG: soft lockup - CPU#1 stuck for 61s! [invoke-rc.d:1215] |
It eventually seems to pull out of it, but you might not want to do this on your production box until you're sure everything is happy and keen. If anyone knows anything about these errors, let me know. That said, I've been on a conference bridge with myself for the past ten minutes and everything's fine.
Without further adieu, here's the howto!
Rationale
FreePBX is a popular PHP front end for the Asterisk PBX system. It morphs the complex yet very flexible Asterisk configuration into something easier to use (yet still very extensible). When I worked for a business-class VoIP provider back in the day, we used FreePBX (and its predecessor, AMP) for most of our customer-premise PBX servers.
I prefer configuring and managing my Asterisk system using FreePBX. However, I can't justify an entire server for Asterisk, so I need it to coexist with a number of other applications. What I can justify is a VPS with relatively little memory, so some tuning is required.
The usual installation instructions assume the use of CentOS, Apache and mod_php for the stack. There are a few downsides to this configuration.
Keep track of configuration changes using etckeeper
I do stupid things sometimes.
On a Linux system (and most other Unix-like systems), the /etc directory holds most of the fundamental system configuration files. Within its hierarchy lies a number of very important nuggets:
/etc/passwdand its clandestine friend/etc/shadow: Usernames, passwords, and home directories for all local users./etc/resolv.conf: Nameservers for resolving hostnames./etc/sudoers: The list of users who may use thesudocommand to temporarily assume root privileges./etc/network/interfaceson Debian-derived systems or/etc/sysconfig/network-scriptson RedHat-derived systems: Network configuration, such as IP addresses and interfaces.
... and much, much, MUCH more.
As you can imagine, there's a lot of room for mistakes here. Whether you're adjusting network configuration slightly, configuring your web server, or adding/removing users, there's a good chance you'll regret it later on. It happens to everyone, usually at a very inconvenient time following a supposedly-"quick" reboot.
You can't avoid mistakes, but you can make it easier to find and fix them when they emerge. If you're familiar with revision control, you understand a couple key goals: you should be able to determine what change was made, when it was made, and by whom. This is where etckeeper comes in.
Ideally, you should just be able to fire up git, svn, or what-have-you on your /etc and be done with it. However, as etckeeper's Joey Hess points out, revision control systems tend to ignore empty directories, file permissions, and other things endemic to the /etc landscape:
So instead I followed the lead of these blogs combined with David Härdeman's metastore for solving the metadata storage problem. I also hacked in a solution to the empty directory storage problem, and a few other issues with trying to use git for this thing that it was not really designed for.
He also added a killer feature to etckeeper: automatic commits before and after apt-get and aptitude runs. This means you can see exactly what installing or removing a package did to your /etc, as well as which packages were added or removed. Very awesome.
Installing etckeeper on Ubuntu
It's pretty simple. For this installation, I'll be using a freshly-deployed virtual server. etckeeper is the first thing I'm installing, but you can install it on a mature system, of course.
- Server: Linode 360 Xen-based virtual private server
- Distribution: Ubuntu 9.10, 32-bit
First, since this is a brand-new system, I edit /etc/apt/sources.list to enable the universe repositories, by uncommenting the relevant lines:
I then run apt-get update to pull in up-to-date package lists, and apt-get upgrade to apply any updates.
That's the hard part. Now, let's install etckeeper and its friend git-core:
Code:
root@localhost:~# apt-get install etckeeper git-core | |
(apt-get does its thing) | |
... | |
added vim/vimrc | |
added vim/vimrc.tiny | |
added xml/catalog | |
added xml/catalog.old | |
added xml/xml-core.xml | |
added xml/xml-core.xml.old | |
Committed revision 1. | |
| |
Processing triggers for libc-bin ... | |
ldconfig deferred processing now taking place | |
root@localhost:~# |
By default, this uses the Bazaar revision control system. If you're OK with bzr, then by all means use it. However, I use git for everything else, so I prefer to use it with etckeeper.
To change to git, you'll first want to remove the existing stuff using etckeeper uninit:
Code:
root@localhost:~# etckeeper uninit | |
** Warning: This will DESTROY all recorded history for /etc, | |
** including the bzr repository and ignore file. | |
| |
Are you sure you want to do this? [yN] y | |
Proceeding.. |
Then, edit the top of /etc/etckeeper/etckeeper.conf to comment out the bzr line and uncomment the git line:
Code:
# The VCS to use. | |
# VCS="hg" | |
VCS="git" | |
# VCS="bzr" | |
# VCS="darcs" |
Then, reinitialize etckeeper with etckeeper init, and do your first commit with etckeeper commit:
Code:
root@localhost:~# etckeeper init | |
Initialized empty Git repository in /etc/.git/ | |
root@localhost:~# etckeeper commit 'initial commit' | |
... | |
create mode 100644 wgetrc | |
create mode 100644 xml/catalog | |
create mode 100644 xml/catalog.old | |
create mode 100644 xml/xml-core.xml | |
create mode 100644 xml/xml-core.xml.old | |
root@localhost:~# |
Using etckeeper
To be adequately used, anything like etckeeper must be simple and easy to use. Fortunately, it is. You just have to remember one thing:
etckeeper commit
Let's make a simple change and show how it's done. Perhaps we'll add a regrettable typo somewhere:
Code:
root@localhost:~# echo halt >> /etc/rc.local |
We're done with this edit, so let's commit it into etckeeper. By the way, you can either specify a brief commit message on the command line, or it will fire up an editor to let you enter a longer log message.
Code:
root@localhost:~# etckeeper commit 'enabling alternate h in rc.local' | |
[master 5c403d3] enabling alternate h in rc.local | |
1 files changed, 1 insertions(+), 0 deletions(-) |
We can now use normal git tools to examine this revision!
Code:
root@localhost:~# cd /etc | |
root@localhost:/etc# git log | |
commit 5c403d3e74c24a6f0bce5abe70f0bfac65c8d837 | |
Author: root <root@localhost.(none)> | |
Date: Sun Dec 6 16:23:08 2009 +0000 | |
| |
enabling alternate h in rc.local | |
| |
commit e5c3218de86f0cc2e477cbf960d381c8fcdbd8fe | |
Author: root <root@localhost.(none)> | |
Date: Sun Dec 6 16:19:50 2009 +0000 | |
| |
initial commit | |
root@localhost:/etc# git diff e5c3218 5c403d3 | |
diff --git a/rc.local b/rc.local | |
index 65634df..cd0acfd 100755 | |
--- a/rc.local | |
+++ b/rc.local | |
@@ -12,3 +12,4 @@ | |
# By default this script does nothing. | |
| |
exit 0 | |
+halt |
Reverting bad changes
And yes, you can use gitk and git bisect and git push and whatever the heck else you want to use. That's the point. Even more importantly, since this edit was clearly a serious mistake (two of them, actually), we can toast it:
Code:
root@localhost:/etc# git revert 5c403d3 | |
Finished one revert. | |
[master 2a973c7] Revert "enabling alternate h in rc.local" | |
1 files changed, 0 insertions(+), 1 deletions(-) | |
root@localhost:/etc# git status | |
# On branch master | |
nothing to commit (working directory clean) | |
root@localhost:/etc# tail -2 rc.local | |
| |
exit 0 |
Further things to explore
- etckeeper will, by default, run before and after each apt run. If you'd rather it not run before, you can affect this behavior in
/etc/etckeeper/etckeeper.conf. - It will also do a daily autocommit of any changes in
/etc. You can turn this off in/etc/etckeeper/etckeeper.confas well. If you do, it might be a good idea to run something that checks for uncommitted changes nightly, e-mailing you if you've been lazy. - You probably don't want to push your
/etcto a public git repository.
I'd like to give props to Yaakov for introducing me to etckeeper. I believe it's an effective and easy way to keep yourself sane, even on single-administrator systems. I don't know how I survived working on systems with multiple administrators and no revision control, but I'd rather not do so again.
Team of RIT engineering students wins IEEE Student Design Contest
![Shall we play a game? [Photo of the handheld game]](http://edge.rit.edu/content/P09003/public/187.jpg)
Kudos to a team of engineering students from RIT not only for placing first in the 9th Annual Student Design Contest, but for doing it with a senior design project of considerable awesomeness:
The goal of this project is to create a custom handheld game for Luke, a nine-year-old child with severe visual limitations. To accommodate this limitation, the handheld was designed to engage multiple senses with a lower emphasis on visual interpretation. It is expected that this handheld will provide educational and physical benefits. The lower emphasis on visual cues will help Luke to develop other senses such as touch and hearing. Although visual cues are not a primary focus they are included, this will provide a common activity in which all children can enjoy and will facilitate Luke to interact with his peers while providing entertaining and educational benefits. [link]
The contest was held in May, but RIT’s PR department did not issue a press release until mid-October. Today, the Rochester Democrat and Chronicle published an article focusing on why the team chose this project:
The idea of a game for Luke started about 3½ years ago with his pediatrician, Dr. Julie Lenhard of Perinton. Lenhard noticed that when Luke and his brother came to her office for checkups, Jack could look at books and magazines or draw pictures while sitting in the waiting room. But because of his vision problem, Luke had nothing similar to do. “I thought, wouldn’t it be great if Luke had a (Nintendo) Game Boy sort of toy that was suited for him, that he could play with quietly in the many various situations when the adults were boring and talking and he had nothing to do,” Lenhard said.
![That's a P8X32A-Q44, per the schematic [Photo of inside of handheld game]](http://edge.rit.edu/content/P09003/public/229.jpg)
The device itself is based on the Parallax Propeller P8X32A, a 32-bit multicore microcontroller optimized for high-performance embedded applications. More information on the architecture and design process, as well as schematics and source code, is available on the project’s web site.
Certainly, designing and building a project that actually makes a difference in someone’s life is a rarity for undergrads. Over the summer, my wife worked on the modernization project at Brooks Hill Elementary (where Luke’s parents teach, and presumably where he goes to school), and she reports he’s the sweetest little kid in the world1, which makes it all the more awesome.
——
1 With apologies to everyone else whose little kid is the sweetest in the world.
Self-intervention: Charity address labels
I rummaged through our mailing-supplies drawer this morning, hoping to find more postage. In the process, I discovered my charity address label collection loomed a little larger than I remember. This evening, I decided to see what all's in there.
Needless to say, it is mammoth. I appear to have been hoarding these things for many years. All have the right address, but there's just a ludicrous quantity of them.
Here is the pile:
- 11 marine-themed labels from the American Diabetes Association (I've been using these lately; there used to be a lot more.)
- 55 bird-themed labels (and 6 general-purpose bird stickers) from the Audubon Society
- 90 shiny labels from Amnesty International
- 15 line-art cat and dog labels from Lollypop Farm
- 40 labels with nearly photo-realistic fruit from Feeding America
- 24 orange kitten labels from Lollypop Farm
- 24 labels featuring piles of gray kittens
- 36 kites, suns, giraffes, and cardinals from the Muscular Dystrophy Association
- 42 Christmas-themed labels from the March of Dimes (with 24 Christmas-themed stickers)
- 24 labels featuring hands feeding dogs and/or lifting kittens from Lollypop Farm
- 80 more nearly photo-realistic fruit from Feeding America
Total: 441 address labels.
Which should I keep? The orange kittens or the fruits? And no, there were no stamps in the pile. Drat.
Irons in the Fire
It's been awhile since I've updated this here blog. Fortunately, I have a plethora of wonderful excuses:
![]() | ![]() |
Working on school projects: For ELT201, I get to build a power amplifier (and pre-amplifier!). This is coming along nicely. Above left, you can see the power amp board. I assembled this at home in a marathon soldering session, and it shows. When in doubt, make it small. On the right is the pre-amp board, which is almost entirely surface-mount. This is being assembled in the lab, using a magnifying glass and a good soldering station.
![]() |
In ELT202, I'm working with two other students on a capstone project. My major hardware piece is the "middle" board: it accepts input from two other boards, and sends output to a bank of LEDs. There's also a 555-based clock there to flash menacingly if required. We still have to test everything together, merge all of our working schematics into a consolidated computer simulation, and work on a presentation.
![]() |
Working on spare-time projects: Way way way back in the day, I bought a Trimble SVee6-CM3 OEM GPS board. This is a rather dated unit: it takes a long time to acquire, it eats a lot of power, and it's somewhat large. However, I had it lying around and suddenly knew enough about electronics to do something with it. So I did. The first iteration was a breadboard special (pictured above) in support of a one-day special event. It worked pretty poorly, all things being equal. The next iteration -- just starting to undergo construction as we speak -- should be a wee bit better. There's no Tupperware involved yet, and I'm going to use a proper heat sink on the voltage regulator.
Writing: I have to write stuff too. I'm taking Advanced Composition, the "more strenuous" version of the ubiquitous college composition course. I am finding it remarkably challenging, and that's not a bad thing. Improving my reading, writing, and analysis skills can only be good. Alas, it sucks most of my available writing time.
Also worth noting: I've moved the Real-Time Photo postings over to my photo gallery, in the interest of keeping this blog a little more focused on textual text. The New and Updated Photographs RSS feed will keep you up-to-date with that stuff.
Political Content Advisory: Why I don't read political stuff in the morning
![Meanwhile, the College Republicans Club at MCC is facing dechartering. [Quasi-related clipart thumbnail]](http://photo.hoopycat.com/d/1827-2/0924091546.jpg)
From this week’s Bills Digest (the official publication of the Buffalo Bills), way back on the Bills Bits page, I bring you a report of former tight end Jay Riemersma’s candidacy for Congress. Note that I normally read the Bills Digest first thing in the morning, as I’ve found it’s all I can handle at 5:30am in the library.
It’s normally full of great inconsequential stuff, but this little tidbit caught me off-balance:
Riemersma is a Republican candidate running for the seat vacated by Rep. Peter Hoekstra, who is hoping to become Michigan’s next governor. “I’m announcing my candidacy because we need a Republican renaissance – a return to our conservative principles of governance – and I’m ready to help lead this movement,” Riemersma said in a release from his campaign.
At this point, I’m reading the article and thinking “Wow! That’s awesome. The Republican Party has really become derailed over the past few decades, and it’s about time someone stood up for the principles of Reagan and Goldwater.” Proponents of individual freedom and small government! Hooray! Perhaps we’ll finally have a choice other than the Democrats and the bat-shit-crazy-invisible-sky-creator people, with reasoned debate and realistic foundations!
A little tidbit about stats, teams played for, years active, receptions/yards/touchdowns, etc, etc, then:
Since retiring from the NFL, Riemersma has worked for the conservative Family Research Council and coached high school football.
Utoh. Oh crap. This isn’t going where I thought it was going. There’s another paragraph, and it starts with a quote. Oh no.
“Too many Christians shroud their God-given light with misguided intentions and uninformed choices,” Riemersma said in the statement. “Moving forward to the next election, I implore all Christians to base their vote not on a political party or a polished politician, but rather on Biblical principle.”
Blurrghrrffl.
Keeping life organized, one sheet at a time
As you might expect, I have a lot of stuff to keep track of in my life. From my househusbandly duties to my schoolwork, there’s a lot to do. Over the years, I’ve developed a good collection of systems to keep track of it all.
The most important of these is my integrated to-do list and calendar system, which allows me to keep track of what I have to do by a particular date (the “to-do list” part) as well as my appointments and classes (the “calendar” part). For the calendar element, I coordinate my schedule with my wife’s using Google Calendar. I access this via the web interface, as well as through a homebrew mobile-friendly CGI script that shows me a read-only view of a particular date via my cellphone. This is very handy for scheduling followup/return appointments while at the doctor’s or dentist’s office.
For the to-do list element, I use Hiveminder, a service I’ve mentioned in the past. This is a fully-featured to-do list manager with a very flexible API and many built-in input/output options. There are myriad ways for me to enter new tasks: e-mail, web, Twitter and Jabber are my most common. I can quickly add a new homework assignment or a reminder to myself from my cellphone by relaying the request through Twitter, or I can even snap a photo of something interesting and e-mail it to Hiveminder for later review.
Where these two meet the road is on a sheet of paper that I print daily using a custom application I call printcal. This produces a listing of all my calendar and to-do list items, organized by day, up to the maximum length of the paper. On a given day, I might get something like this:
Code:
Monday, September 21 (Day 264, week 38) | |
Partly cloudy, High 74, Low 61, (POP: 40%) | |
All day: Dawn needs car/dropped off at ________ | |
All day: DINNER: Grilled chicken breast, carrots, potatoes, salad, 8oz sirloin | |
11:00am-12:20pm ELT-201-100 (09-185) | |
1:00pm- 2:50pm ELT-202-105 (09-185) | |
4:00pm- 4:50pm MTH-210-010 (09-174) | |
normal priority: | |
* ELT202 Sign up to work freshman lab (sheet outside 9-185) (U23D) | |
* Make a lunch for tomorrow morning (U7OO) | |
low priority: | |
* Updates: arrogant-bastard (U9YY) | |
* Updates: framboise (U9YZ) |
Lines 1 and 2 tell me about the day: what day it is, and what the weather will probably be. Lines 3 through 7 comprise my personal calendar plus the family joint calendar, which generally includes the night’s dinner and anything that both of us need to know about. We can both view each other’s calendars as well, but this allows her to push things to my attention.
Lines 8 through 13 show what is due on my to-do list that day. In parentheses after each item is a unique code: when I am done with something, I can SMS “d hmtasks done a2c4” to Twitter and Hiveminder will mark it as done. This is, of course, done in conjunction with crossing the item out. I can also edit things (due e6g8 by next tuesday) remotely. This is sometimes a pain from my phone’s keypad, but it means I don’t have to remember to update my to-do list when I get home each night!
I originally started carrying my to-do list as a tri-folded sheet of paper, with one fold for each day. Each morning, I would copy the things I hadn’t crossed off from the previous day’s section to the new section. Carrying a sheet of paper around all the time took a bit of getting used to, but I rather liked the non-electronic nature of it. Plus, it trained me to carry a pencil around without accidentally running it through the wash.
Eventually, I started printing my calendar on the “back” of it, which added a decent amount of utility. Once that happened, I was a few short steps from better handling of my to-do list, since I had no way to put something on the “back burner", nor was I protected from accidental loss of the paper. I then found Hiveminder, and the rest is history.
Having the paper with me means there’s always some scratch paper in my pocket. This is great for doodling, writing quick notes to myself, or collaborating with someone in real-time in meatspace. Oftentimes, a trip to the pub for a couple drinks with my wife will fill up the back of the paper in short order. And you know what? If someone spills beer on my Personal Analog Assistant, I’m only out a couple cents!
:: Next >>
![And this is a newly-deployed system. I get the same feeling looking at a mature /etc as I do looking at the Hubble Deep Field. [screenshot of /etc]](http://blog.hoopycat.com/media/blogs/ryan/etc-screenshot.png)
![[screenshot of /etc/apt/sources.list being edited in vi]](http://blog.hoopycat.com/media/blogs/ryan/sources-list-enable-universe-ubuntu-9.10.png)



