blog

2018 Gulaschprogrammiernacht and organizing sprints for XMPP

| categories: xmpp, converse, foss, omemo, plone

Recently I attended the Gulaschprogrammiernacht for the first time.

It's a hacker/maker event in the Zentrum für Kunst und Medien (Centre for Arts and Media) in Karlsruhe, Germany.

AFAIK it's organized by the local chapter of the infamous Chaos Computer Club.

I heard about it from Daniel Gultsch on Twitter. It sounded like fun, so I decided to attend and spend the time adding OMEMO support to Converse.

Guus der Kinderen and I intended to organize an XMPP sprint for that weekend in Düsseldorf, but we were cutting it a bit fine with the organization, so I hoped that we could just shift the whole sprint to GPN.

Unfortunately Guus couldn't attend, but Daniel and Maxime Buquet (pep) did and I spent most of the event hanging out with them and working on XMPP-related stuff. The developers behind the Dino XMPP client also attended and hung out with us for a while and there was someone working on writing an XMPP connector for Empathy in C++.

XMPP hackers at Gulaschprogrammiernacht

Maxime worked on adding OMEMO support, to Poezio, and Daniel provided us with know-how and moral support. Daniel worked mainly on the Conversations Push Proxy.

We had some discussions around the value of holding regular sprints and I told them about my experience with sprints in the Plone community.

The Plone community regulary organizes sprints and they've been invaluable in getting difficult work done that no single company could or would sponsor internally. To me it's a beautiful example of what's been termed Commons-based peer production.

The non-profit Plone foundation provides funding and an official seal of approval to these sprints, and usually a sprint has a particular focus (such as adding Python3 support). Sprints can range from 3 people to 30 or more.

One difference between the Plone and XMPP communities, is that Plone is a single open source product on which multiple companies and developers build their businesses, whereas XMPP is a standardized protocol upon which multiple companies and developers create multiple products, some open source and some closed source.

In both cases however there is a single commons which community members have an incentive to maintain and improve as they build their businesses around it.

Another difference is between the Plone Foundation and the XMPP Standards Foundation. The XSF, for better or worse, interprets its role and function fairly strictly as being a standards organisation primarily focused on standardising extensions to XMPP, and less on community building or supporting software development.

Despite these differences, I still consider sprints a great way to foster community and to improve the extent and quality of XMPP-related software and documentation.

There is an interesting dynamic between cooperation and competition in both the Plone and XMPP communities. Participants compete with one another but they also have the shared goal of maintaining and growing a healthy software ecosystem.

Maxime was particularly excited by our discussion and very quickly put word into action by planning and announcing an XMPP sprint in Cambridge, UK in August.

There's still time to vote on the date of the sprint and to suggest topics.

Hopefully this will be first of many more sprints and communit events.

Unmanned laptops at the Gulaschprogrammiernacht

Slack's bait and switch

| categories: xmpp, converse, foss, slack

Slack has finally decided to close down their IRC and XMPP gateways.

True to form, you can only read their announcement if you already have a Slack account and are logged in to a workspace.

Here's the gist of their announcement:

As Slack has evolved over the years, we've built features and capabilities —
like Shared Channels, Threads, and emoji reactions (to name a few) — that the
IRC and XMPP gateways aren't able to handle. Our priority is to provide a
secure and high-quality experience across all platforms, and so the time has
come to close the gateways.

They're of course being economical with the truth here.

Perhaps their XMPP gateway can't handle "Shared Channels" and "Threads", but that's because they purposefully stopped working on it.

A "Shared Channel" simply means a chatroom which people from outside your workspace can participate in. If a workspace is mapped to a members-only chatroom, then making something a shared channel simply means updating the members list or making the chatroom open (so anybody can join it).

Threads can be implemented by adding a <thread> element in the message stanza, as documented in XEP-201.

And emoji... there's nothing in XMPP that prevents people from sending emoji.

Note

UPDATE: Several readers have pointed out that "emoji reactions" and emoji are different things. Emoji reactions can be tacked to a particular message.

Still, there's nothing fundamental about XMPP that prevents emoji reactions, and work is currently underway to add support for them.

The protocol is designed to be eXtensible (hence the X in XMPP) and new features are continuously being added.

Classic bait and switch

We all know the real reason Slack has closed off their gateways. Their business model dictates that they should.

Slack's business model is to record everything said in a workspace and then to sell you access to their record of your conversations.

