ejabberd 19.09.1をインストールしてクラスタリングする

「いまさらXMPP」と言われそうですが、オープンであることはそれだけで価値があることだと思います。

今回、XMPPサーバーのErlang実装である ejabberd をインストールしてクラスタリングしようと思います。 ejabberdはXMPPの他にMQTTとSIPも喋れるので我が家の萬のことに使えそうです。

とりあえず皆さんお手持ちのサーバーがあると思いますが、私は2台のサーバーにUbuntu Server 18.04 LTSをインストールして最新の状態にアップデートしておきました。 CentOSでもArch Linuxでも何でも大丈夫だと思います。 dpkgとrpmはバイナリパッケージが有りましたが、私はSource packageでインストールしていきます。

DNSサーバーもあると便利なのですが、ここでは省きます(私は設定しますが)。

Erlang/OTP 22のインストール

導入方法は何でもいいと思います。私はソースから入れてみます。 必要なパッケージは README.md を確認してほしいのですが、私はこんな感じに入れています。書き漏らしているものがあったらスミマセン。

sudo apt install -y build-essential libssl-dev zlib1g-dev libncurses5-dev autoconf curl git
cd ~/
curl -L https://github.com/erlang/otp/archive/OTP-22.1.3.tar.gz | tar -zx
cd otp-OTP-22.1.3
./otp_build autoconf
./configure --prefix=/usr/local/erlang/22.1 \
            --enable-smp-support \
            --enable-m64-build \
            --disable-sctp \
            --enable-threads \
            --enable-kernel-poll \
            --enable-hipe \
            --without-javac \
            --without-wx \
            --without-docs \
            --without-odbc \
            --disable-debug
make -j2
sudo make install

インストール

cd ~/
curl -L https://github.com/processone/ejabberd/archive/19.09.1.tar.gz | tar -zx
cd ejabberd-19.09.1
sudo apt install -y libexpat1-dev 

さて ejabberd のビルドを始めます。

./autogen.sh
./configure --prefix=/usr/local/ejabberd \
            --with-erlang=/usr/local/erlang/22.1 \
            --enable-user=ejabberd \
            --enable-group=ejabberd \
            --enable-tools \
            --enable-elixir \
            --enable-zlib \
            --enable-hipe \
            --enable-sip \
            --enable-stun
make -j2
sudo make install
sudo useradd -M -d /usr/local/ejabberd/ -s /usr/sbin/nologin ejabberd
sudo chown ejabberd:ejabberd -R /usr/local/ejabberd
sudo cp ejabberd.service /etc/systemd/system/ejabberd.service

設定

/usr/local/ejabberd/etc/ejabberd/ejabberd.yml を適当に変更します。基本的に特殊な話はないですが、最初の hosts のところはejabberdクラスタ全体としての(XMPPサーバーの)ホスト名です。 ここでは example.com としていますので、jid@example.com というJIDを使うことになります。

--- /usr/local/ejabberd/etc/ejabberd/ejabberd.yml.orig  2019-10-19 07:01:43.351109724 +0900
+++ /usr/local/ejabberd/etc/ejabberd/ejabberd.yml       2019-10-19 07:01:47.711079485 +0900
@@ -15,7 +15,7 @@
 ###

 hosts:
-  - localhost
+  - "example.com"

 loglevel: 4
 log_rotate_size: 10485760
@@ -36,7 +36,7 @@
     max_stanza_size: 262144
     shaper: c2s_shaper
     access: c2s
-    starttls_required: true
+    starttls_required: false
   -
     port: 5269
     ip: "::"
@@ -46,7 +46,7 @@
     port: 5443
     ip: "::"
     module: ejabberd_http
-    tls: true
+    tls: false
     request_handlers:
       /admin: ejabberd_web_admin
       /api: mod_http_api
@@ -153,7 +153,7 @@
   mod_fail2ban: {}
   mod_http_api: {}
   mod_http_upload:
-    put_url: https://@HOST@:5443/upload
+    put_url: http://@HOST@:5443/upload
   mod_last: {}
   mod_mam:
     ## Mnesia is limited to 2GB, better to use an SQL backend

続いて /usr/local/ejabberd/etc/ejabberd/ejabberdctl.cfg を編集します。Erlangのノード名を指定します。 私は1号機のホスト名は xmpp1, 2号機は xmpp2 としています。

--- /usr/local/ejabberd/etc/ejabberd/ejabberdctl.cfg.orig       2019-10-19 07:07:51.002048355 +0900
+++ /usr/local/ejabberd/etc/ejabberd/ejabberdctl.cfg    2019-10-19 07:07:54.230022994 +0900
@@ -134,7 +134,7 @@
 #
 # Default: ejabberd@localhost
 #
-#ERLANG_NODE=ejabberd@localhost
+ERLANG_NODE=ejabberd@xmpp1

 #.
 #' EJABBERD_PID_PATH: ejabberd PID file

xmpp1, xmpp2 ともにお互いがお互いのホスト名を解決できるように、/etc/hosts も設定しておきます。ここはDNSが自由に設定できるならそれでも構わないです。 例は省きます。

起動してみる

とりあえず xmpp1 だけ起動してみます。

sudo systemctl start ejabberd

ejabberdctl を使ってステータスを見てみます。

sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl status

こんな結果が戻ればOKです。

The node ejabberd@xmpp1 is started with status: started
ejabberd 0.0 is running in that node

XMPPのホスト名も確認します。example.com が戻ればOKです。

sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl registered_vhosts

ユーザー登録してみる

dummy ユーザーと dummy2 ユーザーを登録してみます。パスワードは pass123 にしました。

sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl register dummy example.com pass123
sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl register dummy2 example.com pass123

User dummy@example.com successfully registered などと表示されれば登録できています。

試しにクライアントから接続してみます。接続先のサーバーはxmpp1のIPアドレスを直接指定します。

PidginというXMPPクライアントでの設定画面はこうなります。 f:id:dreamizm:20191019083200p:plain f:id:dreamizm:20191019082912p:plain

dummy@example.comdummy2@example.com を設定してどちらもオンラインにします。 お互いにユーザー追加をしてメッセージを送れれば大丈夫です。

2号機(xmpp2) もユーザー登録以外は同様の設定をして動かしておきます。

クラスタリング

/usr/local/ejabberd/.erlang.cookie をxmpp1からxmpp2にコピーします。 一応 sha1sum /usr/local/ejabberd/.erlang.cookieハッシュ値を確認して、同一であることを確認します。 ファイルのオーナーも調整しておきます。

sudo chown ejabberd. /usr/local/ejabberd/.erlang.cookie

一旦ejabberdを再起動して

sudo systemctl restart ejabberd

クラスタに参加します。

sudo -u ejabberd /usr/local/ejabberd/sbin/ejabberdctl --no-timeout join_cluster 'ejabberd@xmpp1'

うまくいっていることを確認します。

$ sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl list_cluster
ejabberd@xmpp1
ejabberd@xmpp2

xmpp1とxmpp2で情報が同期されているはずなので、確認します。xmpp2でコマンドを叩いてみます。

$ sudo -u ejabberd -H /usr/local/ejabberd/sbin/ejabberdctl registered_users example.com
dummy
dummy2

dummy@example.com でxmpp1に、 dummy2@example.com でxmpp2に接続してメッセージがやり取りできることを確認しておきましょう。

おわり

以前はejabberdのクラスタリングはmnesiaの同期操作を手作業でしないといけなかったのですが、最近のリリースではコマンドひとつでできるようになりました。 ぜひみなさんも高機能なXMPPで遊んでみてください。