Zen and the Art of Motorcycle Maintenance

In my final year of college, I took several photography classes that shaped my views on quality. My instructor, Kenneth Barrett, taught students not only about the typical photography concepts you'd expect, but also about composition and style. We studied famous black and white photographs and I fell in love with artists like Diane Arbus. Her photographs felt harsh, sometimes sadistic and even exploitative.

I first began shooting on a 1973 Mamiya/Sekor 1000 DTL my father gave me. It was the world's first camera with dual-pattern through-the-lens (TTL) metering. It was bulky, difficult to hold and completely unforgiving. It took patience loading the 35mm film. Developing the film was even more laborious. 30 seconds in the stop bath, 4 minutes in a fixer, 30 seconds in a rinse, 2 minutes in a clearing agent and so on. It was easy to screw up and I did on numerous occasions.

The more advanced I became shooting 35mm, the more I appreciated the restrictiveness of the format. The beauty of it wasn't about the camera's constraints, rather what it forced you to focus on. You had 36 chances to take a beautiful photograph.

Years later after graduating, the darkroom was converted to a digital photo studio. Kenneth Barrett no longer teaches there. Today, I take pictures on my iPhone and post them on Instagram. It takes seconds. I apply filters to emulate quality that would, in real life, sometimes take hours to create. I'm reminded of a quote from one of my favorite books by Robert Pirsig's, Zen and the Art of Motorcycle Maintenance:

"It's the style that gets you; technological ugliness syruped over with romantic phoniness in an effort to produce beauty and profit by people who, though stylish, don't know where to start because no one has ever told them there's such a thing as quality in this world and it's real, not style. Quality isn't something you lay on top of subjects and objects like tinsel on a Christmas tree. Real quality must be the source of the subjects and objects, the cone from which the tree must start."

Support Ops Podcast

Last week, I had the pleasure of joining (mt) chief correspondent, Sara Carter, on the Support Ops podcast. Support Ops is all about customer support. More specifically, bringing humanity to customer support. We had a fantastic time and I can't thank Chase Clemons enough for having us on the show.

Chase, who runs the Support Ops blog and podcast, is extremely passionate about providing great customer experiences. He currently works at 37signals, a company I've always admired. I first came across his work through UserConf 2012, a customer service conference about keeping your customers happy. You can watch his talk -- "Try New Stuff" -- right here:

Generating Passwords with node.js

For a few years now, I've been using the same silly random password generator from a coworker of mine. Since I use 1Password for password management, I'm frequently creating new random passwords. While a feature exists within 1Password for generating new passwords, I usually find comfort in doing this from Terminal. When my coworker's server was down for a few days, I temporarily reverted to some bash-foo:

date +%s | sha256sum | base64 | head -c 13 ; echo
tr -cd '[:alnum:]' < /dev/urandom | fold -w13 | head -n1
< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c 13 ; echo

While these examples are super handy, I wanted to use this as an opportunity to play around with node.js. This simple utility can generate 13 character random passwords using 2 node modules, express and request. Here is the meat of it:

var express, http, make_passwd;

express = require('express');

http = express();
http.use(express.logger());

make_passwd = function(n, a) {
  var index = (Math.random() * (a.length - 1)).toFixed(0);
  return n > 0 ? a[index] + make_passwd(n - 1, a) : '';
};