They're a typical walled garden, information silo or Siren Server

So they have to close everything off, to make sure that people can't extract their conversations out of the silo.

We saw it with Google, who built Gtalk on XMPP and even federated with other XMPP servers, only to later stop federation and XMPP support in favour of trying to herd the digital cattle into the Google+ enclosure.

Facebook, who also built their chat app on XMPP at first allowed 3rd party XMPP clients to connect and then later dropped interoperability.

Twitter, although not using or supporting XMPP, had a vibrant 3rd party client ecosystem which they killed off once they felt big enough.

Slack, like so many others before them, pretend to care about interoperability, opening up just so slightly, so that they can lure in people with the promise of "openness", before eventually closing the gate once they've achieved sufficient size and lock-in.

On Federation

When we talk about "federation" in networks, we mean the ability to communicate between different service providers.

For example, email is federated. You can set up your own email server, and then send emails to people with their own email servers, or to people with Gmail or Yahoo! accounts.

You can email any other email address in the world, regardless of where that email address is hosted.

If email never existed, and a company like Slack today would come out with this brand new concept of "Electronic Mail", let's call it digimail, do you think they would standardise the digimail protocol and allow you to send messages to other digimail purveyors?

We all know the answer to that. They won't, and neither would Google, Microsoft or Facebook.

Heck, Facebook is actively trying to replace email since years.

The reason email is federated, is because it was developed before surveillance capitalism was a thing and because it was established and entrenched long before these companies came around.

There's a reason why your email address is still the de facto way to sign up for any service on the web (sometimes with one or two degrees of separation), and it's because of federation.

XMPP is designed to allow federation. Think about that. Instead of having to sign up to various different chat providers, all which try to lock you in and monetize your conversations, you could instead have one chat account, and use that to chat with anybody else, regardless of which chat provider they are using.

Alas, that's the dream, but because XMPP came much later to the scene, it didn't develop the critical mass as email has, and here we are. With dozens of chat apps, all non-interoperable and closed off.

What would it take for XMPP to take off?

One of the sad things that has come out of Slack's meteoric rise to success, has been how many free and open source projects have jumped over to using it (after previously using IRC or XMPP).

In so doing, they have closed off their discussions from search engines and they prevent people from accessing their past archives.

Slack has many cool features, and they work very well, I'm not going to deny it.

However, the XMPP Software Foundation has done a lot of work in recent years to enable protocol extensions that provide features that people have come to expect from chat applications, for example:

Unfortunately XMPP clients have been lagging far behind in various respects.

One of the main problems is funding. The modern digital economy is largely set up around surveillance capitalism and user lock-in.

So attempts to create software that doesn't follow these precepts, often end up unfunded or underfunded.

However, our "weakness", is also our strength.

XMPP clients, and the XMPP network can provide something that Slack never can. Federation, free and open software, interoperability, extensibility and user choice.

Converse

For the last few years I've been working in my spare time on making a JavaScript XMPP chat client, called Converse.

Originally the idea was to make a Gtalk like chat client that you integrate in your website, and it can still be used like that.

A screenshot of Converse as overlayed chatboxes

However, in the last year I've updated it further so that it can also be used as a fullscreen application, like Slack is used.

You can try the fullscreen version at https://inverse.chat/

A screenshot of Converse as a fullscreen application

If you have no-one to chat to, then come join the discuss@conference.conversejs.org chat room.

This link will take you directly there (via inverse.chat): https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org

Converse still lacks lots of features that Slack has, but that's not because XMPP itself can't support those features.

What Converse however does have, is that it's free and open source software, based on a standard protocol and it can be extended, updated and improved upon, by anyone.

We're actively working on adding new features and more and more people are joining in.

Moreover, anybody can host it and you can integrate it into any website.

Ultimately, I believe in the power and utility of interoperability and software freedom, even though the current trend is to close off and lock down.

These information silos are as powerful as we make them. If enough projects choose standardised protocols and FOSS software, we will be able to create viable alternatives that foster freedom instead of lock-in.

Note

Hacker News discussion

This blog post triggered a lively discussion on Hacker news, you can read that here: https://news.ycombinator.com/item?id=16567009


Customizing and whitelisting SASL authentication mechanisms in Strophe.js

| categories: xmpp, strophe.js, foss, sasl

Introduction

If you've decided to read this fairly technical blogpost, then you probably have at least a rough idea what SASL is about and why one would want to create custom SASL auth mechanisms or whitelist the supported mechanisms.

