Most of my public code begins its life in a private repository. This is because, more often than not, I'm storing security credentials in a static file and don't want anyone abusing my credentials.

Like most developers, I'm lazy. It's easier to define a root-level constant with an API key or dashboard password than it is to program an interface for setting and storing those credentials. Unfortunately, it means I can very easily slip up and distribute those credentials to the world.


A couple of weeks ago, I built a quick little Node.js prototype that uses Tri-Met's public API to fetch arrival times at a particular bus stop. I further extended the app by wiring it to a Twilio endpoint so that it will grab the bus stop ID from a text message - and respond to the sender with another text containing their stop information.

I was very proud of the application, and quickly moved to write up how I'd prototyped it in an afternoon. I pushed my code to GitHub and waited for the post to auto-publish.

Then a friend reminded me I'd pushed both my Tri-Met and Twilio credentials to the GitHub repository. I couldn't sleep.

I quickly deleted the repo and hoped all would be well. I couldn't just delete the credentials and push the change; GitHub would still have a copy in their revision history. Flushing the entire repository down the drain was my only option. I moved it back to a private repo on Beanstalk and left it at that.

Obviously, people wanted to see the code. But my laziness had resulted in a repository I couldn't actually publish.

The Resolution

Thankfully, someone pointed me to an article on using environment variables with the system hosting my running code. I was able to configure an environment variable for each piece of my authentication credentials, then could reference them within the application.

No more hard-coding!

I created a new repository with no history and transplanted my now-clean application to the new repo. I pushed it to GitHub for the world to see, completely confident that no one can use the code there to access my accounts with Tri-Met or Twilio without my permission.

It also taught me a very important lesson about code organization. I rarely, if ever, hard-code my credentials any more. Instead, I'll bite the bullet and just code an interface for setting them up.[ref]In situations where  a host exposes an interface for me, I'll just use theirs instead of rolling my own.[/ref] If I absolutely have to hard-code credentials, I do so with a [cci]_local.conf[/cci] file that's ingored globally.

I also hand-check every single diff before I commit changes to be sure I haven't accidentally committed a file or that my command-line tools haven't created a swap/change/save/tmp version of the [cci]_local.conf[/cci] file that's now in the list of files to be committed.

Additionally, this lesson also taught me never to use the [cci]-a[/cci] flag when preparing a Git commit - always inspect the list of changed/new files to be sure you know exactly what's going into a repository. Once it's there, it's there for good.