{"id":73,"date":"2013-05-13T11:57:59","date_gmt":"2013-05-13T11:57:59","guid":{"rendered":"http:\/\/blog.rophuine.net\/coder\/?p=73"},"modified":"2013-05-13T12:24:41","modified_gmt":"2013-05-13T12:24:41","slug":"software-collaboration-using-jabber","status":"publish","type":"post","link":"http:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/","title":{"rendered":"Software Collaboration using Jabber"},"content":{"rendered":"<p>Software teams are often not in control of their own budgets. It&#8217;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&#8217;s nice to have free options for key team needs.<\/p>\n<p>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.<\/p>\n<p>Enter XMPP.<\/p>\n<p>If you don&#8217;t know what XMPP is, let me explain. It&#8217;s basically IRC with federated user account management. Is that clear? I&#8217;m going to call XMPP by its old name, Jabber, from here on in, because I think it&#8217;s easier.<\/p>\n<p>Think persistent chat rooms, private messaging, moderator privileges, all of that sort of thing &#8211; 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&#8217;t quite as schmick as Campfire, but there are open-source clients and libraries, so the sky&#8217;s the limit, really.<\/p>\n<p>We already did a lot of our communication using GTalk, and Google Talk works over jabber &#8211; so this seemed like an ideal option.<\/p>\n<p>The first thing I needed was a private XMPP server. It seems like there are two good free, open-source options out there: <a title=\"Openfire\" href=\"http:\/\/www.igniterealtime.org\/projects\/openfire\/index.jsp\">Openfire<\/a> and <a title=\"ejabberd\" href=\"http:\/\/www.process-one.net\/en\/ejabberd\/\">ejabberd<\/a>. I chose ejabberd, because the install seemed simpler &#8211; and let&#8217;s face it, there&#8217;s no point blowing hours of developer time to save $144\/year. We used a DigitalOcean VPS to host it (if there&#8217;s one thing <strong>every<\/strong> software team needs, it&#8217;s a linux box with a public IP address). The trickiest part was realising that I needed two different host names &#8211; 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&#8217;s a second thing <strong>every<\/strong> software team needs, it&#8217;s a DynDNS account). My authentication server runs on (let&#8217;s pretend our company acronym is ABC) abcim.dyndns.org, and the conference server is conference.abcim.dyndns.org &#8211; and thanks to a wildcard entry, I&#8217;m only using up one of our hostname entries.<\/p>\n<p>Installing and configuring ejabberd is left as an exercise for the user &#8211; 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.)<\/p>\n<p>Once you have a Jabber server up and running, you&#8217;re going to need a client. <a title=\"Pidgin\" href=\"http:\/\/pidgin.im\/about\/\">Pidgin<\/a> is the hands-down winner when it comes to administering jabber group rooms (or <a href=\"http:\/\/adium.im\/\">Adium<\/a> 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&#8217;s at for setting up a room, there are other clients which can cope with jabber group rooms &#8211; Jitsi seems decent, and Xabber make a sub-par but bearable Android client (the other jabber\/XMPP-enabled Android apps I&#8217;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.<\/p>\n<p>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&#8217;t prepared to stop there, however.<\/p>\n<p>One team member wasn&#8217;t keen on installing a native client. I can understand that &#8211; as developers, we push our machines to the limit, and we&#8217;re naturally suspicious of installing software on our machines. Down with bloat!<\/p>\n<p>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&#8217;t a dead end was <a title=\"Candy IM client\" href=\"http:\/\/candy-chat.github.io\/candy\/\">Candy<\/a>, which I hosted under Apache. I chose Apache instead of the other options because I&#8217;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&#8217;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.<\/p>\n<p>Even this wasn&#8217;t enough. I didn&#8217;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 &#8211; and for that, I needed to write some software.<\/p>\n<p>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&#8217;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&#8217;ll see there&#8217;s a pre-built jabber hook &#8211; but it only accepts a username. I didn&#8217;t even try it out, but I assume it just sends event notifications to a jabber user &#8211; 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.<\/p>\n<p>Enter <a title=\"GitHub XMPP Notifier Project\" href=\"https:\/\/github.com\/Rophuine\/GitHub-XMPP\">GitHub-XMPP<\/a>. Well, actually, that didn&#8217;t exist a few days ago &#8211; 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 &#8211; and I also discovered <a title=\"json2csharp\" href=\"http:\/\/json2csharp.com\">json2csharp<\/a> and <a title=\"json formatter and validator\" href=\"http:\/\/jsonformatter.curiousconcept.com\/\">json formatter and validator<\/a>, which were both invaluable when exploring the json API and building a C# json deserializer. I&#8217;d also been meaning to take a look at <a title=\"Nancy\" href=\"http:\/\/nancyfx.org\/\">Nancy<\/a>, and this was the ideal opportunity.<\/p>\n<p>The long and short of it is I now have an application (which I&#8217;m running under mono on our linux server) which can receive GitHub events and give our jabber group room a running commentary on what&#8217;s going on with our GitHub private repo. Push events, wiki updates, pull requests, issues &#8211; you name it, whatever&#8217;s going on, our faithful jabber GitBot tells our Software room what&#8217;s going on. I won&#8217;t cover the installation here &#8211; there&#8217;s a <a title=\"GitHub-XMPP quick start\" href=\"https:\/\/github.com\/Rophuine\/GitHub-XMPP\/wiki\/Getting-Started\">quickstart page<\/a> on the project wiki.<\/p>\n<p>I have plenty of plans for GitHub-XMPP &#8211; 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&#8217;s functional &#8211; it serves the purpose of turning our fledgling jabber server from a place which shares what we&#8217;re saying into a place which also shares what we&#8217;re doing. GitHub-XMPP currently has somewhere between 15 and 20 hours in it &#8211; which means it&#8217;s already cost a great deal more than the $144\/year we&#8217;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 &#8211; so hopefully that $144 will be saved over and over, by teams with tight budget controls and open source projects.<\/p>\n<p>I would encourage you to think about Campfire though &#8211; I haven&#8217;t used it myself, but I&#8217;ve heard so many great things about it I can&#8217;t wait to try it out. GitHub are using it for their internal team communication, and there aren&#8217;t many companies out there with a better finger on the pulse of modern software development than GitHub.<\/p>\n<p>Please tell me about your own collaboration solutions, or if I helped you &#8211; I&#8217;d love to know I&#8217;m helping to keep other teams in touch and motivated!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Software teams are often not in control of their own budgets. It&#8217;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&#8217;s nice to &hellip; <a href=\"http:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Software Collaboration using Jabber<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,6],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Software Collaboration using Jabber - Nerdhold Coder<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Software Collaboration using Jabber - Nerdhold Coder\" \/>\n<meta property=\"og:description\" content=\"Software teams are often not in control of their own budgets. It&#8217;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&#8217;s nice to &hellip; Continue reading Software Collaboration using Jabber &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\" \/>\n<meta property=\"og:site_name\" content=\"Nerdhold Coder\" \/>\n<meta property=\"article:published_time\" content=\"2013-05-13T11:57:59+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2013-05-13T12:24:41+00:00\" \/>\n<meta name=\"author\" content=\"Lionell Pack\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lionell Pack\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\",\"url\":\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\",\"name\":\"Software Collaboration using Jabber - Nerdhold Coder\",\"isPartOf\":{\"@id\":\"http:\/\/www.nerdhold.com\/coder\/#website\"},\"datePublished\":\"2013-05-13T11:57:59+00:00\",\"dateModified\":\"2013-05-13T12:24:41+00:00\",\"author\":{\"@id\":\"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/ca2988d5c0cb756a846e4d8c54e86b77\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"http:\/\/www.nerdhold.com\/coder\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Software Collaboration using Jabber\"}]},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/www.nerdhold.com\/coder\/#website\",\"url\":\"http:\/\/www.nerdhold.com\/coder\/\",\"name\":\"Nerdhold Coder\",\"description\":\"Tinkerings of a C# Coder\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/www.nerdhold.com\/coder\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/ca2988d5c0cb756a846e4d8c54e86b77\",\"name\":\"Lionell Pack\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/image\/\",\"url\":\"http:\/\/0.gravatar.com\/avatar\/9be7b23cd97814ac4a40b9b4d2955b5a?s=96&d=mm&r=pg\",\"contentUrl\":\"http:\/\/0.gravatar.com\/avatar\/9be7b23cd97814ac4a40b9b4d2955b5a?s=96&d=mm&r=pg\",\"caption\":\"Lionell Pack\"},\"sameAs\":[\"http:\/\/blog.rophuine.net\"],\"url\":\"http:\/\/www.nerdhold.com\/coder\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Software Collaboration using Jabber - Nerdhold Coder","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/","og_locale":"en_US","og_type":"article","og_title":"Software Collaboration using Jabber - Nerdhold Coder","og_description":"Software teams are often not in control of their own budgets. It&#8217;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&#8217;s nice to &hellip; Continue reading Software Collaboration using Jabber &rarr;","og_url":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/","og_site_name":"Nerdhold Coder","article_published_time":"2013-05-13T11:57:59+00:00","article_modified_time":"2013-05-13T12:24:41+00:00","author":"Lionell Pack","twitter_misc":{"Written by":"Lionell Pack","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/","url":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/","name":"Software Collaboration using Jabber - Nerdhold Coder","isPartOf":{"@id":"http:\/\/www.nerdhold.com\/coder\/#website"},"datePublished":"2013-05-13T11:57:59+00:00","dateModified":"2013-05-13T12:24:41+00:00","author":{"@id":"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/ca2988d5c0cb756a846e4d8c54e86b77"},"breadcrumb":{"@id":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.nerdhold.com\/coder\/2013\/05\/13\/software-collaboration-using-jabber\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/www.nerdhold.com\/coder\/"},{"@type":"ListItem","position":2,"name":"Software Collaboration using Jabber"}]},{"@type":"WebSite","@id":"http:\/\/www.nerdhold.com\/coder\/#website","url":"http:\/\/www.nerdhold.com\/coder\/","name":"Nerdhold Coder","description":"Tinkerings of a C# Coder","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/www.nerdhold.com\/coder\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/ca2988d5c0cb756a846e4d8c54e86b77","name":"Lionell Pack","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.nerdhold.com\/coder\/#\/schema\/person\/image\/","url":"http:\/\/0.gravatar.com\/avatar\/9be7b23cd97814ac4a40b9b4d2955b5a?s=96&d=mm&r=pg","contentUrl":"http:\/\/0.gravatar.com\/avatar\/9be7b23cd97814ac4a40b9b4d2955b5a?s=96&d=mm&r=pg","caption":"Lionell Pack"},"sameAs":["http:\/\/blog.rophuine.net"],"url":"http:\/\/www.nerdhold.com\/coder\/author\/admin\/"}]}},"_links":{"self":[{"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/posts\/73"}],"collection":[{"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/comments?post=73"}],"version-history":[{"count":7,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":80,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/posts\/73\/revisions\/80"}],"wp:attachment":[{"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/media?parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/categories?post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nerdhold.com\/coder\/wp-json\/wp\/v2\/tags?post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}