Building a XMPP (Jabber) server.
Setting up an XMPP server
“XMPP by any other name would…”
We recently had a chat (pun not intended) amongst the team to discuss some of the ways we could cut costs during these financially challenged times. One area identified was around inter-office calling charges. We have three stores: one in Onehunga (local), one in Tawa (national) and one in Hamilton (national). All of which are subject to charges when they call us here at head office (and vice versa).
We use Fonality’s HUD client here at head office (actually HUDlite to be exact because it’s free) for call management, presence management and IM.
So a thought was born that maybe we could link the remote sites to the HUDLite server on our VoIP system, and they could IM rather than calling. But alas, it all seemed a little too hard and we could foresee a few problems, so we opted instead to make our own Jabber server (using the XMPP protocol) and give the sites access to that.
This turned out to be a great compromise. Now staff at the remote sites IM rather than calling – they can see if the person they want to talk to is available and can get answers immediately. Even better, what would have been a calling cost is absorbed as part of our data charges.
So how did I do it?
I already knew I was going to use Ubuntu server for this project, but I had to decide between Jabber or IRC (why? because those were the two mentioned in the Ubuntu server guide…*snigger*). For reasons like clients, setup, the name (I do like Jabber over IRC) I went with Jabber, or to be more precise an XMPP server.
The start was a basic build using Ubuntu 10.04 LTS (there are newer versions at the time of writing this but I prefer their Long Term Support version – until the next one does…). Near the end of the install (when prompted if you want additional software installed) I selected OpenSSH server so I can log in remotely to administer the system and install the components – it’s handy if you need to copy-and-paste.
After the first reboot make sure that universe and multiverse are present in the sources.list file (add them if they are not…)
sudo vi /etc/apt/sources.list
Once that’s done, I make sure everything is up-to-date
sudo aptitude update sudo aptitude safe-upgrade
Then one more reboot for good luck and we’re on our way.
sudo shutdown -r now
Basic install
The XMPP server can support a number of db backends. By default it uses MySQL so that was how I left it for our server. Preliminary testing was unsuccessfully using the “Berkeley DB” as the user authentication database, however jabberd2 can be configured to use LDAP, MySQL, Postgresql, etc.
For this HOW-TO we’ll be using MySQL, so…
sudo aptitude install mysql-server
When prompted, type in a password for the MySQL ‘root‘ user and note it down for use later.
Now we install the engine of our communication server: jabberd2…
sudo aptitude install jabberd2
Once installed we may as well stop the services since they’re not configured properly yet.
sudo /etc/init.d/jabberd2 stop
Configuring MySQL
The jabberd2 package has a script to do all the setup work for you.
sudo gzip -d /usr/share/doc/jabberd2/db-setup.mysql.gz
Log into MySQL as the “root” user and execute the script.
mysql -u root -p mysql>SOURCE /usr/share/doc/jabberd2/db-setup.mysql mysql>GRANT select,insert,delete,update ON jabberd2.* to jabberd2@localhost IDENTIFIED by 'password'; mysql>quit
Replace the password above with one of your own choice.
Configuring jabberd2
The sm.xml file configures the session manager component of jabberd2. The session manager acts as a layer between the router and the externally available components. We need to configure a few settings like id, and database connection details.
sudo vi /etc/jabberd2/sm.xml
Change/update the following tags:
<id>your.domain.com</id> <driver>mysql</driver> <user>jabberd2</user> <pass>password</pass>
Now we edit the c2s.xml file. This configures the client-to-server component of the jabberd2 server. The c2s component handles communications with Jabber clients, and the settings in c2s.xml are primarily concerned with client communication.
IT’S DESCISION TIME: Do you want to have encrypted connections? Your choice effects the settings in the first part of the c2s.xml file.
YES, I would like encrypted connections…
The first step of this process is to create either a self-signed certificate or obtain one from a certificate authority.
Once you’ve created your certificate, you can copy it into /etc/jabberd2/your.domain.com.pem
Now we edit the c2s.xml file.
sudo vi /etc/jabberd2/c2s.xml
part way down add/update the following lines
<id register-enable='true' pemfile='/etc/jabberd2/your.domain.com.pem'> your.domain.com </id>
This setting will allow users to be automatically created, and will use the defined certificate for encryption.
NO, I don’t want encrypted connections…
sudo vi /etc/jabberd2/c2s.xml
part way down add/update the following lines
<id register-enable='true'>your.domain.com</id>
Other changes regardless of connection type
Continue editing the c2s.xml file
<module>mysql</module> <user>jabberd2</user> <pass>password</pass>
By default, jabberd2 looks for the MySQL sock in the /tmp directory. We can create a link to the actual MySQL sock file in /var/run/mysqld, but the “tmp” directory is emptied during each reboot. The easy fix for me was to alter the jabberd2 boot script so the symbolic link was created as jabberd2 was started.
sudo vi /etc/init.d/jabberd2
add this line near the top with the other variable declarations
LINK2MYSQLSOCK="/tmp/mysql.sock"
then just before the section that executes the ‘start‘ options add…
if [ ! -e "${LINK2MYSQLSOCK}" ]; then
echo -n "Recreating Jabber's lost MySQL socket link...\n"
ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock
fi
This first checks to see if the sock file is there, and if it’s not creates the link to the right place for you!
Now start the Jabber server…
sudo /etc/init.d/jabberd2 start
and if we’ve done everything right, the server should be running ready for clients to connect to.
The client
There are a number of clients to choose from regardless of what platform your using. For a list of clients vs. platform you can visit http://xmpp.org/xmpp-software/clients/ and work your way through the list to select one based on your own criteria.
I had the best results with Miranda, Pidgin, OneTeam, Empathy (on Linux), iChat (on Mac OSX), and Citron, finally settling for Pidgin to rollout with our organisation on Windows PCs. It was as much about the look and feel as it was about it actually working – in an ideal world I would have liked a Windows version of “iChat” because i love the look and feel as well as the chat bubbles.
A note on “Resource names”
In Jabber you are able to log in several client programs simultaneously. You don’t need to have different Jabber accounts for different locations (e.g. work and home). You can chat in one location, then go to another, log in again with the same JID and the previous Jabber client will not go offline.
This is because Jabber has a thing called “resources”. When you log in, you are usually asked for for the “Resource Name”. Some programs like to use their program names as the resource name (e.g. “iChat” or “Miranda”).
For more information you can visit here.
Backing up data
It’s probably a wise decision to back up the data stored in the MySQL database so that it can be restored if you have to rebuild the server.
For my particular setup, I have a cron script which dumps the schema and data and Bacula archives it as part of daily site-wide unattended backup procedure.
Fundamentally the steps can be performed manually or via a script. Here’s what I did.
sudo mkdir /var/spool/mysql sudo vi /var/lib/mysql/jabberd2-backup-db mysqldump -u root -ppassword -d jabberd2 > /var/spool/mysql/schema.sql mysqldump -u root -ppassword -t jabberd2 > /var/spool/mysql/data.sql sudo chmod +x /var/lib/mysql/jabberd2-backup-db
Now add it to cron, so it can be automated daily (in this case at 01:30 each day)…
sudo vi /etc/crontab
30 1 * * * root /var/lib/mysql/jabberd2-backup-db
and restart cron
sudo service cron restart
These could also just be entered as manual commands individually…
sudo mysqldump -u root -ppassword -d jabberd2 > /var/spool/mysql/schema.sql sudo mysqldump -u root -ppassword -t jabberd2 > /var/spool/mysql/data.sql