I'll therefore provide just a very brief recap of the topics involved:

The Simple Authentication and Security Layer or SASL RFC 4422 is a framework for adding authentication support to connection-based protocols.

It provides an abstraction layer for authentication mechanisms, so that protocols, such as XMPP don't have to deal with the intricacies and complexities of supporting multiple authentication mechanisms.

It therefore makes auth mechanisms pluggable (if they are SASL compatible).

Strophe.js has supported SASL since a long time, but it didn't provide an easy way add custom SASL mechanisms, or to whitelist the mechanisms to be used.

Until now... or rather, since the 1.2.9 release.

Creating a custom SASL auth mechanism

To create a custom SASL authentication mechanism is fairly simple.

You can glean what's required by simply looking at how the default mechanisms are created.

See for example how the SASLPlain mechanism is defined.

And look as the SASLMechanism prototype to see the interface that the mechanism supports.

Perty much it boils down to creating constructor, settings its prototype to an invoked Strophe.SASLMechanism instance, providing its name, a boolean to indicate whether it should proactively respond without an initial server challenge, and an integer value specifying its priority amongst the supported mechanisms.

The default mechanisms and their respective priorities are:

  • EXTERNAL - 60
  • OAUTHBEARER - 50
  • SCRAM-SHA1 - 40
  • DIGEST-MD5 - 30
  • PLAIN - 20
  • ANONYMOUS - 10

Then it's a matter of implementing onChallenge and any of the other methods provided by the SASLMechanism prototype.

onChallenge is called once the server challenges the client to authenticate itself or proactively if the mechanism requires that the client initiates authentication (configured with the isClientFirst parameter of Strophe.SASLMechanism).

So, lets create a fictional auth mechanism called SASL-FOO which works similarly to SASL-PLAIN, except that the password is encrypted with double-encoding ROT13 (hint: this is a joke).

We would then create the authentication mechanism like so:

Strophe.SASLFoo = function() {};
Strophe.SASLFoo.prototype = new Strophe.SASLMechanism("FOO", true, 60);

Strophe.SASLFoo.prototype.onChallenge = function(connection) {
    var auth_str = connection.authzid;
    auth_str = auth_str + "\u0000";
    auth_str = auth_str + connection.authcid;
    auth_str = auth_str + "\u0000";
    auth_str = auth_str + DoubleROT13(connection.pass);
    return utils.utf16to8(auth_str);
};

Whitelisting the supported SASL auth mechanisms

Now with SASL-FOO in hand, we can whitelist the supported authentication mechanisms by specifying a list of mechanisms in the options map passed in when we instantiate a new Strohe.Connection.

var service = 'chat.example.org';
var options = {
    'mechanisms': [
        SASLFoo,
        Strophe.SASLPlain
    ]
};
var conn = new Strophe.Connection(service, options);

Bonus: Whitelisting SASL auth mechanisms in Converse.js

Due to the above changes it'll also be possible to whitelist SASL mechanisms in Converse.js (version 2.0.1 and upwards).

This is done via the connection_options configuration setting:

converse.initialize({

    connection_options: {
        'mechanisms': [
            converse.env.Strophe.SASLMD5,
            converse.env.Strophe.SASLPlain
        ]
    },
});

Strophe.js and Converse now support passwordless login with client certificates

| categories: xmpp, converse, sasl, strophe.js, foss, openfire

Introduction

Did you know that x509 certificates, the certificates that webservers use to prove their identity during the establishment of an HTTPS connection, can also be used by a client (like your webbrowser) to prove its identity, and even to authenticate?

I'm talking here about so-called client certificate authentication.

Client certificate authentication is especially popular in environments with high security requirements. They can even be used to enforce 2-factor authentication, if in addition to a client certificate you also require a password. That usecase is however out of scope for this blog post.

With the release of Strophe.js 1.2.8, it's now possible to have passwordless login with TLS client certificates in Converse and any other Strophe.js-based webchat projects.

For Converse, you'll need at least version 2.0.0.

Here's what it looke like:

Logging in with an SSL client certificate

The technical details and background

XMPP and SASL

The XMPP logo

XMPP supports authentication with client certificates, because it uses SASL (Simple Authentication and Security Layer).

SASL provides an abstraction that decouples authentication mechanisms from application protocols.

This means that XMPP developers don't need to know about the implementation details of any authentication mechanisms, as long as they conform to SASL.

