Wednesday, March 31, 2010

Integrating RabbitMQ with ejabberd

Last few days I've been trying to make RabbitMQ and ejabberd work smoothly together by means of mod_rabbitmq gateway. The official mod_rabbitmq document is pretty clear but the installation chapter is rather short. Plus, it presumes that ejabberd is installed from the source tree, which might not be the case. Here I want to give you more detailed instructions on the installation/configuration process in case mod_rabbitmq doesn't work for you out of the box.

My environment is Ubuntu 9.10 with rabbitmq-server and ejabberd packages installed via apt-get. Both RabbitMQ and ejabberd are up and running. Now I want them to talk to each other and route messages properly.

Compiling mod_rabbitmq


If you have the same environment as mine you can just download the binary and the header files, and copy them to the corresponging ejabberd folders (see last two lines in the bash snippet below). Alternatively you can compile mod_rabbitmq.beam file yourself:

$ git clone git://git.process-one.net/ejabberd/mainline.git ejabberd
$ cd ejabberd
$ git checkout -b 2.1.x origin/2.1.x
$ cd src
$ wget http://hg.rabbitmq.com/rabbitmq-xmpp/raw-file/73c129561101/src/mod_rabbitmq.erl
$ wget http://hg.rabbitmq.com/rabbitmq-xmpp/raw-file/73c129561101/src/rabbit.hrl
$ ./configure --disable-tls
$ make
$ sudo cp mod_rabbitmq.beam /usr/lib/ejabberd/ebin/
$ sudo cp rabbit.hrl /usr/lib/ejabberd/include/

Configuring mod_rabbitmq


You need to know the short name of the machine you are running RabbitMQ on. Use hostname -s command for this. Open /etc/ejabberd/ejabberd.cfg file for edit, find modules section, and add mod_rabbitmq stanza to the list

{modules,
[
{mod_adhoc, []},
...
{mod_rabbitmq, [{rabbitmq_node, rabbit@yourhostname}]},
...
{mod_version, []}
]}.

Replace yourhostname with your machine short name. In my case it was ubuntu.

Setting up cookie


To make RabbitMQ and ejabberd work together, they have to run in the same Erlang cluster. That means they have to use the same cookie file. By default RabbitMQ is installed under rabbitmq user with /var/lib/rabbitmq home directory, and ejabberd under ejabberd user with /var/lib/ejabberd home directory. If you compare their cookies

$ sudo cat /var/lib/rabbitmq/.erlang.cookie
$ sudo cat /var/lib/ejabberd/.erlang.cookie


they will most likely be different. That's why if you restarted ejabberd now you would see exception in RabbitMQ log: "Connection attempt from disallowed node ejabberd@ubuntu". To fix it just copy one cookie file to another

$ sudo /etc/init.d/ejabberd stop
$ sudo mv /var/lib/ejabberd/.erlang.cookie /var/lib/ejabberd/.erlang.cookie.orig
$ sudo cp /var/lib/rabbitmq/.erlang.cookie /var/lib/ejabberd/.erlang.cookie
$ sudo chown ejabberd:ejabberd /var/lib/ejabberd/.erlang.cookie
$ sudo /etc/init.d/ejabberd start

The installation part is now done, and you are good to go.

Adding rabbit buddy to your roster


The rabbit's JID comprises two parts: exchange name and routing domain. To find the latter one, look at the /var/log/ejabberd/ejabberd.log file. Searching for "Routing" you should get something like this

=INFO REPORT==== 2010-03-30 21:35:22 ===
{contacted_rabbitmq,rabbit@ubuntu}

=INFO REPORT==== 2010-03-30 21:35:22 ===
I(<0.314.0>:mod_rabbitmq:90) : Routing: "rabbitmq.jabber.ndpar.com"


This is the buddy's domain. For the name you can use any exchange name available in the RabbitMQ server. Run sudo rabbitmqctl list_exchanges command and pick up the name from the list. I use amq.fanout exchange which exists in every RabbitMQ server. So I go to my IM client (Adium) and add this user to the buddies list

amq.fanout@rabbitmq.jabber.ndpar.com

Rabbit's greetings


To publish a message to RabbitMQ I use the same Groovy script as in the previous post. I just amended the exchange name and routing key

channel.basicPublish 'amq.fanout', '', null, 'Hello, world!'.bytes

Run the script and voilà, you've got mail



Troubleshooting


Here are some hints for you if something goes wrong.

• While working with mod_rabbitmq keep an eye on the log files of both RabbitMQ and ejabberd:

$ tail -f /var/log/ejabberd/ejabberd.log
$ tail -f /var/log/rabbitmq/rabbit.log

• Check which exchanges, queues and bindings the RabbitMQ server has:

$ sudo rabbitmqctl list_exchanges
$ sudo rabbitmqctl list_queues
$ sudo rabbitmqctl list_bindings

• If you screw up something there, you can roll back to the default values:

$ sudo rabbitmqctl stop_app
$ sudo rabbitmqctl reset
$ sudo rabbitmqctl start_app

• Check ejabberd web admin, it has lots of information there

http://yourdomainname:5280/admin

• If your IM client is Adium, check its folder periodically — it tends to collect some garbage there:

~/Library/Application Support/Adium 2.0/Users/Default/libpurple

Resources

• Tony Garnock-Jones' presentation slides about RabbitMQ and its extensions

1 comment:

Mark Ellul said...

I just wanted to let any readers know the urls for the rabbitmq mods are...

https://raw.github.com/rabbitmq/rabbitmq-xmpp/master/src/mod_rabbitmq.erl

and

https://raw.github.com/rabbitmq/rabbitmq-xmpp/master/src/rabbit.hrl

Depending on your OS you may need to install

apt-get install erlang-dev erlang-parsetools

I will add more comments if I hit any more roadblocks