Software teams are often not in control of their own budgets. It’s not uncommon to find teams who regularly fork out thousands per developer for Visual Studio licences, yet have trouble getting budget for a $25/year DynDNS account. I run into this sort of problem myself from time to time, and so it’s nice to have free options for key team needs.
One key requirement for a software team is to be able to communicate. Too many distributed teams rely on email and ad-hoc IM solutions, and with my current team becoming increasingly distributed, I wanted a good way for us to keep in touch. Campfire by 37 Signals is the current industry go-to option for this sort of thing, but for teams with tightly controlled budgets, or self-funded open-source projects, the $144/year entry-level plan might not be an option.
Enter XMPP.
If you don’t know what XMPP is, let me explain. It’s basically IRC with federated user account management. Is that clear? I’m going to call XMPP by its old name, Jabber, from here on in, because I think it’s easier.
Think persistent chat rooms, private messaging, moderator privileges, all of that sort of thing – but you can join any room in the world using your gmail account, or your corporate email address (if you run a jabber server), or your own personal email address (if you have your own domain). The interface isn’t quite as schmick as Campfire, but there are open-source clients and libraries, so the sky’s the limit, really.
We already did a lot of our communication using GTalk, and Google Talk works over jabber – so this seemed like an ideal option.
The first thing I needed was a private XMPP server. It seems like there are two good free, open-source options out there: Openfire and ejabberd. I chose ejabberd, because the install seemed simpler – and let’s face it, there’s no point blowing hours of developer time to save $144/year. We used a DigitalOcean VPS to host it (if there’s one thing every software team needs, it’s a linux box with a public IP address). The trickiest part was realising that I needed two different host names – an authentication server and a conference server. They both run on the same virtual server, of course, but I needed a wildcard DNS entry (if there’s a second thing every software team needs, it’s a DynDNS account). My authentication server runs on (let’s pretend our company acronym is ABC) abcim.dyndns.org, and the conference server is conference.abcim.dyndns.org – and thanks to a wildcard entry, I’m only using up one of our hostname entries.
Installing and configuring ejabberd is left as an exercise for the user – but the documentation is reasonably easy to follow, and the installation is quite straight-forward. (Pro-tip: you can add any jabber-enabled account as a server administrator. I added my gmail account.)
Once you have a Jabber server up and running, you’re going to need a client. Pidgin is the hands-down winner when it comes to administering jabber group rooms (or Adium for Mac, as I understand). I signed in with my gmail account and joined a group room called Software on conference.abcim.dyndns.org, having already set my gmail account as an admin account in the ejabberd config. Now I can invite the rest of the team to the room. While Pidgin is definitely where it’s at for setting up a room, there are other clients which can cope with jabber group rooms – Jitsi seems decent, and Xabber make a sub-par but bearable Android client (the other jabber/XMPP-enabled Android apps I’ve tried have varied from non-functional to sub-par-and-not-bearable). For any team members without gmail accounts, there are other jabber account providers out there, or you can set up your own accounts @abcim.dyndns.org using /sbin/ejabberdctl.
At this stage, we had a group collaboration server which allowed us to sign in either using our existing gmail accounts or private @abcim.dyndns.org accounts. I wasn’t prepared to stop there, however.
One team member wasn’t keen on installing a native client. I can understand that – as developers, we push our machines to the limit, and we’re naturally suspicious of installing software on our machines. Down with bloat!
Luckily, there are web clients out there. I made an account for him @abcim.dyndns.org and went hunting for a web-based client. I briefly reviewed several, but the simplest install that seemed like it wasn’t a dead end was Candy, which I hosted under Apache. I chose Apache instead of the other options because I’m super-familiar with Apache hosting, and it came pre-configured for Apache anyway. It took a little tweaking to get it hosted in the folder I wanted, but it wasn’t long before I had a web client running at abcim.dyndns.org which you could point a browser to, sign in with your @abcim.dyndns.org account, and get auto-joined to our Software group room.
Even this wasn’t enough. I didn’t just want a place where we could sit and chat. I wanted a dynamic room which reflected not only what we were saying, but what we were doing – and for that, I needed to write some software.
We had recently signed up for a paid GitHub account, and migrated our old-school SVN repo into a sparkly new GitHub private repo. The benefits of that are a topic for another blog entry, but I promise you it’s been more than worth the seven bucks a month. GitHub have a great API, and part of it allows you to register for http/JSON notifications of various events, so I decided we should have notifications of various GitHub events posted to our jabber server. If you go into your GitHub repo settings and click on Service Hooks, you’ll see there’s a pre-built jabber hook – but it only accepts a username. I didn’t even try it out, but I assume it just sends event notifications to a jabber user – and I wanted it to go to our group room instead. Luckily, GitHub provide a generic WebHook option which allows you to receive JSON event notifications at your own web service.
Enter GitHub-XMPP. Well, actually, that didn’t exist a few days ago – but I realised I needed something which could accept GitHub event notifications and post them to our jabber room, so I wrote one. It was quite a fun little project, actually. On the way through, I discovered that the GitHub event JSON was woefully undocumented – and I also discovered json2csharp and json formatter and validator, which were both invaluable when exploring the json API and building a C# json deserializer. I’d also been meaning to take a look at Nancy, and this was the ideal opportunity.
The long and short of it is I now have an application (which I’m running under mono on our linux server) which can receive GitHub events and give our jabber group room a running commentary on what’s going on with our GitHub private repo. Push events, wiki updates, pull requests, issues – you name it, whatever’s going on, our faithful jabber GitBot tells our Software room what’s going on. I won’t cover the installation here – there’s a quickstart page on the project wiki.
I have plenty of plans for GitHub-XMPP – I want to turn it into a fully-featured, configurable, scriptable jabber bot, capable of being both a useful tool and a creative outlet for our team. For the time being, though, it’s functional – it serves the purpose of turning our fledgling jabber server from a place which shares what we’re saying into a place which also shares what we’re doing. GitHub-XMPP currently has somewhere between 15 and 20 hours in it – which means it’s already cost a great deal more than the $144/year we’re saving by not subscribing to Campfire. I built it on my own time, though, and not only did I have fun, I released it under the GPLv3 – so hopefully that $144 will be saved over and over, by teams with tight budget controls and open source projects.
I would encourage you to think about Campfire though – I haven’t used it myself, but I’ve heard so many great things about it I can’t wait to try it out. GitHub are using it for their internal team communication, and there aren’t many companies out there with a better finger on the pulse of modern software development than GitHub.
Please tell me about your own collaboration solutions, or if I helped you – I’d love to know I’m helping to keep other teams in touch and motivated!