Up til version 1.2.7, Strophe.js supported the SASL auth mechanisms: ANONYMOUS, OAUTHBEARER, SCRAM-SHA1, DIGEST-MD5 and PLAIN.

For client certificate auth, we need another SASL mechanism, namely EXTERNAL. What EXTERNAL means, is that authentication happens externally, outside of the protocol layer. And this is exactly what happens in the case of client certificates, where authentication happens not in the XMPP layer, but in the SSL/TLS layer.

Strophe.js version 1.2.8 now supports SASL-EXTERNAL, which is why client certificate authentication now also works.

How do you communicate with an XMPP server from a web-browser?

There are two ways that you can communicate with an XMPP server from a web-browser (e.g. from a webchat client such as Converse).

  1. You can use XMLHttpRequests and BOSH, which you can think of as an XMPP-over-HTTP specification.
  2. You can use websockets.

Both of these protocols, HTTP and websocket, have secure SSL-reliant versions (HTTPS and WSS), and therefore in both cases client certificate authentication should be possible, as long as the server requests a certificate from the client.

I'm going to focus on BOSH and HTTPS, since this was my usecase.

The HTTPS protocol makes provision for the case where the server might request a certificate from the client.

Note

NOTE: Currently the only XMPP server that supports client certificate authentication with BOSH is Openfire, and funnily enough, only Openfire 3. In Openfire 4, they refactored the certificate handling code and broke client certificate authentication with BOSH. I've submitted a ticket for this to their tracker: https://issues.igniterealtime.org/browse/OF-1191

The authentication flow

So this is how the authentication flow works. I'll illustrate how the authentication flow works by using actual log output from Converse

Note

NOTE: My XMPP server's domain is called debian, because I was running it on a Debian server and because naming things is hard. In hindsight, this wasn't a good name since it might confuse the dear reader (that means you).

2016-09-15 12:07:05.481 converse-core.js:128 Status changed to: CONNECTING

Firstly, Converse sends out a BOSH stanza to the XMPP server debian, to establish a new BOSH session.

2016-09-15 12:07:05.482 converse-core.js:128
    <body rid="1421604076"
          xmlns="http://jabber.org/protocol/httpbind"
          to="debian" xml:lang="en" wait="60"
          hold="1" content="text/xml; charset=utf-8"
          ver="1.6" xmpp:version="1.0"
          xmlns:xmpp="urn:xmpp:xbosh"/>
2016-09-15 12:07:06.040 bosh.js:749 XHR finished loading: POST "https://debian:7445/http-bind/"

The above stanza was sent as an XMLHttpRequest POST, and the above XML was sent as the Request Payload.

Strophe.js takes care of all this, so nothing to worry about, but sometimes digging through the internals is fun right? Right?!

2016-09-15 12:07:06.042 converse-core.js:128
    <body xmlns="http://jabber.org/protocol/httpbind"
          xmlns:stream="http://etherx.jabber.org/streams" from="debian"
          authid="fe0ee6ab" sid="fe0ee6ab" secure="true" requests="2"
          inactivity="30" polling="5" wait="60"
          hold="1" ack="1421604076" maxpause="300" ver="1.6">
        <stream:features>
            <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
                <mechanism>EXTERNAL</mechanism>
            </mechanisms>
            <register xmlns="http://jabber.org/features/iq-register"/>
            <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
            <session xmlns="urn:ietf:params:xml:ns:xmpp-session">
                <optional/>
            </session>
        </stream:features>
    </body>

So now the XMPP server, debian, has responded, and it provides a list of SASL mechanisms that it supports. In this case it only supports EXTERNAL.

Luckily our webchat client supports SASL-EXTERNAL, so it responds in turn and asks to be authenticated.

2016-09-15 12:07:06.147 converse-core.js:128
    <body rid="1421604077" xmlns="http://jabber.org/protocol/httpbind"
          sid="fe0ee6ab">
        <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl"
              mechanism="EXTERNAL">dXNlcjAxQGRlYmlhbg==</auth>
    </body>

Now here comes the tricky part. The XMPP server's BOSH servlet, asks the webbrowser (which is establishing the HTTPS connection on our behalf) to give it the client certificate for this user.

The webbrowser will now prompt the user to choose the right client certificate. Once this is done, the XMPP server authenticates the user based upon this certificate.

2016-09-15 12:07:06.177 bosh.js:749 XHR finished loading: POST

