My RabbitMQ setup for notifications

July 23, 2013

I recently decided to try out RabbitMQ (the popular messaging queue) to fix the problem of notifications.

In the context of multi-devices in which we are today, notifications are becoming an issue.

We have a multitude of accounts (whether it be email, chat, web services, etc.) that are not tied to any of our devices in particular. However each of those devices have their own implementation of notifications, which can become redundant and cumbersome.

I’ve put myself on a mission to switch to a distributed notifications model.

A central messaging service such as RabbitMQ is a viable solution since there is a unified stream (or queue) of messages which can be sent and received from anywhere. You need a central server that will serve as the aggregator and as the distributor.

On my server, I just installed RabbitMQ and configured a file for the server to be up and running, which should be under /etc/rabbitmq/rabbitmq.config:

[
  {rabbit, [
     {ssl_listeners, [5673]},
     {ssl_options, [{cacertfile,"/etc/ssl/certs/StartCom_Certification_Authority.pem"},
                    {certfile,"/path/sslcerts/mydomain.tld/ssl.crt"},
                    {keyfile,"/path/sslcerts/mydomain.tld/ssl.key"},
                    {verify,        verify_none},
                    {fail_if_no_peer_cert,false}]}
   ]}
].

Note: I recommend using StartSSL for free, trusted SSL certificates. I’m using the certificate I have for a domain that I use with my web server.

Next, you’ll want to setup users and disable the guest user, since this will be a publicly facing service. The easy way to do this is to (temporarily) enable the web interface by issuing:

rabbitmq-plugins enable rabbitmq_management

And then going to http://server-name:15672/, the user will be guest, password guest (see why you need to do this?). After setting up a user and disabling the guest user, you’re good to go. You may disable the interface or not make it public-faced.

And that’s it for RabbitMQ.

I’m a fan of python, so I looked for a python library for interacting with RabbitMQ and found pika.

However, since I would be making a lot of scripts to send and receive notifications, writing the setup code for using pika every time was redundant, therefore I wrote aamnotifs, a quick wrapper around it.

You can check it out on github or install it using sudo pip install aamnotifs

RabbitMQ allows for a queue to have “routing keys”, I’ll call them “channels”, for clarity, of messages to flow through. The way I use it is I have a different channel per notification type I send, therefore I’ll have an “irc”, “mails”, “server”, etc. channel that I can then “subscribe” to any number of those channels with a receiver.

Sending a notification:

import aamnotifs
n = aamnotifs.Notifs("amqps://user:password@domain.tld:5673/%2F")

# The routing_name is the name of the "channel" you want to use
# it can be "mail", "chat", etc.
# This will make it easy to choose which channels your clients
# will receive. Notification title can be the application name.
n.send("example_channel", "Notification title here", "Notification content here")

Receiving notifications:

import aamnotifs

def print_all_notifications(title, message):
    print "Notification received: {0}: {1}".format(title, message)

def print_mail_and_irc_notifications(title, message):
    print "Mail and IRC notifications received: {0}: {1}".format(title, message)

try:
    n = aamnotifs.Notifs("amqps://user:password@domain.tld:5673/%2F")

    # The routing_name is the name of the "channel" you want to use
    # it can be "mail", "chat", etc.
    # This will make it easy to choose which channels your clients
    # will receive. Can be a list too, for listening on multiple streams.
    n.receive("#", print_all_notifications) # "#" matches all channels

    # OR n.receive(["mail", "irc"], print_mail_and_irc_notifications)
   
except KeyboardInterrupt:
    break

This should get you started with a nice base on top of which to create a lot of nice things.

Right now I’m using it to receive new email notifications, weechat IRC highlights/messages, some important rss feeds, and some server monitoring notifications too.

On my desktop I use it with notify-send and dunst as very nice OSD notification replacement.

On my laptop (MacBook Pro), I use a receiver that I integrated with pync, which gets my notifications and displays them using OS X’s notification center.

On my iPhone, I use pushover to receive the notifications I send using simple http requests on my server.


edit: Thanks to rickhanlonii for making me improve the clarity of usage.

Please don’t hesitate to leave comments, suggestions or ask any questions below.