http.get('/', function(request, response) {
  var password;

  password = make_passwd(13, 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890');

  response.type('text/plain');
  response.send(password);
});

http.listen(process.env.PORT);

I've published a working version to Heroku. You can find the full repository on GitHub. Give it a shot:

curl –s http://passwd.tjstein.com 2>/dev/null | pbcopy

Speaking at Social Brand Forum 2012

On October 17-18, I'll be giving a talk at Social Brand Forum 2012, Iowa’s premier social media marketing event. The session is centered around how businesses can successfully manage a crisis with social media, focusing on the impact of customer relationships and brand reputation. I'm thrilled to be part of such a great event.

Social Brand Forum 2012 brings national-level social media content to the Eastern Iowa Creative Corridor for a day and half of keynotes, panel discussions, and interactive sessions. Featuring speakers, authors, and thought leaders from the national stage, the event is designed to help marketers at organizations small and large build stronger brands through social media content, conversations, and community.

Running WordPress on Heroku + Amazon RDS

With the announcement of the Heroku and Facebook partnership yesterday, Heroku quietly confirmed support for two new languages, Python and PHP. The self-proclaimed polyglot platform, Heroku's Celadon Cedar Stack now has a considerable advantage over newcomers like PHP Fog, and Orchestra.io by avoiding mostly separate, language-specific products.

To test out Heroku's PHP support (version 5.3.6), I deployed WordPress. One of the current limitations is the lack of native MySQL support, outside of hooking into the Xeround Cloud DB or Amazon RDS. I've found one blog post that suggested using the default PostgreSQL backend that Heroku provides with the 'PG4WP' WordPress plugin, enabling WordPress to be used with a PostgreSQL database. While this may work, it lacks most plugin support and is more of a bandaid for the platform limitations. Instead, you can use Amazon's Relational Database Service (RDS) addon.

Amazon RDS is a service that allows you to set up, operate and scale a dedicated MySQL database server on top of EC2. In addition to standard MySQL features, RDS offers the following functionality:

  • Automated backups
  • Point-in-time recovery
  • Seamless vertical scaling between instance types

The free Amazon RDS add-on lets you connect your Heroku app to an RDS instance and seamlessly use it in place of the standard, Heroku-provided PostgreSQL database. To get started, you should configure the RDS command line toolkit and Heroku gem if you haven't already. Let's start by creating the RDS database instance on your local machine:

rds-create-db-instance --db-instance-identifier [name]\
  --allocated-storage 5 \
  --db-instance-class db.m1.small  \
  --engine MySQL5.1 \
  --master-username [user] \
  --master-user-password [pw] \
  --db-name [name] \
  --headers

This will take a few minutes. Once the database is provisioned, add your local IP address to the security group -- assuming your workstation’s public IP is 1.1.1.1:

rds-authorize-db-security-group-ingress default --cidr-ip 1.1.1.1/32

Heroku also needs to be able to access your RDS instance. To allow Heroku’s cloud through the RDS firewall, run the following command:

rds-authorize-db-security-group-ingress default \
    --ec2-security-group-name default \
    --ec2-security-group-owner-id 098166147350

Now we can begin building the application layer. Since we're going to be using Git for version control, I'd suggest cloning WordPress from the GitHub repository; it is synced from Automattic's SVN repository every 15 minutes, including branches and tags:

git clone git://github.com/WordPress/WordPress.git
cd WordPress

Before we start making any changes to file structure, we should make our own Git repository and start committing. Note here that you'll want to populate the wp-config.php with the MySQL credentials from the rds-create-db-instance command above:

git init
mv wp-config-sample.php wp-config.php
git add .
git commit -m 'initial commit'

Now, create the stack and enable the RDS addon with your MySQL credentials. Once the stack has been created, you can deploy:

heroku create --stack cedar
heroku addons:add amazon_rds url=mysql://user:pass@rdshostname.amazonaws.com/databasename
git push heroku master

The output should look something like this:

➜ wp-heroku-test git:(master) git push heroku master
Counting objects: 985, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (965/965), done.
Writing objects: 100% (985/985), 3.65 MiB | 221 KiB/s, done.
Total 985 (delta 66), reused 0 (delta 0)

-----> Heroku receiving push
-----> PHP app detected
-----> Bundling Apache v2.2.19
-----> Bundling PHP v5.3.6
-----> Discovering process types
       Procfile declares types -> (none)
       Default types for PHP   -> web
-----> Compiled slug size is 24.9MB
-----> Launching... done, v4
       http://evening-waterfall-3372.herokuapp.com deployed to Heroku

To git@heroku.com:evening-waterfall-3977.git
 * [new branch]      master -> master

Notes

  • A commenter on HackerNews noted that the slug is still read-only, but the ephemeral filesystem is writable. The slug is what gets deployed on each new dyno spawned. The ephemeral filesystem is the individual file system on each dyno. So a plugin like WP Super Cache would be able to write to the file system, but that cache would only exist for the individual dyno that wrote it.

  • Because of the usage concerns of media and content uploads, I'd suggest using a CDN or Amazon S3 for storing images and attachments.

  • The zlib extension for PHP is not compiled on the Celadon Cedar Stack. Theme and plugin uploads through the WordPress admin panel will fail. To get around this, set up your themes and plugins on your local workstation first, commit and deploy.

  • Do not include a phpinfo page in the document root as it will contain your database credentials in plain text.

  • If you want to have pretty permalinks, create the .htaccess file on your local machine and populate the mod_rewrite rules prior to deploying.