2016-09-15 12:07:06.180 converse-core.js:128
    <body xmlns="http://jabber.org/protocol/httpbind" ack="1421604077">
        <success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
    </body>

The XMPP server responds with success and we're logged in!

How to set up client certificate authentication with Converse and OpenFire 3.10.3

Note

NOTE: Thanks goes out to Dennis Shtemberg from Infusion, who initially tested client certificate authentication with BOSH on Openfire and on whose notes the following is based.

1. Install Openfire 3.10.3

The XMPP logo

On Debian(-based) Linux, you can simply do the following:

wget http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3.10.3_all.deb
sudo dpkg -i openfire_3.10.3_all.deb

2. Configure Openfire's system properties

Open the admin console: http://localhost:9090/ (where localhost is the host the server is running on)

Navigate to Server > Server Manager > System Properties and add the following properties:

Property Value
xmpp.client.cert.policy needed
xmpp.client.certificate.accept-selfsigned true
xmpp.client.certificate.verify true
xmpp.client.certificate.verify.chain true
xmpp.client.certificate.verify.root true
sasl.mechs EXTERNAL

Make sure the xmpp.domain value is set to the correct host. If you're running Openfire on localhost, then you need to set it to localhost. If you're not using localhost, then replace all mention of localhost below with the xmpp.domain value.

3. Lay the groundwork for generating an SSL client certificate

First, make sure you have OpenSSL installed: aptitude install openssl Then create a directory for certificate files: mkdir ~/certs

Now create a config file called user01.cnf (~/certs/user01.cnf) with the following contents:

[req]
x509_extensions = v3_extensions
req_extensions = v3_extensions
distinguished_name = distinguished_name

[v3_extensions]
extendedKeyUsage = clientAuth
keyUsage = digitalSignature,keyEncipherment
basicConstraints = CA:FALSE
subjectAltName = @subject_alternative_name

[subject_alternative_name]
otherName.0 = 1.3.6.1.5.5.7.8.5;UTF8:user01@localhost

[distinguished_name]
commonName = user01@localhost

The otherName.0 value under subject_alternative_name assigns the user's JID to an ASN.1 Object Identifier of "id-on-xmppAddr". The XMPP server will check this value to figure out what the JID is of the user who is trying to authenticate.

For more info on the id-on-xmppAddr attribute, read XEP-178.

4. Generate an SSL client certificate

  • Generate a self-signed, leaf SSL certificate, which will be used for client authentication.

    • Generate a private RSA key

      openssl genrsa -out user01.key 4096

    • Generate a sigining request:

      openssl req -key user01.key -new -out user01.req -config user01.cnf -extensions v3_extensions

      • when prompted for a DN enter: user01@localhost
    • Generate a certificate by signing user01.req

      openssl x509 -req -days 365 -in user01.req -signkey user01.key -out user01.crt -extfile user01.cnf -extensions v3_extensions

    • Generate PKCS12 formatted certificate file, containing the private key and the certificate. This will be the client certificate which you will log in with.

      openssl pkcs12 -export -inkey user01.key -in user01.crt -out user01.pfx -name user01

      • when prompted for export password enter: user01

5. Install the PKCS12 certificate on your local machine

Double click the pfx file and follow the steps to import it into your machine's keystore.

6. Import the x509 certificate into Openfire

sudo keytool -importcert -keystore /etc/openfire/security/truststore -alias user01 -file ~/certs/user01.crt sudo keytool -importcert -keystore /etc/openfire/security/client.truststore -alias user01 -file ~/certs/user01.crt sudo systemctl restart openfire

Note

NOTE: The default keystore password is "changeit"

7. Create the user associated with the SSL client certificate

Go back to Openfire admin console, navigate to Users/Groups > Create New User and create a new user.

  • Username: user01
  • Password: user01 (This is not controlled by Openfire).
  • Click Create User

8. (When using Java 1.7) Patch Openfire

When trying to log in, I received the following error:

2016.09.08 00:28:20 org.jivesoftware.util.CertificateManager - Unkown exception while validating certificate chain: Index: 0, Size: 0

Turns out the likely cause for this is the fact that I was using the outdated Java version 1.7.

At the time, I didn't know that Java is the culprit, so I patched the following code

If you read the comments in the link above, you'll see there are two sections, with one being outcommented. I swopped out the two sections, and then recompiled Openfire.

After that, client certificate auth worked. The best way to avoid doing this is apparently to just use Java 1.8.

