Running your own XMPP server on Debian or Ubuntu - ejabberd
in order to get closer to my goal of reducing my dependence on centralized services, I decided to setup my own XMPP / Jabber server on a server running Debian wheezy. I chose ejabberd since it was recommended by the RTC Quick Start website and here's how I put everything together.
DNS and SSL
My personal domain is fmarier.org and so I created the following DNS records:
jabber-gw CNAME fmarier.org.
_xmpp-client._tcp SRV 5 0 5222 jabber-gw.fmarier.org.
_xmpp-server._tcp SRV 5 0 5269 jabber-gw.fmarier.org.
Then I went to get a free TLS certificate for jabber-gw.fmarier.org and fmarier.org.
Let's Encrypt
The easiest way to get a certificate is to install certbot from debian-backports by adding the following to your /etc/apt/sources.list:
deb http://httpredir.debian.org/debian jessie-backports main contrib non-free
and then installing the package:
apt update && apt install certbot
Then, shutdown your existing webserver if you have one running and request a cert like this:
certbot certonly -d jabber-gw.fmarier.org,fmarier.org --standalone
Once you have the cert, you can merge the private and public keys into the file that ejabberd expects:
cat /etc/letsencrypt/live/jabber-gw.fmarier.org/privkey.pem /etc/letsencrypt/live/jabber-gw.fmarier.org/fullchain.pem > ejabberd.pem
and then restart the service:
systemctl restart ejabberd.service
I wrote a cronjob to renew this certificate automatically using certbot.
StartSSL
I have also used StartSSL successfully. This is how I generated the CSR (Certificate Signing Request) on a high-entropy machine:
openssl req -new -newkey rsa:2048 -sha256 -nodes -out ssl.csr -keyout ssl.key -subj "/C=NZ/CN=jabber-gw.fmarier.org"
I downloaded the signed certificate as well as the StartSSL intermediate certificate and combined them this way:
cat ssl.crt ssl.key sub.class1.server.ca.pem > ejabberd.pem
ejabberd installation
Installing ejabberd on Debian is pretty simple and I mostly followed the steps on the Ubuntu wiki with an additional customization to solve the Pidgin "Not authorized" connection problems.
Install the package, using "admin" as the username for the administrative user:
apt-get install ejabberd
Set the following in /etc/ejabberd/ejabberd.yml (don't forget the trailing dots!):
acl:
admin:
user:
- "admin": "fmarier.org"
hosts:
- "fmarier.org"
auth_password_format: scram
fqdn: "jabber-gw.fmarier.org"
Copy the SSL certificate into the /etc/ejabberd/ directory and set the permissions correctly:
chown root:ejabberd /etc/ejabberd/ejabberd.pem
chmod 640 /etc/ejabberd/ejabberd.pem
Improve the client-to-server TLS configuration by adding starttls_required to this block:
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
certfile: "/etc/ejabberd/ejabberd.pem"
starttls: true
starttls_required: true
protocol_options:
- "no_sslv3"
- "no_tlsv1"
- "no_tlsv1_1"
- "cipher_server_preference"
ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
tls_compression: false
dhfile: "/etc/ejabberd/dh2048.pem"
max_stanza_size: 65536
shaper: c2s_shaper
access: c2s
s2s_use_starttls: required_trusted
s2s_protocol_options:
- "no_sslv3"
- "no_tlsv1"
- "no_tlsv1_1"
- "cipher_server_preference"
s2s_dhfile: "/etc/ejabberd/dh2048.pem"
s2s_ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
Create the required dh2048.pem file:
openssl dhparam -out /etc/ssl/ejabberd/dh2048.pem 2048
Restart the ejabberd daemon:
/etc/init.d/ejabberd restart
Create a new user account for yourself:
ejabberdctl register me fmarier.org P@ssw0rd1!
Open up the following ports on the server's firewall:
iptables -A INPUT -p tcp --dport 5222 -j ACCEPT
iptables -A INPUT -p tcp --dport 5269 -j ACCEPT
Optionally create a cronjob in /etc/cron.d/restart-ejabberd to restart ejabberd once a day to ensure it doesn't stop responding to requests after running for a while:
0 4 * * * root /bin/systemctl restart ejabberd.service
Note that if you'd like to be able to talk to contact via the GMail XMPP server, you will unfortunately need to change the s2s_use_starttls setting in step 3 to the following:
s2s_use_starttls: optional
Client setup
On the client side, if you use Pidgin, create a new account with the following settings in the "Basic" tab:
Protocol: XMPP
Username: me
Domain: fmarier.org
Password: P@ssw0rd1!
and the following setting in the "Advanced" tab:
Connection security: Require encryption
From this, I was able to connect to the server without clicking through any certificate warnings.
Testing
If you want to make sure that XMPP federation works, add your GMail address as a buddy to the account and send yourself a test message.
In this example, the XMPP address I give to my friends is me@fmarier.org.
Finally, to ensure that your TLS settings are reasonable, use this automated tool to test both the client-to-server (c2s) and the server-to-server (s2s) flows.
Spam protection
If you start having problems with spammers sending messages or subscription requests to your users, you can whitelist the servers that are allowed to federate with yours by putting the following in /etc/ejabberd/ejabberd.yml:
acl:
trusted_servers:
server:
- "cheogram.com"
- "conference.soprani.ca"
- "conversations.im"
access:
s2s:
trusted_servers: allow
all: deny
s2s_access: s2s
RSS Atom
Better alternatives...
Personally I'd suggest prosody rather than ejabberd which (IMO) is a pain to install and configure.
If you want something ejabberd-ish then there's also the mongoose.im project which was forked from ejabberd and has implemented many new (and working) features.
Comment by Steven Watkin — 06:36, 03 January 2014
Remove comment
comment 2
I found the opposite - that ejabberd was much easier than both Prosody and Mongoose.IM to set up (Mongoose is probably easy on Debian/Ubuntu, but on Amazon Linux the dependencies are harder to install).
Comment by Anonymous — 05:08, 12 August 2014
Remove comment
comment 3
Thank you for this great howto.
Is there anyway to establish an s2s connexion with a domain that does not have SRV record? Some of my contact use gtalk with googleApps with their domain and does not have access to their DNS server. Is their anyway to disable TLS with all domains that use google's server?
Thank you, Regards. Charlie
Comment by Charlie — 13:34, 16 October 2014
Remove comment
LetsEncrypt
Looking for good install guide. The only drawback I see in reading your directions (I haven't done this yet) is the fact that you are concatenating key/bundle/csr to static file - and LE certs expire quickly. You will have to repeat this every 90 days. I suppose I could come up with a root cronjob to do it as a certbot cron.d 'post-renew' job, but I am guessing there is a better way.. if I find I will post again.
Comment by B. Shea — 10:20, 24 August 2018
Remove comment
Re: LetsEncrypt
I suppose I could come up with a root cronjob to do it
Indeed, that's exactly how I have my letsencrypt certs set to renew automatically using certbot.
Comment by francois — 14:24, 24 August 2018
Remove comment
https://feeding.cloud.geek.nz/posts/running-your-own-xmpp-server-debian-ubuntu/