Monday, July 25, 2011

Ejabberd cluster on Ubuntu Server

Two years ago, I created a blog about the clustering of ejabberd nodes, running on OpenSolaris.

This message here has the same purpose but now running on Ubuntu Servers and linked to an openldap server. I used 9.04 (Jaunty Jackalope), but I think there shouldn't be too much changes in earlier or later versions.

I used the following setup:
3 ejabberd nodes (ejabberd1, ejabberd2, and ejabberd3)
1 OpenLDAP Server

Installation and Configuration First ejabberd

Make sure that your are logged in as root user.

1. Install ejabberd:
$ apt-get install ejabberd
2. Configure ejabberd to get users from the openldap server
* adapt /etc/ejabberd/ejabberd.cfg:

** %% Admin user: in this example the user must be listed in the LDAP
** %% Hostname
** %% List of LDAP servers: {ldap_servers, [""]}.
--> make sure that ejabberd node can reach ldap server using its
hostname (possibly adapt /etc/hosts)
** %% Encryption .. LDAP Servers (LDAPS): {ldap_encrypt, }.
--> tls, ssl, none, ...
** %% Port connect to LDAP server: {ldap_port, }.
** %% LDAP Manager: {ldap_rootdn, ""}.
--> e.g. {ldap_rootdn, "cn=admin,dc=example,dc=com"}.
** %% Password of LDAP manager: {ldap_password, ""}.
** %% LDAP attribute that holds user ID: {ldap_uids, [{"uid", "%u"}]}.

3. Modify /usr/sbin/ejabberdctl: ERLANG_NODE=ejabberd@`hostname`
--> not single quotes but back single quotes around hostname
4. Start ejabberd: /etc/init.d/ejabberd start

Check if ejabberd is running:

$ ejabberdctl status
Node ejabberd@ejabberd1 is started. Status: started
ejabberd is running

Installation and Configuration Other ejabberd Nodes

1. Install ejabberd:
$ apt-get install ejabberd
2. Copy ejabberd.cfg from first node
3. Copy ejabberdctl from first node
4. Copy /var/lib/ejabberd/.erlang.cookie from node 1 to new node.
5. Start ejabberd: /etc/init.d/ejabberd start

Check if ejabberd is running:

$ ejabberdctl status
Node ejabberd@ejabberd2 is started. Status: started
ejabberd is running

Now synchronize the databases is the tricky part. Thanks to this blog it is a piece of cake.
Just perform the steps below to synchronize the database of node 2 with the first node:

1. Start ejabberd in debug mode:
$ ejabberdctl debug
You arrive in an Erlang shell.
2. Enter the following commands:

* FirstNode = 'ejabberd@first', %%where first is the hostname of the first node (!) Make sure that the line ends with a comma, indicating that there are other commands to follow
* mnesia:stop(),
* mnesia:delete_schema([node()]),
* mnesia:start(),
* mnesia:change_config(extra_db_nodes, [FirstNode]),
* mnesia:change_table_copy_type(schema, node(), disc_copies).

3. End the debug session by pressing Ctrl-c, Ctrl-c

Your second node now runs ejabberd with the same database as on the first node.
Repeat this procedure for other ejabberd nodes which must serve the same database.

Web Interface ejabberd
By default there is a webinterface available for ejabberd on http://:5280/admin

Log on with an LDAP user who has been added to the list of Admin users in ejabberd.cfg, login name is in the format user@domain, e.g.


  1. Hello, I followed your tutorial, but I've got an error as the following:
    =ERROR REPORT==== 2011-03-06 22:10:13 ===
    E(<0.37.0>:ejabberd_rdbms:67) : Start of supervisor 'ejabberd_odbc_sup_mydomain.tld'

    And keeped filling my logs like 50 times a second!

    I've fixed by issuing the following command after your second step on the node (as mentioned in,-problems-after-update-(ejabberd-2.0.5-%3E-2.1.5)-td31083113.html):
    mnesia:add_table_copy(sql_pool, node(), disc_copies).

    And then everything went ok.

    Thanks for your tutorial!

  2. I wonder if this works with 2.1.2? These instructions are a couple of years old as I read them. I tried this. I get {atomic, ok} upon completion, but then if I start another debug session and call mnesia:info(). , the line that lists "running db nodes" just has the node that I am on.

    I find this peculiar, the official documentation for clustering seems so simple
    But neither of these sets of instructions work for me. The output is baffling opaque. From my limited experience so fra it appears to be one of those tings that either "just works", or are you ever in for a long road to figure out what is going on.

    Where is the best place to go to get help?
    Thanks for your time.

    1. Not sure if it works for version 2.1.2. I've done this post to not forget it, and tested it on 3 virtual machines.
      But you are right that either it "just works" or "what's going on, get alive, and some more frustration".
      This post worked fine for me, but should try it for later versions. Maybe when I have some more time, I'll post a new version.
      Btw, did you try the above comment?