Putting your .dot files in a repository

After 15 years of manually copying my dotfiles between my machines I finally decided it was time to put them in a repository.

GitHub has a good page explaining why you’d want to do this along with many links to different scripts. I settled on dotfiles because it seemed the simplest and at this point, I didn’t want too many moving parts.

Let’s imagine you have a single .vimrc file that you want to manage.

# Install dotfiles
pip install dotfiles
# Copy ~/.vimrc to ~/Dotfiles/vimrc and symlink ~/.vimrc to ~/Dotfiles/vimrc
dotfiles --add ~/.vimrc

At this point, you now want to manage your Dotfiles directory somehow. I’ve become partial to Bitbucket lately given that they let you have unlimited private repositories. Congratulations! You’re almost done.

On a new machine, clone your repostiory in to ~/Dotfiles and then run

dotfiles --sync

And that’s it! It makes me wonder why I didn’t do this years ago.


Bulk-queueing photo posts on Tumblr

Let’s suppose you have a folder full of images and you want to queue
each image as a unique post
in Tumblr. You spend a few minutes manually
uploading each one as a queued post in your browser before exclaiming,
“Argh! This is terrible! There must be a better way…”

Several minutes of googling later you proclaim, “Argh! I can’t believe no one has made a tool to do this!”. Time to pour yourself a drink and break out some python.

  1. Install python-tumblpy
  2. Register an app for yourself on Tumblr – you’ll need this to get a valid oauth token for uploading
  3. Download and run this script

It will authorize your app and generate an oauth token. Pass it a list of images on the command line and each one will be uploaded and queued as a unique post. Each image that is successfully uploaded has “_done” added to its filename.


$7 USB Cloudwatch Notifier

Cloudwatch rocks and we have a ton of alarms to let us know when something breaks (or is about to break!). The only downside is that you can start getting a lot of emails or text messages and if you try not to chronically check your email, you might miss something.

If only there was some way to know something was broken without having to check your mail… luckily there is! For $7 you’ll never have to wonder about the state of your cloudwatch alarms again.

Step 1: Buy this USB mail notifier ($7)

Step 2: Grab this zip file to control the device. It contains compiled version of usbnotifierosx_cli for controlling the device and a very simple PHP script for checking if you have any active cloudwatch alarms.

Step 3: Run the script via crontab every minute. Light is green? No alarms… Red? Alarm!

You can now get back to work and never worry about missing a cloudwatch alarm again.

Thanks to Eric Betts for creating usbnotifier_cli!


Signing your SES mail with DKIM using PHPMailer and Route 53

If you use Amazon’s Simple Email Service to send email you might have noticed your messages have an unfortunate via listing in gmail – email-bounces.amazonses.com. To fix this, you need to sign your mail with DKIM before you send it.

To deliver mail, I was using PHPMailer with a custom SES delivery method. To start signing messages, I followed these steps:

Generate a key

I started by using the form here. The nice thing about the form is that it generates the keys and gives you a zip file that contains the keys, instructions on what to set your DNS txt entry to plus some sample PHP code for use with PHPMailer.

Unfortunately the key is 1024 bits which didn’t work when I tried to add a txt entry in Route 53 using the AWS management console, I kept getting a TXTRDATATooLong error. There seems to be a 255 character limit for TXT entries. Switching to a 768 bit key solved the problem. Here’s the code to generate the key:

openssl genrsa -des3 -passout pass:<change-me> -out .htkeyprivate 768
openssl rsa -in .htkeyprivate -passin pass:<change-me> -pubout -out .htkeypublic

(change the <change-me> password)

Add an entry to Route53

Add the following TXT entry to your domain in Route 53:

Name: mailer._domainkey
Type: TXT - Text
Value: "v=DKIM1; k=rsa; g=*; s=email; h=sha1; t=s; p=<key from .htkeypublic>;"

Sign and send a test email to yourself

