May 11, 2010
These days it’s fairly common to run a local environment for web development. Whether you’re running Apache, Mongrel, or the App Engine SDK, we’re all starting to see the benefits of having a production-like environment right there on your laptop so you can iteratively code and debug your app without deploying live, or even needing the Internet.
However, with the growing popularity of callbacks and webhooks, you can only really debug if your script is live and on the Internet. There are also other cases where you need to make what are normally private and/or local web servers public, such as various kinds of testing or quick public demos. Demos are a surprisingly common case, especially for multi-user systems (“Man, I wish I could have you join this chat room app I’m working on, but it’s only running on my laptop”).
The solution is obvious, right? SSH remote forwarding, or reverse tunneling. Use a magical set of options with SSH with a public server you have SSH access to, and set up a tunnel from that machine to your local machine. When people connect to a port on your public machine, it gets forwarded to a local port on your machine, looking as if that port was on a public IP.
The idea is great, but it’s a hassle to set up. You need to make sure sshd is set up properly in order to make a public tunnel on the remote machine, or you need to set up two tunnels, one from your machine to a private port on the remote machine, and then another on the remote machine from a public port to the private port (that forwards to your machine).
In short, it’s too much of a hassle to consider it a quick and easy option. Here is the quick and easy option:
$ localtunnel 8080
And you’re done! With localtunnel, it’s so simple to set this up, it’s almost fun to do. What’s more is that the publicly accessible URL has a nice hostname and uses port 80, no matter what port its on locally. And it tells you what this URL is when you start localtunnel:
$ localtunnel 8080
Port 8080 is now publicly accessible from http://8bv2.localtunnel.com …
What’s going on behind the scenes is a web server component running on localtunnel.com. It serves two purposes: a virtual host reverse proxy to the port forward, and a tunnel register API (try going to
). This simple API allocates a port to tunnel on, and gives the localtunnel client command the information it needs to set up an SSH tunnel for you. The localtunnel command just wraps an SSH library and does this register call.
Of course, there’s also the authentication part. As a free, public service, we don’t want to just give everybody SSH access to this machine (as it may seem). The user localtunnel on that box is made just for this service. It has no shell. It only has a home directory with an authorized_keys file. We require you to upload a public key for authentication, and we also mark that key with options that say you can only do port forwarding. Although, it can’t be used for arbitrary port forwarding… because it’s only a private port on the remote side, it can only be used with the special reverse proxy.
So there it is. And the code is on GitHub. You might notice the server is in Python and the client in Ruby. Why? It just made sense. Python has Twisted, which I like for server stuff. And Ruby is great for command line scripts, and has a nice SSH library. In the end, it doesn’t matter what it’s written in. Ultimately it’s a Unix program.
December 12, 2009
Webhooks. User-defined callbacks on the web. Yes. YES! Wait, what does that even mean? That stupid website doesn’t seem to explain them at all!
Let’s explore this through an analogy. This analogy uses stockbrokers! Yay! (?)
Consider, before the web, before email, how people would interact with their stockbroker: the telephone. Whenever you wanted to manage your investments and find out what’s really going on in the market, you would call your stockbroker. It’s similar to how you might use your browser to visit Twitter to update your status and find out what’s going on with your friends, right? This is the basis of the analogy. Bear with me.
Imagine in this story your phone is a browser, a phone call is a web request, and the broker is a web application, like Twitter.
It’s 1989 and you like to think of yourself as a big time stock trader with an impressive portfolio. Good for you. You got to this point by staying in close touch with your stockbroker. You’d call her (!) to find out what was happening in the market, discuss whether buying certain stock was a good idea, and maybe put in an order. You were able to get information out of the system and put orders into the system by picking up your phone and calling your broker.
The problem is that you can only react to events in the market as quickly as you get the information. This means you’d have to call your broker quite a bit to stay on top of a fast moving, highly volatile market. A programmer might try to automate this with a script. You take a similar approach: you hire an assistant to deal with your stockbroker. Perhaps this is unheard of in reality, but stay with me.
Now an assistant is not unlike a computer program in theory. You can give them instructions and based on certain conditions and input, they’ll do as you say. For example, maybe you instruct your assistant to buy a certain type of stock after it behaves a certain way, and if there’s not enough money to buy the amount that you told them, they can transfer the money from your savings account after a quick confirmation phone call with you. In today’s world, that sort of thing is not terribly out of the question to automate with a script using the web APIs and programmatic infrastructure available to us now.
Again, in order to react to events in the market in a timely manner, it requires lots of phone calls to your stockbroker. Sure, your assistant can handle it, but it’s a lot of work and wastes a lot of time. In fact, it wastes you money because you pay for your assistant by the hour! If you were a programmer, your script would have to constantly poll the broker API requiring a touchy cron setup or a long running process that gets more inefficient the closer to real-time you want it to be. Not to mention it’s just more work than you should have to deal with. If only there was some way for your assistant or script to be notified when things happen so they could simply react.
One day, your stockbroker says they’re providing a new service they describe as callbacks. You give them a phone number, and they’ll call it whenever something interesting happens regarding stocks relevant to you. Wow! Well, you could give them your number, but there are two problems. First, it’s 1989 and you don’t happen to have a cell phone. You can’t always be reached. Second, even if you could, you’d still want your assistant to handle the events because they have been instructed with how to deal with them and will do a lot of the legwork for you. Luckily, your assistant has a cell phone and is always available, so you give the broker their number.
Now your assistant is working very efficiently making you lots of money. Their job is so much easier because they don’t have to do anything until they get a call from either you or, more importantly, the broker. They can finally react to events as they happen, without a lot of nonsense trying to stay on top of things. What’s more is they will automatically take care of whatever situations you’ve told them.
What a cool feature, this callbacks thing. Thanks, broker!
If you haven’t guessed, the callback feature in this story is the exact mechanics of webhooks. Webhooks would allow you to tell the web apps that you use to “callback” scripts you have online. These scripts will deal with whatever events that web app produces. These callbacks use the same protocol you use to talk to them and that you both know how to use: web requests. Putting your script online at a URL is analogous to your assistant that has a cell phone: it’s always available for direct connection at a persistent “phone number,” unlike you, with dynamic IPs and NATs and turning off your computer. And just like an assistant, the script can do a lot of interesting things for you that you wouldn’t necessarily want to do, most of which is a sort glue work of making different systems work together given some logic. For example, transferring money from your savings account to the broker account when there isn’t enough.
A concrete example of a story made possible from webhooks that might be a useful scenario for many of you involves Twitter. Let’s say Twitter supported webhook callbacks for when somebody follows you. Right now you get an email, and from there you can decide what to do manually: follow them back, block them, or do nothing. I used to go out of my way to block users that I knew were spam bots, but now there’s so many it’s not worth the time. And of course I also generally follow back people that I actually know. If Twitter would simply call a script of mine whenever somebody followed me passing along the user ID, I could very easily run this logic in a PHP script or a simple App Engine app. Or perhaps I’d use Scriptlets (ahem, which was made exactly for these kinds of web scripts). It would work like this:
First, use the Twitter API to look up the user from the ID, and grab their name. Then use the Facebook API to check if that name shows up in my list of friends on Facebook. If so, use the Twitter API to follow them back. Otherwise, if they’re following over 1000 users and that number is more than twice the number that’s following them (which is roughly the heuristic I use manually), use the Twitter API to block them. All automatic.
If you could do this, not only would you have glued together Facebook and Twitter in an interesting and useful way, but you’ve sort of extended the net functionality Twitter provides you. You could imagine perhaps someday Twitter releasing features that would do exactly what you just did. But they won’t. In fact, they’ll never release features that are so specific to you (who says my spam algorithm is the algorithm everybody should use?). This is how webhooks make the web more about you. You can start extending web applications and gluing them together just the way you want.
This is a win-win for web application users and developers. Users get more functionality. Developers can implement less.
Coming back to the stockbroker analogy, there is a type of order called a limit order where you say to buy or sell when it’s at a certain price. With webhooks (or the broker “callback” service), this is merely a convenience because you could easily set that up outside of their system. Speaking of that example, when I mentioned your assistant transferring money between accounts, that reminds me, you know that feature banks have called overdraft protection? If banks had webhooks, all banks could have overdraft protection. Wow, right? That would have been nice for me when I had Washington Mutual, a bank known for its lack of overdraft protection.
What else could you do in a world with webhooks? Basically everything would have a common event-driven infrastructure, allowing you, with just a little bit of scripting glue, to accomplish so much more and make the systems you use better, and more personal.
November 30, 2009
I’ve been playing a lot with Comet lately. It started with Notify.io, in which I decided to prove that HTTP streaming was a simpler alternative to XMPP in getting messages to the desktop. That went quite well, but it was easy because it wasn’t all that different from a socket connection. Then I built a yet-to-be-announced site that uses real-time updates, and I was forced to deal with Comet to the browser. That’s a bit more complicated.
Actually, I’m arguably a veteran of Comet in the browser. I was doing it before it had a name, all the way back in 2005. A friend and I were using it (without knowing that it was terribly novel) to build a real-time strategy game in the browser called AjaxWar. I haven’t really done a lot with it since, but I was hoping after almost 5 years there would be all kinds of advances in libraries and tricks that would make it super easy.
That was not really the case.
I was also hoping for actual persistent connections (that’s what we did in AjaxWar), but it turns out the standard today is long-polling. This is a semi-persistent connection that drops after every message and then reconnects and waits for the next message. I also wanted JSONP and cross-domain support. So I ended up using the dynamic script tag technique:
It’s fairly elegant in its simplicity and cross-browser support. But it has some weird side-effects that I’m not sure if any of the fancier systems got around. For one, it keeps the browser loading. While it’s waiting for messages, the browser says that page is still loading. I also ran into some issues where if I included, say, a Google Calendar widget on the page, it might not decide to keep the connection open (or even start it). I ended up putting a delay on the first call to waitForMsg() until after the calendar widget was likely loaded.
So it’s a bit brittle. You don’t know if it stops working. Therefore you can’t do retries. And you never know if you happen to miss a message between connections (unlikely, but something to worry about). Plus I think if you hit Escape it also kills it.
But this worked well enough for my projects. I knew that if I found a better way, I’d switch over to it, but it was good enough.
Then today I decided to solve the problem right once and for all with a project called CometCatchr.
I know a very small number of people won’t agree with my approach using Flash, but I tend to be pragmatic. I trust Flash is generally available and the benefits completely outweigh everything else to me. It’s also not new. Even the Bayeux protocol includes Flash as supported connection type. Still, I couldn’t find any simple Flash component that gave me what I wanted.
It was a drop-in replacement to my previous technique that worked right out of the box:
It simplified my code, not just client-side, but now I don’t have to support JSONP callbacks on the server. CometCatchr also parses the JSON messages before passing the callback, so that’s taken care of too. I realize it seems less than ideal to couple this with JSON payloads, but I didn’t say it wasn’t an opinionated component.
In fact, it’s very opinionated. It likes single-line JSON messages sent via HTTP using chunked transfer encoding. That’s because that’s how I do Comet streams. Actually, that’s how Twitter does them, too. I’m quite alright with such constraints, but if you want to make changes, it’s MIT licensed and super simple to hack on.
So for the time being, I’ve more or less solved simple Comet to the browser, particularly for me. It also might be worth knowing that another motivation for building this component is that I intend to solve Comet and real-time stuff in the browser entirely… but uhh, yeah. Stay tuned.
October 29, 2009
Last night I went off and put up a wiki about an idea I’ve been thinking about for a while: public open source services or POSS. Think: public services or utilities on the web run as open source.
Unlike open source software, web services aren’t just source code. They’re source code that runs. They have to be maintained in order to keep running, and the resources they consume have to be paid for. This is why most web services are built using a business as the vehicle. This effectively constrains what you can build by framing it as something that needs to turn a profit or support you to work on it. But does it need to be that way? Can web services be built in a way that make it self-sufficient? Not needing some ambivalent leader to take responsibility for it?
I originally blogged about it in February 2007, 6 months after I first wrote about webhooks. Unfortunately my old blog isn’t online right now. Back then, I was trying to solve the administrative problem. How do you maintain the servers in an open source way? My idea then, was to build a self-managing system using something like cfengine or Puppet, where the recipes and configurations are kept with the publicly available source code. As new configurations are checked in, the server(s) adopt the new directives and continue to self-manage.
The practicality of such a setup is a little far fetched, but seemed pretty feasible for smaller projects. However, since the release of Google App Engine, this concern for simple web applications has disappeared. Google just automates the system administration, and scaling! This means to run the app, you just have to write the code and hit deploy. That’s a huge step! Administration concerns? Pretty much solved.
The next thing is the financial concern. How do you pay for it? Or rather, how does it pay for itself? This took longer to figure out, but here we are. From the wiki essay:
You use the same Google Merchant account that App Engine debits as the one that accepts donations. This way no bank account is involved. Then you track the money that goes into the account (using the Google Merchant IPN equivalent). Then you look at your usage stats from the App Engine panel and predicate future usage trends. Then calculate the cost per month. Then divide the cash in the account by that and you have how long the service will run. You make this visible on all pages (at the bottom, say) that this service will run for X months, “Pay now to keep it running.” You accept any amount, but you are completely clear about what the costs are. And this is all automated.
Take the humans out of the loop! (That’s a WarGames reference)
Then you rely on the same sort of community approach of open source to contribute to the application. Like a few members of the project community are given certain rights, some will be given permission to deploy the app from time to time for updating the running service.
If the service isn’t useful, nobody uses it, it’s not paid for, it disappears. If it is useful, people will pay for it to keep it running. They are assured they are paying operating costs, which are significantly lower than most because it doesn’t include paying for human resources! Volunteers might need to meddle with settings, but otherwise, the coders are in control and the community accepts or denies changes made by whoever wants them.
So if this is interesting, read the full essay I wrote up on the wiki. It’s been my intention to prototype and validate this model with many of my projects.
September 15, 2009
It’s near time for slutty domain registrars and confusing DNS hosts to die in a fire.
I’ve wanted to reinvent the domain registration and management experience for a while. Every time I use what’s out there now I die a little inside. I have over 100 domains and I register new ones fairly often. Here’s my current experience:
I start with Instant Domain Search when I think of a domain or need to come up with a domain. Real-time check-as-you-type really helps you in the brainstorming process. There’s actually nothing wrong with this. It’s the most fun part of the experience, but it ends here.
Then I register. If it’s not a fancy TLD like .io or something, I use the registrar that I have most my domains with: Cheap Domain Registration. This is perhaps the worst part. It’s basically a GoDaddy reseller that I stumbled across a long time ago and started registering domains with. Since I’d rather not have my domains across several crappy registrars, I’ve decided to stick with them. Plus, it’s such a frickin pain to transfer domains. I’ve done it a few times and I still don’t even know how it works.
Anyway, it’s effectively GoDaddy, which is the most popular registrar. I don’t exactly know why. It’s probably the sluttiest of them all. It’s so noisy, fake, and slow. Decent prices, but of course they’re going to try and upsell you in every way possible. They got me once because I was in a hurry and I clicked the wrong thing. It’s at least (yes, they give you the option for more) 3 pages of upsell offers.
However, it does have good support, which is important because DNS and domains are such a pain to novices. I sort of like the fact they call me sometimes after registering asking if I got everything set up. I told them never to call me again, but that I’m happy they’re doing that.
That good karma goes out the window when you try and manage your domains. This is the slowest part, and the second worst part of the experience next to avoiding all the upsell traps. Luckily I don’t need to use it ever except for DNS.
Now, it’s nice of them to provide free DNS, but it’s so hard to get to and so clunky once I’m there. I usually want to use EveryDNS just for that, but I still have to use their interface to point my domain to EveryDNS. I also tend to use their web redirect for making naked domains go to www, since each one of those would use up my limited number of records on EveryDNS. So I’m stuck with them for that usually.
Once I’ve got it pointed to EveryDNS, it’s pretty okay. The EveryDNS interface is not so pretty, but it’s quick and to the point. I remember getting a bit confused in the early days, partly due to the interface and partly due to DNS not being the most user friendly of technologies. Unfortunately my free account can only have 20 records, including web redirects. I should probably just donate and get that lifted, but I suppose I’m lazy. I usually just swap out domains I’m not using anymore, or end up using my registrar’s DNS for simple domains.
In the end I’m using up to three systems, DNS and registration both being quite a hassle, particularly in the setup. But if you register a lot of domains, make a lot of sites, you’re in setup mode quite a bit. There are a lot of things that could be better, from the UI to the sales process. It could all be one nice solution that’s just done right.
So I decided to start working on that. It’s called domdori, which is short for “domains done right.” The core experience looks like this:
You find a domain with real-time search. Then you use Amazon 1-click payment to buy the domain right there. You now have the domain. The default records don’t make your new domain point to some ugly, slutty landing page advertisement. The default landing page is whatever you make it. In fact, the DNS settings can default to whatever you want. You get not only an advanced DNS manager UI for power users, but a very straightforward DNS manager UI with smart defaults and complexity abstracted away for most users.
That alone would just completely make my day, but there’s more (in a “less” sort of way). Only, we’ll save that for later. Until then, a public alpha of domdori is approaching…
June 28, 2009
Update: I’ve basically stopped development and support of Yapper because Notify.io is the right way to solve this problem. However, this post describes that problem and is still worth the read. ;)
Today I released Yapper, a full featured Jabber/XMPP interface for Growl. It was based on the simple Twisted script I wrote while building my notification email to Growl piping. Although it’s limited to OS X users, I still think this is a big deal. Let me explain.
If you haven’t heard of Growl, it’s a global notification system that lets applications notify you of events in a consistent, customizable way. It’s been around for a while and is integrated or has plugins for lots of popular apps like iTunes, Adium, and Tweetie. It has bindings for a bunch of languages and also has a command line tool that you shell scripters can use to pipe notifications into. For example, I used this recently for my reminder system.
I think Growl is great particularly because it very nicely solves passive real-time notifications. That is, you want to be notified, but you don’t want it to interrupt you by requiring action. This is why I hate email notifications.
However, the major problem with Growl is that for the most part, it’s limited to local notifications. Sure, you can get notifications from “out there,” like Twitter or IRC or Gmail … but it requires you to have a local application that pushes them into Growl. One for each, in fact.
It turns out, I don’t actually care about most local notifications. Telling me a file is done downloading or what song is playing in iTunes is not terribly notification worthy. If I’m sitting there to get the notification, I probably already know. The most useful notifications are of events important to me that I’m nowhere near … events from things out on the Internet.
So Growl needs a network interface. Oh, wait! It has one! Well, what’s the problem? Two things: it’s a non-standard protocol, and it requires a direct connection. That not only raises the bar for things “out there” to notify you with Growl, but it literally makes it impossible if you’re constantly changing IPs, sitting behind a firewall or NAT, etc.
Let’s see… who’s solved this problem already? Right, IM! XMPP, the open standard for IM and real-time message passing (also known as Jabber), seems to have everything we need. It’s a popular protocol, fairly accessible from any language, and doesn’t require a direct point to point connection. So it’s a perfect transport for network Growl notifications!
Since I’m not one to wait around for people to implement what I think they should implement, I solved this problem by making Yapper. Yapper is a lightweight Jabber client made specifically to receive Growl notifications. It starts when your machine starts and sits in the background just waiting for whatever you have sent to it so it can pop it up with Growl.
You can now easily have Growl notifications sent to you from anywhere. Websites have less of a reason not to directly notify you with Growl for events that are important to you. More importantly for me, I can more easily set up Growl notifications for whatever I want. With the rise of webhooks, so can you. Anyway, to me this generally makes Growl much more useful.
June 26, 2009
Recently I’ve been evaluating software to help support agile/scrum development on our team, and ideally to roll into our NASA Code product for others to use. We’re already married to Trac, so we’ve been playing with Agilo and are looking at some of the other agile plugins for Trac. Unfortunately they’re all so heavyweight, despite some that claim not to be.
I came back to a realization I’m sure a lot of us have had: most software sucks. Especially software that’s intended to augment some real-life process. When asking Timothy Fitz (my insight into the amazing continuous improvement processes used at IMVU) about recommendations on agile tools, he said: “a board and post-its (seriously)”
This is part of the reason most enterprise software sucks so terribly. Enterprise is about lots of real-life process and workflow, and given that process augmentation software even in small doses generally sucks, large amounts of it will suck exponentially.
A lot of us have learned that less software is more effective. One major attraction of Trac was their goal of staying out of the way through minimalism. The trick with minimalism, in general, is knowing what’s actually important—the essence of the message or design. This is a big part of my design process. Asking, “How can I fold these requirements into fewer features and UI?” instead of directly implementing a feature for every requirement.
The other thing about minimalism is that, like abstraction (another form of compression), everything you leave in the design makes such a huge difference. In programming, when you make abstractions, you’re deciding what you can assume. This means abstractions can go in different directions depending on the assumption requirements of what’s going to use the abstraction. The risk with minimalist software is that a simple design choice can drastically change the direction of the abstraction and make or break whether the software fits your needs.
Luckily, minimalism buys you a sort of abstraction that can enable projection. By this I mean that users can project their actual process and workflow onto the software. If it doesn’t have features that impose a particular process, users are free to do what works for them. This is why wikis are so powerful.
Coming back to Timothy’s “a board and post-its” remark, why do you even need software? If you can do it without software, why would you want to bring software in to slow things down?
Software does have a couple strengths. First, it encodes process in way that means you can automate parts of it. Nobody has to worry about manually typesetting when using a word processor. Second, it persists and organizes information that would normally be lost in handwritten notes, or worse, somebody’s head. The trick is getting these advantages without getting in the way.
A naive approach to software design is thinking that perfectly modeling a system, such as your development process, is the way to good software. I used to think this. It sounds great because then you can programmatically reason about every aspect of the system. But in the real-world, no two systems are exactly alike. In fact, a given system can change quite a bit in its lifetime. So there’s really no point to modeling systems with that kind of precision.
However, I’m seeing a lot of this in agile/scrum software. Requirements have stories, stories have tasks, organized into iterations and releases. CRUD for every noun mentioned in scrum. This on top of abstractions in a direction different than we need. Numbers where it doesn’t really matter. Nice pie chart breakdowns we’ll rarely use. Top it off with horrible UI, since with all these features there isn’t time to make them easy to use.
Honestly, Pivotal Tracker seems to have the best abstraction of agile. It folds requirements, stories and tasks into just stories. It automatically and dynamically creates iterations and calculates velocity. It keeps you on a single page, keeping you focused on what’s important.
Unfortunately, we can’t use Pivotal Tracker since we’d need it on our servers and the licensing they offered doesn’t scale if we want to essentially give it away as part of NASA Code. It’s likely I’ll want to just start nudging Trac in the right direction using Pivotal Tracker as a model reference, pulling together code from Agilo and other plugins. If there’s one thing that complements minimalist design, it’s an extension architecture, and Trac has an excellent plugin system.
Anyway, as far as augmenting process and workflow, I’ve always liked the idea of starting with a wiki and lazily formalizing the process into custom software as needed. As long as you can keep it under control, mind your requirement abstractions, and avoid writing too much software.