9. Test login with Converse

The Converse logo

Now you're done with setting up Openfire and you can test logging in with Converse.

Download the latest version of Converse from the releases page.

To hide the password field (since the password won't be checked for anyway), you need to open index.html in your text editor and add authentication: 'external to the converse.initialize call.

Then open index.html in your browser.

In the Converse login box, type the JID of the user, e.g. user01@localhost and click login.

Note

NOTE: If things go wrong, pass debug: true to converse.initialize, then open your browser's developer console and check the output. Check especially the XHR calls to http-bind. Checking the output in the Network tab can also be very helpful. There you'll see what Openfire responds to requests to its BOSH URL.

Conclusion

Client certificate authentication is a bit of a niche requirement, doing so with BOSH/HTTP even more so.

However, I expect webchat XMPP clients to become more and more prevalent in the coming years, even on the desktop, for example when packaged with Github's Electron (an Electron version of Converse is planned BTW, based on the fullscreen version inverse.js).

The fact that this works because of SASL-EXTERNAL authentication being added to Strophe.js means that this functionality is not only possible in Converse, but all webchat clients built on Strophe.js (granted that they use version 1.2.8 or higher).

Unfortunately XMPP server support is lacking, with only Openfire supporting this usecase currently, and not yet (at the time of writing) in the 4.0.x branch. To see whether this gets fixed, keep an eye on the relevant ticket


Open Source software and the expection of free labor

| categories: foss, open-source, economics

Over the last few years of starting and then maintaining an open source project that has received a decent amount of attention, converse.js, I've noticed some interesting things about the expectations some people have towards developers who work on FOSS (free and open source software).

Predictably irrational

Book cover: Predictably irrational

People of course love to receive something for nothing. Dan Ariely, in his book "Predictably Irrational" illustrates some of the biases people have when it comes to free stuff. When confronted with the words "free" (as in gratis), people do things that are irrational and are at odds with how a rational actor (the mythical homo economicus) is expected to behave, which is the bedrock upon which most economic theories are based.

The outcome of the various studies Ariely conducted was consistent: when faced with multiple choices, the free option was commonly chosen. With the opportunity to receive something for free, the actual value of the product or service is no longer considered. [1]

“Most transactions have an upside and a downside, but when something is FREE! we forget the downside. FREE! gives us such an emotional charge that we perceive what is being offered as immensely more valuable than it really is.”

Dan Ariely

The biases regarding "FREE!" apply not only to monetary costs, but also to time. We forgo some of our time when we wait in line for free popcorn or to enter a museum on a free-entrance day. We could have been doing something else at that time, so there's a resultant opportunity cost. [1]

Freedom isn't free, it costs folks like you and me

[2]

These biases of course can also come into play when people evaluate free (as in beer) software. In the same way that people didn't take into consideration the cost of the time they spend in trying to get something for "free", people often also don't consider the non-monetary costs of using FOSS.

A common retort that usually surfaces on Slashdot, Reddit or Hacker News whenever a discussion around using a Linux distribution on the Desktop takes place, is “Linux is only free if you don't value your time”.

That's of course completely true. I do value my time, took that into consideration and still concluded that I want to use GNU/Linux and free and open source software.

Using FOSS requires a certain amount of commitment, and it should be clear to the user why they are willing to go that route (freedom from vendor-locking, the ability to control and keep private your data, the ability to modify the code to your liking etc.).

I think people have been hyping the "FREE!" aspect of FOSS way too much.

Software for nothing and your support for free

[3]

Note

Disclaimer

I consider a certain amount of support and maintenance as a requirement for a successful open source project and not something you (as the developer) can ignore.

I try to channel bug reports and feature requests to the Github issue tracker and general support questions to a mailing list, where hopefully other people would also be willing to share the load by answering questions.

So while I complain about people wanting "something for nothing" below, I invariably mean people who write to me directly, instead of on the issue tracker and who are often trying to get me to work on something right away.

So, when considering that many people don't properly evaluate the costs involved in using FOSS, some requests and emails that I sometimes receive start to make sense.

“Please guide me”

One common recurrence, is to be contacted by someone who is integrating converse.js into a project for a paying client, and somehow got stuck. Perhaps they didn't read the docs or perhaps they don't have the requisite technical skills to do the job. These emails sometimes have a pleading, desparate tone to them. Perhaps to instill some sense of guilt or obligation or perhaps just because the person is really desperate and under time pressure.

What gets me every time however, is that as far as I can tell, these are people working for commercial businesses who get paid for the work they do. They then trawl the web looking for hapless FOSS developers to do their work for them for free, or as expressed in the commonly used phrase in these kinds of emails: “Please guide me”.

The novelty and warm fuzzy feeling of altruistically helping strangers solve their problems disappears like mist before the sun when you realise that they're getting paid for the work you're doing for them right now.

And make no mistake about it, maintenance and support for an open source project is work and sometimes even drudgery. The fun part is writing new code or trying out new things, not helping people who can't be bothered to study the documentation.

We need a feature and we hope you'll do it for free

Another common theme is emails where people somehow just assume that I'll implement some feature for them. At first this presumptuousness startled me.

I think it's totally fair to ask when the project is charitable and the people involved don't receive any payment themselves, but that's often not the case.

Instead, the underlying assumption appears to be that I love working on open source projects so much that I'll do it all for free and that I don't have ideas on what to work on next.

Sometimes people qualify their requests by stating that they're a small non-profit. Non-profits do however pay out salaries, don't they?

I'd be willing to reduce my hourly rate when working for a non-profit with a good cause, but I'm most likely not going to do work for free.

The software is free, but the time spent working on it costs money

A nuance that's perhaps lost on many people, is that I have often worked on converse.js for money. There was a rather long "bootstrapping" phase in the beginning where the project wasn't good enough for anyone to actually use or pay money for further development, but after the project stabilized I started getting small paying gigs of custom development on converse.js.

In all cases I made it clear that the Mozilla Public License forces me to open source any changes I made to the covered files, and therefore the work I did for these paying customers (bless their hearts) was open sourced as well.

The point is that while the software is free (as in beer and as in speech), the time spent working on it costs money.

Either someone else pays me to spend my time working on it, or I end up paying by doing something for free while I might be getting paid doing something else (opportunity costs) or by taking time away from other activities.

FOSS development costs money, either the developer is commissioned, or they pay for it themselves (perhaps unwittingly).

Doing work for free devalues it and takes the piss out of actual paying customers

The last point I'd like to make, is that by taking on these requests to do free work for commercial entities (and non-profits), I'm not only devaluing my work, but I'm also disincentivising paying customers (which includes non-profits).

After all, why would anyone pay me to do anything if I'm so eager to please that I'll do it all for free?

The only reason I could see to do that, is to get that mythical "exposure" that's often also sold to web and graphic designers.

The Oatmeal comic: "Exposure"

[4]

So what do you do if you need work done and can't pay for it?

Free and open source software is a beautiful, world-changing and paradigm shifting idea. However, software developers, like all people, need to be paid for their work, also when they work on FOSS.

If you can't pay for software development, then you can still try to incentivise FOSS developers in other ways, but be aware that it'll be more difficult.

One important lesson that I'm glad I learned early in life, is that when you're asking someone to do something for you, then you need to explain to them why it's in their best interests to do so.

People inherently look out for themselves. It's perfectly natural and doesn't necessarily mean they're selfish to the point of being anti-social, it just means that they need to take care of themselves and that they can't expect other people to do it for them or to even have their best interests at heart.

So when desiring something from someone, such as their help, the best approach is to explain to them what's in it for them

For example, if you want a friend to help you out with something, let's say to join a beach cleanup project, you don't tell them why it'll be good for you, you explain to them that it'll be an opportunity to chat, to meet new people, to go for a swim and to have the enjoyment of a clean unspoiled beach.

This is simple stuff, but many people apparently don't know this.

So if you want someone to help you with a software project, explain to them why it would be in their best interest. If you can't find a reason why, then perhaps it's actually not in their best interest and you need to create an incentive for them.

Money works pretty well as an incentive, but there are other ways as well. One sure-fire way to build up goodwill and gratitude (that might translate into more help and assistance) is to contribute. If you can't write code, fix typos in the docs, evangelize the project or contribute in other areas which you have some expertise, like translations, design, UX, helpful feedback etc.

FOSS development is a community effort and a team sport. There'll always be people who try to take more than they give, but on average, humans are matchers. When given something, they want to reciprocate and give back. Keep that in mind when you're trying to get something for nothing.

References

[1](1, 2) Wikipedia article on Predictable Irrational
[2]Sung to the tune of Freedom isn't free
[3]Sung to the tune of "Money for nothing" by Dire Straits.
[4]From The Oatmeal

Next Page »