You’re now ready to send yourself a test email to see if it has worked. Make sure you cc check-auth@verifier.port25.com in your message – port25.com runs a handy verifier that will reply to you with details about what worked (or didn’t work) in your message.

// blah blah blah, normal PHPMailer setup
$mail->DKIM_domain = 'yourdomain.com';
$mail->DKIM_private = 'path/to/dkim.key.private';
$mail->DKIM_selector = 'mailer';
$mail->DKIM_passphrase = '<change-me>';
// and then you send the email...

Hopefully everything worked and your via text in gmail no longer includes email-bounces!

Running an EC2 server? Go install NTP right now…

Seriously, go do it right now – I’ll wait for you to get back.

apt-get install -y ntp

Good job! I’m not sure why I hadn’t come across this yet, but several of my instances had fairly significant clock drifts – significant enough that SES was generating time signature errors. Installing ntp will now be a standard part of a new instance’s setup.

Your sandbox is violating my security

Let’s suppose you come across the following error while debugging your AIR app:

*** Security Sandbox Violation ***
SecurityDomain 'file://.../art.swf' tried to access incompatible context 'app:/myapp.swf'

Let’s also suppose that you’re loading some artwork from art.swf – you’ve created some clips that you’re exporting for actionscript and you’re importing them in your app by using applicationDomain.getDefinition to get their class in to mypp. At some point in myapp you add some bits of that artwork to the stage you add some MouseEvents to a clip containing that artwork.

Suddenly when you try to interact with that clip, you start getting a whack of Security Sandbox Violations. Google to the rescue? Unfortunately, no. You will get a lot of Error #2048, 2122 posts but our simple art.swf doesn’t contain any code and isn’t trying to do anything funny. If you search for “*** Security Sandbox Violation ***” you’ll come across this stack overflow post which might give you an idea.

Perhaps Flash is trying to give the clip you imported from art.swf some kind of focus? A quick artwork.mouseEnabled = false, artwork.mouseChildren = false later and problem solved!

Some pseudocode to better demonstrate the solution:

// Load art.swf
// import class "Art" from art.swf
var my_art:Art = new art();
var my_clip:MovieClip = new MovieClip();
// Listeners that do mouse things...
// At this point, you may get your sandbox violated.. The solution?
my_art.mouseChildren = false;
my_art.mouseEnabled = false;
// Yay! Your security is safe

Flash Player Bugs – so much fun!

Public Advisory: If you have Flash Player version installed, upgrade it! There are some strange issues in that release that can cause MouseEvents to not report… perhaps in connection to masking or scrollRects.

What follows is the -vvv story of how I discovered the issue and a recommended solution.

Over the weekend mysterious bug reports began surfacing. Coinciding with a major update on our site it seemed like we must have introduced a new strange bug.  I couldn’t believe we didn’t catch it sooner, but it was uncommon enough that it could wait until Monday. On Monday morning I began testing against older versions of our code and no matter how far back I would go, I could still reproduce the bug.  At this point, I was losing my mind – how could code that was working perfectly for more than a year suddenly stop working? I began testing other browsers, other operating systems and eventually saw the pattern: if you were using Flash Player version you would encounter the bug. Annoyingly, isn’t listed Adobe’s list of archived flash versions – if it had been it would have saved much debugging.

So, what to do? When you use swfobject you can specify the minimum flash version required for your swf. I didn’t want to force everyone to upgrade to 11.1 (our tools work in flash 10 and above), so I added an extra check before embedding our swfs. If your flash version matches exactly, our minimum version is 11.1, otherwise it is 10.0. We get to take advantage of Flash’s streamlined expressInstall update process while allowing older users to stay put.

    var version = swfobject.getFlashPlayerVersion();
    v_check = '10.0.45';
    if (version.major == 11 && version.minor == 0 && version.release == 1) {
        v_check = '11.1.0';
    swfobject.embedSWF(swf, id, width, height, v_check, ...);

Hopefully this information helps someone else who can’t understand why working code suddenly broke…