A self-hosted alternative to Jetpack's Photon service

Like many people, I’ve long had a bit of a love/hate relationship with Jetpack, the WordPress plugin from Automattic
that adds a slew of features like pretty photo galleries, WordPress.com stats, automatic sharing to Google+ and Twitter,
etc. A lot of these are incredibly useful and implemented really well, but due to some philosophical issues I have with
things that the plugin does, as well as a desire to have more control of various aspects of my website, I’ve been
looking for alternatives to the parts of Jetpack I used most. Today I’d like to share the self-hosted alternative I
built to replace Photon, Jetpack’s image proxy and editing service.

Image proxy services

One of the greatest features of Photon is that the service itself is hosted on WordPress.com infrastructure, which means
that it’s very fast and stable, and frees you from having to worry about it. The downside is that, since Automattic is
providing it as a free service, there are some stipulations on its use, namely that it is only for sites hosted on
WordPress.com or using the Jetpack plugin. Since I’d been working to migrate off of Jetpack, I could no longer use the
service.

My requirements for an image proxy were pretty simple. First and foremost, it had to serve traffic over https, since
all of my content is https. Next, I wanted a service that supports origin pull, in order to keep the
integration fairly light. The original copy of all images should always live on my site, with the proxy server
fetching them as needed. That way, if I ever disable the WordPress plugin that is rewriting my image URLs, things
should still work as normal, just pulling the images from their original location. I also needed a service that
supports basic image resizing. I disable WordPress’s automatic resizing, so the proxy service needs to dynamically
resize images to whatever size I need. Some of the extras that Photon supports like image filters and
brightness are neat, but I don’t ever use them. Finally, I strongly preferred a service that doesn’t rely on URL query
parameters, since that can have caching implications.

That left me with three main services I looked at: resize.ly, embed.ly, and cloudinary. There are probably
others as well, but those are the ones I looked at. Ultimately, I wasn’t completely happy with any of them, either
because of their use of URL query parameters or they charged more than I really wanted to spend for this. Instead, I
started looking at self-hosted options.

Self-hosted image proxies

There is no shortage of open source image proxies on GitHub, including atmos/camo which actually powers GitHub’s
image proxy. However, since I was looking to self-host, it needed to be something I felt comfortable hacking on and
that didn’t require much work to run. I’m not comfortable enough with ruby or node.js, so that eliminated a good number
of the available projects. Photon itself is open source, and I actually ran that locally for a few
weeks while I was working on my eventual solution. Ultimately I didn’t like Photon’s use of query parameters, its
assumption that remote images are served over “http”, and the fact that it doesn’t provide any caching out of the box (I
suspect that WordPress.com adds caching at a different layer).

willnorris/imageproxy

Most of my development at work is done in Go these days, and I had been looking for an opportunity to run a real Go
service myself (versus just deploying my code to App Engine or something), so this was a great project to do that.

The final result is just a few hundred lines of Go code, utilizing gregjones/httpcache
together with peterbourgon/diskv for caching remote images on disk, and disintegration/imaging for basic image
manipulation like resizing and rotation. All options are specified in the URL path, mimicking the format that
resize.ly uses, and it supports whitelisting of remote hosts, so the instance that I run is locked down to only
serve images from my own sites. And because it’s written in Go, it compiles to a statically linked binary that is
incredibly simple to deploy and manage; I’ve included the upstart init script I use on my Ubuntu server.

I’ve been running it here on my own site for the last month or so, and generally have been really happy with the
results. There’s certainly still some work to do: it doesn’t yet do any image optimization using something like
pngcrush or jpegoptim and I believe color profiles are getting lost on resize. But on the whole, it’s in pretty
good shape.

The final missing piece at this point is the WordPress plugin that rewrites my image URLs to be loaded from the proxy
server. I’m currently using a severely hacked up version of the photon module from the Jetpack plugin which I hope to
clean up and release soon. In the meantime, take a look at the proxy server at
https://github.com/willnorris/imageproxy.