buddycloud
buddycloud
Buddycloud Blog
123 posts
Secure messaging for apps. Tools, libraries and services for secure cloud & on-premise user and group messaging. Saves time. Scales up. Supports you. http://buddycloud.com/
Don't wanna be here? Send us removal request.
buddycloud · 10 years ago
Video
youtube
In-app messaging: Evolving APIs to Protocols
Buddycloud took part of Kamailio World Conference 2015, sharing what’s new and exciting in the real time communications. You can now watch Buddycloud’s talk on APIs and Protocols here: https://www.youtube.com/watch?v=LyZq8jZaJ7U or the open discussion panel moderated by Randy Resnick, Founder VoIP Users Conference: https://www.youtube.com/watch?v=hlPxBnCaXg0.
Thank you Daniel and the rest of the Kamailio World team for organizing everything! We had a great time at the event and look forward to joining again next year. 
1 note · View note
buddycloud · 10 years ago
Text
10 Day Challenge: Build a mobile social network
Scoping the features
We've already had a few conversations about what Project Isizwe wants to achieve.
We are helping them create the backend messaging for ‘WiFi Chat’. Wifi-Chat is a localised social network which allows the Government to have real-time conversations with citizens and opens up the opportunity to meet and chat online.
There are a few ways to think about how we plan the features in a limited time span:
perfect code, but nothing shipped
completely hacked code, but shipped
perfect code, with some working features and the rest on a road map
We decided on option 3.
So we sat down with the Isizwe team to talk through the launch features and are now working to get them written.
Tumblr media
In terms of helping the end-user, we came up with the following features:
status sharing (similar to twitter),
Buddycloud channels for different conversations,
users will be able to create their own profile on WiFi Chat and upload an avatar (pic),
government will be able to create Chat Channels for any relevant discussion topic that they would like,
users will be able to join these Chat Channels and provide real-time feedback,
government will be able to create individual channels for each District, Municipality, City or Town under which multiple chat discussions will be ongoing.
(our working document)
Wifi-Chat's features are interesting because we're having to design it for very low-end devices. We also have to account for some users that might not have used such a service before. This shows up in the little design elements: a "hamburger menu" is replaced with just text saying "menu". We'll find out more on Monday when we meet some future users.
In other news, we're staying at a lion farm, eating lots of biltong and enjoying the weather.
Tumblr media
You can follow our code at https://github.com/project-isizwe/wifi-chat and infrastructure at https://github.com/buddycloud/buddycloud-vm
1 note · View note
buddycloud · 10 years ago
Text
10 Day Challenge: Build a mobile social network
Tomorrow morning some of the Buddycloud team departs from Berlin, Germany, for Johannesburg, South Africa.
We're excited to build a production-ready mobile social network for Project Isizwe, including user and group communication: backend, frontend, message synchronisation in just 10 days. This is amazingly fast and we're up against a very tight schedule.
Tumblr media
Background
Project Isizwe provides free WiFi to township residents and has 500K users on their free wifi service. Now they want to help their users communicate, help and share information with each other. And more...  
Project Isizwe identified a big problem with how their users are being ignored by the government. They noticed two things:
there is no effective forum for feedback and debate between residents and the Government and,
the younger residents don’t feel they are heard through traditional government channels.
For example, younger residents never attend town-hall meetings and this leads to their voice being lost in the decision making.
The Project Isizwe team designed a solution called Wifi Chat and asked Buddycloud to help them with in-app messaging and social infrastructure to power this.
Tumblr media
Wifi Chat will provide a real-time, secure and easy to use set of channels and site for informing citizens of new developments or topics and receiving feedback, input and comments.
Because messaging is really important to Project Isizwe's strategy, they wanted to build wifi-chat as open source using open standards. This will enable their developers  to extend the Buddycloud to new in-house apps. For example, various city Governments could integrate their own communication channels into one service.
They had us at "open and extensible" and we offered to jump in and help and learn about their requirements.
Deciding to use a ready-made backend like Buddycloud has immediately saved at least a year of development time. That means our time in SA can be used to just spin-up a ready-made Buddycloud stack on their network and leaves us free to focus on developing the frontend.
And so to the frontend: we're up against some interesting challenges:
lots of low end devices
web only
To give you an idea of the devices we're dealing with here's a selection:
Phone modelShareOSVersionScreen size Huawei Y220-U0011.3%Android2.3320x480 Samsung GT-S5280 Galaxy Star4.5%Android4.1.2240x320 Vodafone VF685 Smart Kicka4.3%Android4.4320x480 Nokia Lumia 5204.2%Windows Phone8@2_240x400 Samsung GT-S5301 Galaxy Pocket Plus3.7%Android4240x320 ZTE V7953.2%Android2.3320x480 BlackBerry Z102.8%BlackBerry10@2_384x640
This week we've been thinking about how to best create a realtime messaging solution on resource constrained devices. We've been going backwards and forwards on Angular, Backbone and other Javascript frameworks to work out what will best suit this project and enable us to ship in 10 days.
We're going to work some magic...
For quick spin-up of the backend, we'll be using the Buddycloud-vm project to generate and orchestrate new server images for testing and production servers.
For the next 10 days we'll be posting a daily development report covering the the technical challenges. You can start following our code progress starting on Monday as we push to https://github.com/project-isizwe/wifi-chat
Felix has already started working his interface magic and we'll be posting more images as they fly off his machine.
See you on Monday!
0 notes
buddycloud · 10 years ago
Text
Announcing Buddycloud-VM: everything you need to run Buddycloud on premises.
The Buddycloud virtual machine helps developers test and deploy Buddycloud.
While Buddycloud hosting is a great way to start building and testing in-app communication, sometimes you need more flexibility than cloud hosting.
The buddycloud-vm is a good way to spin-up your own on-premises messaging stack.
We have designed the buddycloud-vm to be flexible enough to build and deploy into your workstation or to deploy remotely into your own datacenter/ Amazon/Google/Digital Ocean servers.
Grab the latest version off Github. Community support is always available in the Buddycloud chatroom.
0 notes
buddycloud · 10 years ago
Text
In-app messaging: what’s next?
Tumblr media
(photo credit: Doc Searls - silos)
Benedict Evans writes that the three phases of messaging were always about unbundling expensive services based on price arbitrage. But what comes next?
Phase 1: Unbundling International voice calling. Remember how prohibitive calls across a border were? Skype won this!
Phase 2: Unbundling Mobile-based messaging. SMS was squeezed by BBM and similar services. The competing services force operators to compete: 10c/SMS collapses to "unlimited SMS" packages. Line, WhatsApp and a hundred others messaging services bloom.
We are now at Phase 3
Phase 3: The generic data layer. "Why can't we just communicate between services?" To use Benedict's example, "Why is it that if I use a cab service app I can only talk to the driver by a PSTN voice call or SMS? Why does a restaurant booking app send me out to the phone dialer?" Phase 3 will play out with Apps just as WhatsApp will, but with  live voice and SMS, being unbundled. WebRTC goes some way to providing a data layer between devices. WebRTC is the a BYOS (bring your own signalling) transport.
Messaging is quite hard to get right which is why tools like Facebook Developer tools, Layer, ChatCenter and Buddycloud exist; they help developers add messaging to apps.
When every mobile and web developer can easily add messaging to their app, the power of WhatsApp’s et al.’s ad-hoc messaging communities will shift to specialist apps. 
The next unbundling will start on the long tail of messaging: if the fat head of messaging is WhatsApp and Line, the long tail is the tens of thousands of apps that include a way for users to communicate. The long tail includes the AirBnB app where a guest communicates with their host, the Uber app that connects the driver with the passenger and the kidney-disease-support-group app where patients message each other. And thousands more.
The unbundling, as with the previous two phases, will be bottom-up: developers experimenting on weekend projects, apps emerging from studios, and the “fat-head” of mainstream messaging apps being replaced.
Messaging is now free
Now we're in a world where messaging is essentially free (both to use and to run) and we're also in a world where every developer likes to invent their own messaging service. There's also a race to offer ever cheaper messaging backends to developers. With WebRTC built into every browser, we can assume we've reached free. If one subscribes to Peter Thiel's Zero to One thinking: this would be the globalisation stage of messaging.
What’s coming next
Phase 4: unbundling the silos
To understand how the next stage plays out, it's useful to look 30-odd years ago at the roots of, arguably the world's most successful app, email.
Back in, Eric Allman's sendmail pulled together email from the UUCP network, ARPAnet mail and BerkNet mail systems into one unified system. Users no longer needed to switch between systems to contact other users outside of their mail silo.  Eric created a flattened namespace and service to route messages between silos: he federated incompatible messaging silos. And while some of the addressing looked odd (domain!user), users didn't have to log in and out of different systems to communicate. Eric's design also meant that organisations could easily join the mail network simply by using an agreed-upon protocol.
The ecosystem of email succeeded because it was an open protocol, implementable by others (sendmail was open source) and most importantly it federated between sites. Back in the pre-cloud days it was also "on-premises".
Applying this sea change from 30 years ago to messaging: messaging will be apps built on a flat namespace with backend services that interconnect. The specialised silos will still exist but interconnect (Compuserve mail eventually interconnected with AOL mail and even SMTP based email).
No more: I'm greg99 on this service but if you want to reach me on Wire then I'm greg.watson and on this other service I'm known by my phone number. The future will be just [email protected] everywhere: [email protected]  on Future-instagram(tm), [email protected] on future-twitter(tm) and  [email protected]  on cat-social-network(tm).  Some might call this "bring your own identity" (BYOI).
Summary: The fourth phase of messaging will be federation of the silos using an open protocol with a flat user namespace.
Working on the Fourth Phase
At Buddycloud we're trying to work on this fourth phase, a "generic data layer" and signaling for messaging. Developers can add the stack to their apps and save development time. Moreover they plug into a larger ecosystem of existing users and services.
If Buddycloud does its job well, we help other companies grow the ecosystem too (for example Surevine Ltd produces a really nice Buddycloud frontend for security-sensitive customers).
From working with customers, we have noticed is that it's really important for customers to be able to extend messaging.  Developers seek more than one-size-fits-all messaging. For example we find that developers each want different message formats and different application logic on the backend.
We also notice that, security is really important - this usually plays out as customers wanting on-premises deployments (for example, the finance or healthcare industries).
Another thing that we have discovered: communication needs to extend beyond the firewall of each enterprise: Imagine only being able to email people inside your organisation. (Remember only being able to email other uses on compuserve - never outside?) It’s quite conceivable to need to communicate with a supplier. When viewed like this network federation is a natural extension of any communication network.
We're working on Building the fourth phase of communication at Buddycloud. Realtime messaging and video calling between users on any network, anywhere in the world should become as natural as email.
PS: we’re looking for smart engineers to join the team.
0 notes
buddycloud · 10 years ago
Text
Setting up Your "Office Stack"
Open Source Principles versus Getting Things Done
Imagine you are starting a new company: you have a team in-house and around others scattered around the world.
I set up the tools for another company 6 years ago.  And was doing it again recently for Buddycloud. And how times have changed.
In light of recent spying events, code developed in a transparent manner (usually open source) is increasingly important. Being free both in dollar terms and in time spent talking to a sales team is also a huge win. But setting up and managing an open source office stack can quickly become a time-sink.
Here's a quick retrospective to how we used to (about 6 years ago) set up team collaboration. And how we've done it today at Buddycloud HQ.
Source Code and Issue Tracking
Then: Apache+SVN+LDAP+WebSVN+Trac
Details are sketchy, but I remember the pain level was high. "Back in the day" one rolled with  subversion <shudder if you will>, fronted by Apache and some kind of LDAP authentication. That got you source control.
For bonus points and to view your code, you'd install WebSVN. Oh, dark days! Of course, you'd want to track bugs: Trac was the go-to tool for this. And came with a whole new set of dependencies. These were all cutting edge back then.
Now: 
Tumblr media
Let's be clear - we weren't going near SVN for source code wrangling. All of the Buddycloud repositories are based on GitHub. It's hard to remember the pre-GitHub existence. As one of the best platforms to share code, GitHub offers us the chance to share all of our projects online, forming a straightforward flow to collaborate together in solving issues, commenting proposals and improving the code of our projects. And there's no need to configure apache virtual hosts or buy SSL certificates for svn.example.com.
Currently, we have nearly 40 repositories. And almost zero admin overhead.
Team Organisation
Then: Hire a project manager
Just a few years ago one would hire full-time cat-herders^WW project managers to look after a product team. Their task was to help the team answer "what should I do next?", "what's the big picture?", "what are my colleague working on?"
To answer these questions would take lots of meetings. Some of the worldwide team would be waking up early to jump on team calls. And some would be staying up late to synchronise plans. Add in meetings digging into deep-hack-mode time and you quickly have a non-developer friendly environment.
Now:
Tumblr media
Trello tasks are added to different topic boards, you tag your work colleagues to them, set up due dates so you get reminded when you have to get your tasks finished and get notifications according to your interests, amongst many other features.
There's 101 organisation tools out there: We use Trello because of its simple, but effective approach as an agile task tracking/planning tool [and it's free].
I also highly recommend using Trello on your phone to get into a GTD-type workflow and free up your mind: quickly capture thoughts and tasks for when you are back at your desk.
Email, Calendaring and Documents
Then: roll it yourself: Postfix, Cyrus, Amavisd, OpenOffice and trying new open-source calendaring apps every week.
There was a day when setting up an office involved: Order server from Dell, Install Linux, Setup Postfix, hope you weren't on a DNSBL, configure something else in /etc that you kinda understood but could never be totally sure about, tweak, configure some more.
And then you'd wonder when there was going to be a good calendering solution released as open source. And be sorely reminded that the solution was called Exchange. Then you'd hope you could get by without calendaring.
Now:
Tumblr media
We like open source: the Buddycloud stack is all released as open source. But we're also keen to spend our time on adding value to Buddycloud. Not tweaking spam-rules. Or looking at Exchange CAL costs. So we switched over to Google Apps: Gmail for email. Calendar for planning our meetings and organizing our schedules. Drive for storing and sharing files amongst the team. Hangouts to communicate with far away team members or developers of our community.
We'd rather be using open source. But we'd rather-more be spending our time on shipping Buddycloud code.
(BTW: We started having a Hangout Buddycloud’s Developer Call every Tuesday at 2:30pm GMT+1. This is aimed at bringing other Buddycloud developers and integrators together to share and get help from the dev-team and each other.)
Mailing Lists
There are two uses for mailing lists:
discussions: we do a lot of consensus building on buddycloud-dev. A good mailing list helps us work through an issue knowing that the solution is well crafted.
announcements: [strangely] a bunch of people seem to still want to get news updates through email. And we are not going to judge them for that.
Then: Mailman + Postfix
Over the years, mailman was the way to power mailing lists. It's good software. But installing Mailman involved debugging messages like "Premature end of script headers" or "Mailman CGI error!!!" And things always felt fragile. I'd tip-toe around our email stack with the through "perhaps I'll hold off upgrading Postfix incase Mailman stops working".
I'd have paid for a branded-hosted solution. It would have been nice to have someone else looking after this for us.
Now:
Tumblr media
To solve the discussion list problem - we used Google Groups. Our asynchronous communication means we can work without interruption. Developers can also sign-up on a modern web page. And others can just chip in their 2c through the website without needing to join a mailing list. Yes, I feel like a sell-out to the pure open source solution. Yes, I enjoy my free time. As I age I value the latter more.
Tumblr media
And for announcements-only lists, MailChimp helps us manage lists of users, Buddycloud-integrators and fans. And shoots off emails to them with updates. List is here if you are interested in a more read-only relationship.
Social Media
Then: We'd go down to the pub or beer garden and tell our friends what we were building. They'd tell their friends and the physical "social graph" would relay the message. Or we'd make a post on Slashdot.
Now:
Tumblr media
Everyone has their own flavour of social network. Buffer spools up announcements and pushes them out to each network. Right now, one Buffer post = a post on Twitter, Facebook, LinkedIn and Google+. And it gives us metrics on reach that keep Mizar in Marketing happy.
A lot has changed in just 5 years: complexity has increased and we're pushed towards solutions that wrap up the complexity in hosted offerings. Us developers and open source advocates like our principles. And tinkering with new software is a great procrastination technique.
But we also like hosted solutions that let get on with tasks further up the stack.
BTW, Buddycloud builds a hosted messaging stack. Build on open source. Released as open source. And you can install it yourself and tinker with settings. Or just use our hosted option and do something else with your free time.
What are you using for your "office stack"?
1 note · View note
buddycloud · 10 years ago
Text
The Buddycloud plan for 2015
Some thinking on how we are approaching 2015.
More Incremental Advances
In 2012 we set our sights on designing the best way to build messaging
Today Buddycloud is being added to more and more apps customers apps. This is good. But not good enough: in 2015 we're doubling down on making incremental changes to the Buddycloud-stack that help with reliability and scalability.
We'll also be spending more time on the open specification process that powers Buddycloud so that others can build their own messaging products.
Stay Lean and Flexible
We're fortunate to have a revenue stream from existing Buddycloud customers. And we're humbled by their trust in our open communication mission.
Each Buddycloud customer has slightly different needs. And this is helping us make sure we keep the Buddycloud stack flexible enough to cover general use cases. 
Improve on Our Competition
Yes, there are other messaging systems out there.
But we notice developers want something that does what it says it will do. Reliably. And with the added benefit of being able to run on-premises and federate with other sites. No other commercial messaging stacks do this. 
Focus on Product Not Sales
We're a tech team that sees our engineering selling itself - weekend hacking projects becoming enterprise messaging systems.
Boring unsexy, no big launch parties, self funded. And no sales team, just good product selling itself with word-of-mouth. 
And that's our plan for 2015.
1 note · View note
buddycloud · 11 years ago
Text
Using Docker with Github and Jenkins for repeatable deployments
Docker helps us deploy to Buddycloud’s testing and production environments. We use Docker to run Buddycloud’s hosted environment. And deploy after every commit to our testing and production Git branches.
Again and again.
Automatically.
Background: we’re holded up in the Austrian mountains working on the new Buddycloud hosting platform. We need to be able to reliably test and deploy code. What generally happens is that, unless servers are completely rebuilt between test or production, they slowly degrade over time. A new library here, a config change there. And soon your tests are no longer against a vanilla environment.
Tumblr media
Also, we want to be testing on exactly the same environment that we are running in production.
Core services and Docker deployments
What services should be run under docker and what are “core” services that other apps use?
We separate core services like databases, DNS and LDAP (for server authentication) from services that are updated and managed by Docker. These is is our plumbing - it’s just got to be there.
This has the knock on effect that when we do deployments to services that use a database: the deployed service or the application MUST take care of ensuring that the database is at the correct schema version.
This is a good thing: it keeps us honest about upgrades working smoothly. And catching failures before they hit production.
Tumblr media
By default docker exposes no ports. We need to expose some ports to the outside world, and some ports to localhost so that processes can intercommunication. For example our Apache instances run a reverse proxy back to the buddycloud-http-api. The ports are exposed using the docker startup commands.
For example Apache uses
docker run -d --name=apache -h=si.buddycloud.com -P -p 80:80 -p 443:443 -t apache
Tumblr media
So we have designed the following code flow that takes code from a developers laptop to SI and if that’s passing, we manually make a call to push to production.
Tumblr media
We ended up with the following code > deployment flow:
Developer checks out https://github.com/buddycloud/hosting.git works on their change or feature branch.
when they are ready to test in a system integration environment they commit back to the dev-candy branch
Github triggers a Jenkins hook that fires off the scripts from https://github.com/buddycloud/buddycloud-package/tree/master/projects/hosting/docker
Jenkins tries to build the project
If successful Jenkins calls the docker scripts that deploy to either production or system integration environments
the service is started and visible on https://hosting.buddycloud.com
Buddycloud helps you quickly add communication to your app. If you would like to try it out see Buddycloud Getting Started page.
4 notes · View notes
buddycloud · 11 years ago
Text
Buddycloud Crawler in XEP-0060 and the Buddycloud XEP
A couple of years ago I wrote the buddycloud channel directory as my GSoC'12 project and as my first buddycloud project to go live in production.
The component is running fine in search.buddycloud.org, however the crawler wasn't crawling as we required. The crawler was designed on top of XEP-0060, and uses smack with its pub-sub extensions to discover Buddycloud channels and items on the Buddycloud channel server.
But then comes a day when you get the guts to look at old code. Reason: the crawler was dumb dumb. It crawled every single item of every single node every time it ran. Stupid, eh? But there's more: by using smack's XEP-0060 implementation, the crawler missed an important feature that the Buddycloud XEP specifies - XEP-0059, a.k.a. RSM.
The Buddycloud XEP uses RSM in several occasions, eg.: disco#items and pubsub <items>.
<iq type=’result’ from=’channelserver.example.com’ to=’[email protected]/KillerApp’ id=’items1’> <pubsub xmlns=’http://jabber.org/protocol/pubsub’> <items node=’/user/[email protected]/posts’> <item id=”1291048810046”> <entry xmlns=”http://www.w3.org/2005/Atom” xmlns:thr=”http://purl.org/syndication/thread/1.0”> <author> <name>Dirk</name> <jid>[email protected]</jid> </author> <content type=”text”>A comment, wondering what all this testing does</content> <published>2010-11-29T16:40:10Z</published> <updated>2010-11-29T16:40:10Z</updated> <id>/user/[email protected]/posts:1291048810046</id> </entry> </item> <!— [more items…] —> </items> <set xmlns=’http://jabber.org/protocol/rsm’> <first>1291048810046</first> <last>1131048810046</last> <count>19827</count> </set> </pubsub> </iq>
Thus, we needed to somehow integrate RSM on smack to get the crawler properly working, so that it could page through all results that the channel server provides and avoid looking into the past when not needed.
Finally, we achieved that by creating a class that works as a packet extension called RSMSet and by overriding some of the PubSub classes offered by smack, such as the PubSub class itself. Now, when we need to do RSM, we ask the PubSubManager for a new PubSub packet and then inject the RSMSet extension into it. As in:
DiscoverItems discoRequest = new DiscoverItems(); discoRequest.setTo(discoverInfo.getFrom()); RSMSet rsmSet = new RSMSet(); rsmSet.setAfter(discoverInfo.getRsmSet().getLast()); discoRequest.setRsmSet(rsmSet);
And then, we store the last item crawled in every node inside the directory's database, so the crawler can be smarter about what to crawl.
Job done.
Next step on performance improvement list: crawl the /firehose when possible.
0 notes
buddycloud · 11 years ago
Text
Buddycloud in the Mountains Update
Tumblr media
We have enough food, drink, wood for the fire, good wifi and it looks like we might be snowed in. We're in the Austrian mountains working on a really simple and quick way to host a new Buddycloud site.
Some background: We have worked hard to organise our install docs and make buddycloud easy to install with .deb packages. Guilherme has also worked on a protocol tester to check buddycloud instances really are working and installed correctly.
Buddycloud's design is to be as modular as possible. This gives you choice:
Don't like the media server, slide it out and use a replacement.
Don't like how we do the webclient, slide it out and use your own frontend. 
The problem with this approach is that there are more moving pieces to setup and more places to make a mistake at install time. And this is before you have even decided that Buddycloud is right for your needs.
So we're building a way for you to get your own Buddycloud and XMPP account. When you grow, you can spin up your own Buddycloud site on your own hardware and migrate your data over.
The hosting platform (at least v0.0.1) will:
host your buddycloud on a sub-domain (eg: megacorp.buddycloud.net)
your own buddycloud website, API, buddycloud service, media service
user management: invite, add, delete, disable users
and a nice UI and API to manage everything.
tested updates using Docker (helps us ship working code).
Expect more news and code soon.
Tumblr media
Rene starting the fire
Tumblr media
Doors are not very big
Tumblr media
1 note · View note
buddycloud · 11 years ago
Text
Buddycloud in the Mountains
Imagine 5 days of being in a snowbound cabin deep in the mountains. Eating good food and hacking on great code.
We're doing something a little special: going to the mountains for a few days of distraction free hacking. 
The plan, use the time build a Buddycloud hosting platform that helps you spin up and run your own buddycloud site (we'll be prepping everything before so that we can hit the ground with a good spec and idea of how this will work)
ui / ux
backend code
DNS updating
adaptions to bc server
documentation
deployment
Details:
we will be staying at the Mesnerhof house (15 mins to nearest town). More photos on the Facebook Album
from Saturday 25th January - Thursday 30th January (before the XMPP summit and FOSDEM)
food: I'll be bringing in a lot of food and wine. Then we're cooking and eating in the house
getting there: There is a pickup from Munich on Saturday.
We depart on on Thursday morning and fly to the XMPP summit in Brussels followed by FOSDEM where we are looking forward to presenting the results of our mountain hacking.
Tumblr media
0 notes
buddycloud · 12 years ago
Text
Scaling buddycloud with Fanout.io
We want the buddycloud social network stack to be useful for everyone. From hobbyists to large service providers. In order to help address the scaling needs at the higher end of the spectrum, we’ve added support for Fanout.io in buddycloud’s HTTP API component.
Fanout.io is a cloud service that handles realtime data delivery. It’s kind of like Pusher and PubNub, but with an emphasis on APIs. Normally, the buddycloud HTTP API component sends realtime updates to clients directly. To scale up to really large numbers of connections it becomes necessary to distribute the connection pooling across multiple servers. This is where Fanout can help. Rather than having to add extra servers on your own to handle high load, you can route the pushes through the Fanout CDN instead. This way, you get limitless scaling of realtime pushes without having to manage any additional servers.
To use it, just put your Fanout realm & key in the gripProxies section of buddycloud HTTP API config.js:
exports.production = { ... gripProxies: [ ... // fanout.io { key: new Buffer('{key}', 'base64'), controlUri: 'http://api.fanout.io/realm/{realm}', controlIss: '{realm}' } ] }
Then, make sure your API domain is registered within Fanout and set as a CNAME:
api.yourdomain.com IN CNAME httpfront-{id}.fanout.io
That's all it takes. If you're using buddycloud as part of a large service then you can rest easy knowing that realtime updates will never be a bottleneck. Thousands of people could have a channel page open and see updates instantly. We've got this enabled on our demo site as well.
How we did it
Some months back, Fanout's founder, Justin Karneges, approached us about a possible integration. At first we were skeptical. We understood the value of a CDN, but it was important to us that buddycloud always have the ability to run standalone and not depend on a third-party service. Therefore, the feature would have to be optional. Additionally, we didn't want this to break our API. We already had a long-polling API defined, and we didn't want the API to be different depending on if Fanout routing was enabled or not.
Fanout uses a concept called "GRIP" proxying that addresses all of these concerns. The approach dictates that a special proxy server sit in front of our webserver, handling the work of pushing out lots of data to clients. Because it acts as an HTTP proxy, we’re able to retain our API. Our webserver then speaks the open GRIP protocol to the proxy. This is the same protocol that the open source Pushpin proxy uses as well. What's neat is that buddycloud only needs to support the GRIP protocol, and it can be fronted by either a local Pushpin instance or the Fanout cloud. Or any future GRIP-supporting proxy. This means we have a singular code path, and the code isn't even Fanout-specific. We like standards.
Below is a diagram of how a standalone (non-Fanout) server setup looks:
Tumblr media
In this case, a local Pushpin instance sits on the same physical server as the buddycloud HTTP API component, so that the server itself is capable of performing its own realtime deliveries. This means the server maintains all the open connections with any clients. The end result is more or less the same as before we converted the HTTP API code to use GRIP, although we hope the code will be more maintainable this way, too.
Now for the fun part. If you configure buddycloud to use the Fanout cloud service, then you essentially replace Pushpin in the scheme:
Tumblr media
Here the Fanout CDN represents Fanout’s global cluster of servers. With this setup, the buddycloud server doesn’t need to maintain any of the open connections, and scaling concerns are handled by Fanout.
Code
There were two main changes we had to make to get this to work. First, at any place where we were holding an HTTP request open as a long-poll, we changed the code to reply immediately with a special GRIP response instead. This special response tells the proxy service to hold the connection open on our behalf. The held connection is bound to a channel identifier so that we can later push to it using that channel. Second, whenever new data is available we now publish it to the GRIP service. What's nice is we publish the data regardless of whether or not there are any held connections. This means we no longer need to deal with connection management.
The buddycloud HTTP API component is written in Node with Express, so we used the Nodegrip library for our GRIP support. Below we define some utility methods.
First, the sendHoldResponse() method sends an HTTP response with GRIP instructions. It specifies the channel to bind to and defines the HTTP response to use in case of a timeout. We use this method wherever we need to cause a request to long-poll.
var griplib = require('grip'); exports.sendHoldResponse = function(req, res, channelBase, prevId) { var origin = req.header('Origin', '*'); if (origin == 'null') { origin = '*'; } var headers = {}; headers['Access-Control-Allow-Origin'] = origin; headers['Access-Control-Allow-Credentials'] = 'true'; headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'; headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, X-Requested-With, X-Session-Id'; headers['Access-Control-Expose-Headers'] = 'Location, X-Session-Id'; var channel; var contentType; var body; if (req.accepts('application/atom+xml')) { channel = channelBase + '-atom'; contentType = 'application/atom+xml'; body = '<?xml version="1.0" encoding="utf-8"?>\n' + '<feed xmlns="http://www.w3.org/2005/Atom"/>\n'; } else if (req.accepts('application/json')) { channel = channelBase + '-json'; contentType = 'application/json'; body = {}; body['last_cursor'] = prevId; body['items'] = []; body = JSON.stringify(body); } else { res.send(406); return; } var channelObj = new griplib.Channel(channel, prevId); headers['Content-Type'] = contentType; var response = new griplib.Response({'headers': headers, 'body': body}); var instruct = griplib.createHoldResponse(channelObj, response); console.log('grip: sending hold for channel ' + channel); res.send(instruct, {'Content-Type': 'application/grip-instruct'}); };
The code's a bit large since we want our timeout response to support CORS along with both Atom and JSON encodings. The actual GRIP stuff is in the last few lines.
Next, the publishAtomResponse() method pushes the HTTP response that we want to send to any connected clients. As we want to support both Atom and JSON formats, this is done by having a channel for each format (suffixed with "-atom" or "-json"). We bind to one or the other channel based on the Accept header in a request, and whenever we publish we send to both channels.
exports.publishAtomResponse = function(origin, channelBase, doc, id, prevId) { if (origin == 'null') { origin = '*'; } var headers = {}; headers['Access-Control-Allow-Origin'] = origin; headers['Access-Control-Allow-Credentials'] = 'true'; headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'; headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type, X-Requested-With, X-Session-Id'; headers['Access-Control-Expose-Headers'] = 'Location, X-Session-Id'; headers['Content-Type'] = 'application/atom+xml'; var response = doc.toString(); var channel = channelBase + '-atom'; console.log('grip: publishing on channel ' + channel); grip.publish(channel, id, prevId, headers, response); headers['Content-Type'] = 'application/json'; if (id != null) { response = {}; response['last_cursor'] = id; response['items'] = atom.toJSON(doc); response = JSON.stringify(response); } else { response = JSON.stringify(atom.toJSON(doc)); } channel = channelBase + '-json'; console.log('grip: publishing on channel ' + channel); grip.publish(channel, id, prevId, headers, response); };
The grip.publish() method seen above is another convenience method. It handles the GRIP payload formatting, and also supports publishing to multiple GRIP proxies at once:
exports.publish = function(channel, id, prevId, rheaders, rbody, sbody) { if (!config.gripProxies || config.gripProxies.length < 1) { return; } if (!pubs) { pubs = []; for(var i = 0; i < config.gripProxies.length; ++i) { var gripProxy = config.gripProxies[i]; var auth = null; if(gripProxy.controlIss) { auth = new pubcontrol.Auth.AuthJwt({'iss': gripProxy.controlIss}, gripProxy.key); } pubs.push(new pubcontrol.PubControl(gripProxy.controlUri, auth)); } } var formats = []; if (rbody != null) { formats.push(new griplib.HttpResponseFormat(200, 'OK', rheaders, rbody)); } if (sbody != null) { formats.push(new griplib.HttpStreamFormat(sbody)); } var item = new pubcontrol.Item(formats, id, prevId); for(var i = 0; i < config.gripProxies.length; ++i) { (function() { var gripProxy = config.gripProxies[i]; pubs[i].publish(channel, item, function(success, message) { if (!success) { console.log("grip: failed to publish to " + gripProxy.controlUri + ", reason: " + message); } }); }()); } }
With these convenience methods in place, implementing our /notifications/posts endpoint was easy. When a request is received but we have no items to deliver, we call sendHoldResponse() to cause the request to stay open. Whenever a new item becomes available, we call publishAtomResponse() to have it delivered down any open connections.
The buddycloud HTTP API maintains an item queue per logged-in user, with each one backed by a persistent XMPP session. The GRIP channels are unique per-user then, using the form “np-{jid}” (“np” standing for “notifications/posts”). Requests by unauthenticated users share a single anonymous JID, and that's where the big scaling win is. If there are 1000 anonymous browsers viewing a channel, the GRIP service will deliver updates to all of them with a single push from the buddycloud HTTP API. In a future revision we will look into how to better scale updates for logged-in users.
API
With our changes in place, what does an API call look like? (long lines wrapped)
GET /api/notifications/posts?since=cursor:1 Host: demo.buddycloud.org Accept: application/json HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With, X -Session-Id Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Expose-Headers: Location, X-Session-Id Access-Control-Allow-Origin: * Content-Length: 250 Content-Type: application/json {"last_cursor":"2","items":[{"id":"02befca2-5b5f-4ae1-801f-5d2113bf8ba5","sour ce":"[email protected]/posts","author":"[email protected]","publi shed":"2013-05-13T20:17:56.537Z","updated":"2013-05-13T20:17:56.537Z","content ":"test post"}]}
Answer: it looks exactly the same as it did before this change. That’s the whole point. There may be a proxy service in the middle, but to the outside world it looks like buddycloud’s API.
Multiple GRIP configurations
The buddycloud HTTP API can be configured to use multiple GRIP proxies at once. This makes it possible for the component to work with both a local Pushpin instance and the Fanout.io service simultaneously. To do this, keep Pushpin in the network path, and set upstream_key in pushpin.conf with your Fanout key:
upstream_key=base64:{key}
The resulting topology looks like this:
Tumblr media
Why would you want to do this? The main reason is that it helps with transitioning from a non-Fanout setup to a Fanout setup. With this configuration, the buddycloud HTTP API publishes messages to both services, such that either one is capable of handling realtime connections at any moment. This can be very useful right when you set your CNAME domain to point at Fanout. While you’re waiting for the DNS change to propagate, realtime pushes will still work via the local Pushpin instance. In fact, turning Fanout on and off at this point is just a matter of a DNS change. No additional configuration or restarts of buddycloud is required. You can even point your /etc/hosts file at Fanout within your test environment to confirm everything is fine before making the official DNS change. This greatly reduces the risk involved in configuring and activating Fanout.
Conclusion
We are really impressed with Fanout's approach to scaling realtime. Of all the similar such services available, it's the only one we could ever think of using, and we love the very open way it goes about things. buddycloud will soon be offering hosted service for large businesses, and it's nice to know that the scalability of realtime deliveries is one less thing we’ll have to worry about.
0 notes
buddycloud · 12 years ago
Video
youtube
Presenting at realtimeconf.eu
0 notes
buddycloud · 12 years ago
Text
buddycloud presenting at the Realtime Conference: April 22, 23 2013 Lyon, France
The Realtime conference goes from strength to strength and we’re excited to be invited to present there.
If you build amazing services on the internet you really want to get there.
The conference is a smaller, more intimate gathering of experts and that means that there are limited tickets. To join us, get your's at http://realtimeconf.eu/
Date check: APRIL 22, 23 2013 LYON, FRANCE
Tumblr media
0 notes
buddycloud · 12 years ago
Video
youtube
Last week we presented at FOSDEM, under the theme of: Secure, Federated Communication. Here's the video.
0 notes
buddycloud · 12 years ago
Text
The buddycloud FOSDEM release
Today, just in time for FOSDEM, we're announcing version 0.9 of the buddycloud webclient and updates to all the buddycloud components.
And everything is nicely packaged at downloads.buddycloud.com
This release also includes new releases of the 
buddycloud http API
buddycloud server
buddycloud media server
buddycloud pusher
We're be demoing the new software at FOSDEM and ready to help you setup your own buddycloud instance.
Find us at the Realtime Lounge in FOSDEM (K Building, level 2).
And see you in FOSDEM. Until then this is what we're doing:
0 notes
buddycloud · 12 years ago
Text
Easily Upload Pictures and Video Into Your buddycloud Channel
From the buddycloud department of extreme-alphaware:
Abmar threw together a quick Android upload intent that will post to your channel. Nothing more, nothing less.
To try it out, check out: http://dl.dropbox.com/u/65800395/buddycloud.apk 
I'll be using it at FOSDEM to keep the pictures flowing.
Tumblr media
0 notes