Planet Jabber

February 28, 2020

Alexander Gnauck

Run Snikket on your NAS

Some weeks ago at FOSDEM Matthew Wild announced Snikket. You can find the introduction here in his post.

Many admins are still struggling when they want to run their own XMPP server. One of the strength of XMPP is the extensibility. But this can be also a weakness. It can add a lot of complexity, and a variaty of options you need to choose from for your server install. Many extensions and modules you can choose from during the setup, often dependent on each other. Another burden is often getting your TLS certificate setup fully automated. ALl those pain points are addressed in Skicket.

Snikket is:

  • dockerized
  • certificates are automated by default using Let’s Encrypt
  • all modules to run a modern XMPP server are enabled and perfectly configured out of the box

One specific module to mention is shared roster module. This is what many people expect from a modern instant messaging system by default.
When you run your own family or company team chat server you want all your users being able to communicate with each other out of the box. Without asking them to build the contact list on their own, and request authorization before starting a conversation.

Now I will show how easy it is to install Snikket on a Synology NAS. This tutorial assumes that your Synology NAS has the Docker package already installed.

Step 1: DNS

XMPP is a decentralized system. Similar to Email, where many individual servers communicate to each other. There is no single point of failure. No single company which controls the network and own the users.

This means you need a domain for your Snikket server. And its important that you have access to control the DNS setup. In this sample I am choosing the domain If you websites and other services on your domain its always suggested to use a subdomain for the XMPP services. This is why I decided to use as the Snikket domain.

We need to add the following 3 DNS records. I am pointing to the external IP address of my network.
The other 2 sub domains for groups (group chat service) and share (file share) need to point to the same address or domain. This is why I just use a CNAME records for all of them.

# Domain           TTL  Class  Type  Target  600  IN     CNAME  600  IN     CNAME   600  IN     CNAME

Step 2: Firewall routes

On the firewall the relevant ports get forwarded from the public internet to Snikket which will be running on the Synology NAS. The following 4 ports needs to get forwarded. I redirect ports on the firewall. YOu could to those port redirects also in the docker port setup later.

TCP 80 => TCP 5280 on NAS
TCP 443 => TCP 5281 on NAS
TCP 5222 => TCP 5222 on NAS
TCP 5269 => TCP 5269 on NAS

Step 3: Configure Snikket docker image

Now we switch to our Synology NAS and go to the Docker UI. First we go to the registry tab and search for Snikket docker images. We download the image from the alpha channel.

Once the image is downloaded we press the Launch button. We are getting asked to provide a container name. Lets choose snikket as the name and continue with the advanced settings.
We Enable auto-restart there, to make sure Snikket it running 24/7.

Under volume we mount a local directory from our NAS into the docker image. This is where Snikket will store all persistent data (user data, files, message history etc…)
I create a new directory /docker/snikket_data and mount it as /snikket to our container.

Under port settings we just expose all the required ports we need. In this section you could also redirect the 5280/5281 ports to 80/443. I kept them as is, because we already did the port mapping above on the firewall as described in step 2.

Under environment add the 2 environment variables for the Snikket domain and admin email address.


Now we can save our configuration and start the container. On the first startup Snikket is writing all the configuration files to the volume mount we created above. It also will request the TLS certificates for our subdomains. Lets give Snikket some time for the initial startup. You can look at the logs, or just wait 2-3 minutes.

Now we can just got to the container terminal on the Synology and open a new Bash console. In the console we just type the command which gives us an onboarding link to create the admin user.

create-invite --admin
Copy the link, paste it to a browser on your Desktop or Android device. You should get to a webpage which is hosted on your newly created Snikket server. Just follow the instructions to download the Snikket Android app and create your new admin user.
At any time you can create invites for additional users with the create-invite command. Of course you create your regular users without the --admin option.

That was easy! Now we have our own self hosted secure and federated WhatApp like instant messaging service. Or our company team chat service.

by gnauck at February 28, 2020 16:08

February 26, 2020

Monal IM

Monal for Mac is out

Monal for Mac 4.3 aka the catalyst build is now out in the App Store. Hopefully going forward iOS and Mac will come out at the same time. I will be phasing out the other older Mac client

by Anu at February 26, 2020 22:28


ejabberd 20.02

We are pleased to announce ejabberd version 20.02. After a big release last month, this version is mostly a bugfix release.


  • Fix problems when trying to use string format with Unicode values directly in XMPP nodes
  • Add missing oauth_client table declaration in
  • Improve compatibility with CockroachDB
  • Fix importing of piefxis files that did use scram passwords
  • Fix importing of piefxis files that had multiple includes in them
  • Update jiffy dependency
  • Allow storage of emojis when using MSSQL database (Thanks to Christoph Scholz)
  • Make ejabberd_auth_http be able to use auth_opts
  • Make custom_headers options in HTTP modules correctly override built-in values
  • Fix return value of reload_config and dump_config commands

Downloads & Feedback

As usual, the release is tagged in the Git source code repository on Github.

The source package and binary installers are available at ProcessOne.

If you suspect that you’ve found a bug, please search or fill a bug report on Github.

by Jérôme Sautret at February 26, 2020 14:40


Development News February 2020

Welcome to February’s development news post. This month’s development brought a new look and flow to group chat invitations, some color improvements, and many bug fixes. Gajim Nightly is now also available as a Flatpak app.

February 26, 2020 00:00

February 25, 2020

Paul Schaub

How to Implement a XEP for Smack.

Smack is a FLOSS XMPP client library for Java and Android app development. It takes away much of the burden a developer of a chat application would normally have to carry, so the developer can spend more time working on nice stuff like features instead of having to deal with the protocol stack.

Many (80+ and counting) XMPP Extension Protocols (XEPs) are already implemented in Smack. Today I want to bring you along with me and add support for one more.

What Smack does very well is to follow the Open-Closed-Principle of software architecture. That means while Smacks classes are closed for modification by the developer, it is pretty easy to extend Smack to add support for custom features. If Smack doesn’t fit your needs, don’t change it, extend it!

The most important class in Smack is probably the XMPPConnection, as this is where messages coming from and going to. However, even more important for the developer is what is being sent.

XMPP’s strength comes from the fact that arbitrary XML elements can be exchanged by clients and servers. Heck, the server doesn’t even have to understand what two clients are sending each other. That means that if you need to send some form of data from one device to another, you can simply use XMPP as the transport protocol, serialize your data as XML elements with a namespace that you control and send if off! It doesn’t matter, which XMPP server software you choose, as the server more or less just forwards the data from the sender to the receiver. Awesome!

So lets see how we can extend Smack to add support for a new feature without changing (and therefore potentially breaking) any existing code!

For this article, I chose XEP-0428: Fallback Indication as an example protocol extension. The goal of Fallback Indication is to explicitly mark <body/> elements in messages as fallback. For example some end-to-end encryption mechanisms might still add a body with an explanation that the message is encrypted, so that older clients that cannot decrypt the message due to lack of support still display the explanation text instead. This enables the user to switch to a better client 😛 Another example would be an emoji in the body as fallback for a reaction.

XEP-0428 does this by adding a fallback element to the message:

<message from="" to="" type="chat">
  <fallback xmlns="urn:xmpp:fallback:0"/>  <-- THIS HERE
  <encrypted xmlns="urn:example:crypto">Rgreavgl vf abg n irel ybat
gvzr nccneragyl.</encrypted>
  <body>This message is encrypted.</body>

If a client or server encounter such an element, they can be certain that the body of the message is intended to be a fallback for legacy clients and act accordingly. So how to get this feature into Smack?

After the XMPPConnection, the most important types of classes in Smack are the ExtensionElement interface and the ExtensionElementProvider class. The later defines a class responsible for deserializing or parsing incoming XML into the an object of the former class.

The ExtensionElement is itself an empty interface in that it does not provide anything new, but it is composed from a hierarchy of other interfaces from which it inherits some methods. One notable super class is NamedElement, more on that in just a second. If we start our XEP-0428 implementation by creating a class that implements ExtensionElement, our IDE would create this class body for us:


import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;

public class FallbackIndicationElement implements ExtensionElement {
    public String getNamespace() {
        return null;

    public String getElementName() {
        return null;

    public CharSequence toXML(XmlEnvironment xmlEnvironment) {
        return null;

The first thing we should do is to change the return type of the toXML() method to XmlStringBuilder, as that is more performant and gains us a nice API to work with. We could also leave it as is, but it is generally recommended to return an XmlStringBuilder instead of a boring old CharSequence.

Secondly we should take a look at the XEP to identify what to return in getNamespace() and getElementName().

<fallback xmlns="urn:xmpp:fallback:0"/>
[   ^    ]      [        ^          ]
element name          namespace

In XML, the part right after the opening bracket is the element name. The namespace follows as the value of the xmlns attribute. An element that has both an element name and a namespace is called fully qualified. That’s why ExtensionElement is inheriting from FullyQualifiedElement. In contrast, a NamedElement does only have an element name, but no explicit namespace. In good object oriented manner, Smacks ExtensionElement inherits from FullyQualifiedElement which in term is inheriting from NamedElement but also introduces the getNamespace() method.

So lets turn our new knowledge into code!


import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;

public class FallbackIndicationElement implements ExtensionElement {
    public String getNamespace() {
        return "urn:xmpp:fallback:0";

    public String getElementName() {
        return "fallback";

    public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
        return null;

Hm, now what about this toXML() method? At this point it makes sense to follow good old test driven development practices and create a JUnit test case that verifies the correct serialization of our element.


import static org.jivesoftware.smack.test.util.XmlUnitUtils.assertXmlSimilar;
import org.jivesoftware.smackx.pubsub.FallbackIndicationElement;
import org.junit.jupiter.api.Test;

public class FallbackIndicationElementTest {

    public void serializationTest() {
        FallbackIndicationElement element = new FallbackIndicationElement();

        assertXmlSimilar("<fallback xmlns=\"urn:xmpp:fallback:0\"/>",

Now we can tweak our code until the output of toXml() is just right and we can be sure that if at some point someone starts messing with the code the test will inform us of any breakage. So what now?

Well, we said it is better to use XmlStringBuilder instead of CharSequence, so lets create an instance. Oh! XmlStringBuilder can take an ExtensionElement as constructor argument! Lets do it! What happens if we return new XmlStringBuilder(this); and run the test case?

<fallback xmlns="urn:xmpp:fallback:0"

Almost! The test fails, but the builder already constructed most of the element for us. It prints an opening bracket, followed by the element name and adds an xmlns attribute with our namespace as value. This is typically the “head” of any XML element. What it forgot is to close the element. Lets see… Oh, there’s a closeElement() method that again takes our element as its argument. Lets try it out!

<fallback xmlns="urn:xmpp:fallback:0"</fallback>

Hm, this doesn’t look right either. Its not even valid XML! (ノಠ益ಠ)ノ彡┻━┻ Normally you’d use such a sequence to close an element which contained some child elements, but this one is an empty element. Oh, there it is! closeEmptyElement(). Perfect!

<fallback xmlns="urn:xmpp:fallback:0"/>

import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;

public class FallbackIndicationElement implements ExtensionElement {
    public String getNamespace() {
        return "urn:xmpp:fallback:0";

    public String getElementName() {
        return "fallback";

    public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
        return new XmlStringBuilder(this).closeEmptyElement();

We can now serialize our ExtensionElement into valid XML! At this point we could start sending around FallbackIndications to all our friends and family by adding it to a message object and sending that off using the XMPPConnection. But what is sending without receiving? For this we need to create an implementation of the ExtensionElementProvider custom to our FallbackIndicationElement. So lets start.


import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.xml.XmlPullParser;

public class FallbackIndicationElementProvider
extends ExtensionElementProvider<FallbackIndicationElement> {
    public FallbackIndicationElement parse(XmlPullParser parser,
int initialDepth, XmlEnvironment xmlEnvironment) {
        return null;

Normally implementing the deserialization part in form of a ExtensionElementProvider is tiring enough for me to always do that last, but luckily this is not the case with Fallback Indications. Every FallbackIndicationElement always looks the same. There are no special attributes or – shudder – nested named child elements that need special treating.

Our implementation of the FallbackIndicationElementProvider looks simply like this:


import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.xml.XmlPullParser;

public class FallbackIndicationElementProvider
extends ExtensionElementProvider<FallbackIndicationElement> {
    public FallbackIndicationElement parse(XmlPullParser parser,
int initialDepth, XmlEnvironment xmlEnvironment) {
        return new FallbackIndicationElement();

Very nice! Lets finish the element part by creating a test that makes sure that our provider does as it should by creating another JUnit test. Obviously we have done that before writing any code, right? We can simply put this test method into the same test class as the serialization test.

    public void deserializationTest()
throws XmlPullParserException, IOException, SmackParsingException {
        String xml = "<fallback xmlns=\"urn:xmpp:fallback:0\"/>";
        FallbackIndicationElementProvider provider =
new FallbackIndicationElementProvider();
        XmlPullParser parser = TestUtils.getParser(xml);

        FallbackIndicationElement element = provider.parse(parser);

        assertEquals(new FallbackIndicationElement(), element);

Boom! Working, tested code!

But how does Smack learn about our shiny new FallbackIndicationElementProvider? Internally Smack uses a Manager class to keep track of registered ExtensionElementProviders to choose from when processing incoming XML. Spoiler alert: Smack uses Manager classes for everything!

If we have no way of modifying Smacks code base, we have to manually register our provider by calling

ProviderManager.addExtensionProvider("fallback", "urn:xmpp:fallback:0",
new FallbackIndicationElementProvider());

Element providers that are part of Smacks codebase however are registered using an providers.xml file instead, but the concept stays the same.

Now when receiving a stanza containing a fallback indication, Smack will parse said element into an object that we can acquire from the message object by calling

FallbackIndicationElement element = message.getExtension("fallback",

You should have noticed by now, that the element name and namespace are used and referred to in a number some places, so it makes sense to replace all the occurrences with references to a constant. We will put these into the FallbackIndicationElement where it is easy to find. Additionally we should provide a handy method to extract fallback indication elements from messages.


public class FallbackIndicationElement implements ExtensionElement {
    public static final String NAMESPACE = "urn:xmpp:fallback:0";
    public static final String ELEMENT = "fallback";

    public String getNamespace() {
        return NAMESPACE;

    public String getElementName() {
        return ELEMENT;


    public static FallbackIndicationElement fromMessage(Message message) {
        return message.getExtension(ELEMENT, NAMESPACE);

Did I say Smack uses Managers for everything? Where is the FallbackIndicationManager then? Well, lets create it!


import java.util.Map;
import java.util.WeakHashMap;

import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.XMPPConnection;

public class FallbackIndicationManager extends Manager {

    private static final Map<XMPPConnection, FallbackIndicationManager>
INSTANCES = new WeakHashMap<>();

    public static synchronized FallbackIndicationManager
getInstanceFor(XMPPConnection connection) {
        FallbackIndicationManager manager = INSTANCES.get(connection);
        if (manager == null) {
            manager = new FallbackIndicationManager(connection);
            INSTANCES.put(connection, manager);
        return manager;

    private FallbackIndicationManager(XMPPConnection connection) {

Woah, what happened here? Let me explain.

Smack uses Managers to provide the user (the developer of an application) with an easy access to functionality that the user expects. In order to use some feature, the first thing the user does it to acquire an instance of the respective Manager class for their XMPPConnection. The returned instance is unique for the provided connection, meaning a different connection would get a different instance of the manager class, but the same connection will get the same instance anytime getInstanceFor(connection) is called.

Now what does the user expect from the API we are designing? Probably being able to send fallback indications and being notified whenever we receive one. Lets do sending first!


    private FallbackIndicationManager(XMPPConnection connection) {

    public MessageBuilder addFallbackIndicationToMessage(
MessageBuilder message, String fallbackBody) {
        return message.setBody(fallbackBody)
                .addExtension(new FallbackIndicationElement());


Now, in order to listen for incoming fallback indications, we have to somehow tell Smack to notify us whenever a FallbackIndicationElement comes in. Luckily there is a rather nice way of doing this.


    private FallbackIndicationManager(XMPPConnection connection) {

    private void registerStanzaListener() {
        StanzaFilter filter = new AndFilter(StanzaTypeFilter.MESSAGE, 
                new StanzaExtensionFilter(FallbackIndicationElement.ELEMENT, 
        connection().addAsyncStanzaListener(stanzaListener, filter);

    private final StanzaListener stanzaListener = new StanzaListener() {
        public void processStanza(Stanza packet) 
throws SmackException.NotConnectedException, InterruptedException,
SmackException.NotLoggedInException {
            Message message = (Message) packet;
            FallbackIndicationElement fallbackIndicator =
            String fallbackBody = message.getBody();
            onFallbackIndicationReceived(message, fallbackIndicator,

    private void onFallbackIndicationReceived(Message message,
FallbackIndicationElement fallbackIndicator, String fallbackBody) {
        // do something, eg. notify registered listeners etc.

Now that’s nearly it. One last, very important thing is left to do. XMPP is known for its extensibility (for the better or the worst). If your client supports some feature, it is a good idea to announce this somehow, so that the other end knows about it. That way features can be negotiated so that the sender doesn’t try to use some feature that the other client doesn’t support.

Features are announced by using XEP-0115: Entity Capabilities, which is based on XEP-0030: Service Discovery. Smack supports this using the ServiceDiscoveryManager. We can announce support for Fallback Indications by letting our manager call


somewhere, for example in its constructor. Now the world knows that we know what Fallback Indications are. We should however also provide our users with the possibility to check if their contacts support that feature as well! So lets add a method for that to our manager!

    public boolean userSupportsFallbackIndications(EntityBareJid jid) 
            throws XMPPException.XMPPErrorException,
SmackException.NotConnectedException, InterruptedException, 
            SmackException.NoResponseException {
        return ServiceDiscoveryManager.getInstanceFor(connection())
                .supportsFeature(jid, FallbackIndicationElement.NAMESPACE);


I hope this little article brought you some insights into the XMPP protocol and especially into the development process of protocol libraries such as Smack, even though the demonstrated feature was not very spectacular.

Quick reminder that the next Google Summer of Code is coming soon and the XMPP Standards Foundation got accepted 😉
Check out the project ideas page!

Happy Hacking!

by vanitasvitae at February 25, 2020 20:54

Ignite Realtime Blog

REST API Openfire plugin 1.4.0 released

@wroot wrote:

The Ignite Realtime community is happy to announce the immediate release of version 1.4.0 of the REST API plugin for Openfire!

The REST API plugin provides the ability to manage Openfire by sending a REST/HTTP request to the server.

This update upgrades jackson library to 1.9.11 and also makes new version available in Admin Console again.

Your instance of Openfire should automatically display the availability of the update in the next few hours. Alternatively, you can download the new release of the plugin at the REST API plugin archive page

For other release announcements and news follow us on Twitter

Posts: 2

Participants: 2

Read full topic

by @wroot wroot at February 25, 2020 05:17

February 22, 2020

Monal IM

Burned by an old typo

At some point a long time ago while writing the OMEMO code I entered in the device features. While returning the features that Monal supported, I returned eu.siacs.conversations.axolotl.devicelist instead of eu.siacs.conversations.axolotl.devicelist+notify . The missing +notify meant I didn’t get notifications when the device list changed causing all sort of havoc. Thankfully its been fixed and there is a new Mac beta up as well as a TestFlight build. Thanks everyone for all of your testing, its been gradual but few things shine a light on bugs like testing.

by Anu at February 22, 2020 04:21

February 21, 2020

Monal IM

Mac Catalyst delayed in the Appstore.. it’s blocking the keychain

It seems that the mac app store is currently blocking the use of the keychain as a non public api. It’s clearly a bug because this has worked fine for a decade and until yesterday there were no issues. Until they resolve this, i can’t upload new catalyst builds — including the one intended for the appstore

ITMS-90338: Non-public API usage – The app references non-public symbols in Contents/Frameworks/SAMKeychain.framework/Versions/A/SAMKeychain: _SecItemAdd, _SecItemCopyMatching, _SecItemDelete, _SecItemUpdate, _kSecAttrAccessible, _kSecAttrAccount, _kSecAttrLabel, _kSecAttrService, _kSecAttrSynchronizableAny, _kSecClass, _kSecMatchLimit, _kSecMatchLimitAll, _kSecMatchLimitOne, _kSecReturnAttributes, _kSecReturnData, _kSecValueData,

by Anu at February 21, 2020 03:24

February 20, 2020

Monal IM

Removing Google talk

I am planning to remove Google talk support from 4.4 onwards for Mac and iOS. Its an sad milestone because Google talk was why I made Monal in 2008. However, given google themselves have deprecated it twice and even its replacement google chat has been deprecated, it seems increasingly less important. Additionally, the fact that it does not support any modern xmpp specs and doesn’t work with push means it is barely usable in current versions of Monal. I don’t track user stats but I suspect everyone who used to use this for google has moved on to other clients or slack.

If you *REALLY* need Google talk the legacy mac client will still be around for a little bit.

by Anu at February 20, 2020 20:24

New Mac and iOS beta bre updated

There was a bug in last nights iOS and Mac builds that caused it to crash on group chats. I have updated both clients now. I have also linked the old file to the catalyst version. Catalyst is the mac client now. This should allow brew users to get it as well. Unlike the old Monal for mac, the new one is sandboxed, hardened runtime and notarized.

by Anu at February 20, 2020 14:02

XMPP is weird

There are many weird things about xmpp. The contact approval system and the need to approve a contact to send encrypted messages is probably one of the best examples. A lot of OMEMO issues can probably be traced to your contacts subscription either being to, from or none. Those words alone don’t make much sense so I have added some “debugging” text for users in contact details.

by Anu at February 20, 2020 03:58

February 19, 2020

Monal IM

Monal iOS is available in France

Monal 4.3 if out for iOS. Mac os will come soon. It’s taking longer because it is treated as a new app. I am leaving the other mac app in the app store for older macs. This change in 4.3 also means it is now available in france.

On a related note the first build of 4.4 for Mac is in beta. This has some fixes for message duplication as well as OMEMO device and key discovery. iOS will come soon.

by Anu at February 19, 2020 17:56


ejabberd on macOS with Homebrew package manager

Homebrew is now the de facto package manager for open source software on macOS. Thus, we have discontinued our macOS binary installer to focus on improving further ejabberd experience on macOS by polishing Homebrew ejabberd package.

We recently updated ejabberd on Homebrew and we will keep it in sync with ejabberd official releases. As of today, if you install ejabberd with Homebrew, you will always get the latest release.

If you have any suggestion on how to make ejabberd with Homebrew experience better, please open a Github issues, with the tag Packaging:Homebrew.

We have not yet tested it with Homebrew on Linux or on WSL, but still, pleae submit issues if you find some.

Here is the cheat sheet regarding ejabberd management with Homebrew.

Installing ejabberd

The following command will install ejabberd and its dependencies:

$ brew install ejabberd

Starting ejabberd and launching it on macOS start

brew services start ejabberd

Starting ejabberd

Alternatively, the following command start ejabberd in background, with trying to restart it automatically after reboot:

$ /usr/local/sbin/ejabberdctl start

You can check the status with the command:

$ /usr/local/sbin/ejabberdctl status
The node ejabberd@localhost is started with status: started
ejabberd 20.01 is running in that node

If ejabberd is not running the status command will display a nodedown error:

$ /usr/local/sbin/ejabberdctl status
Failed RPC connection to the node ejabberd@localhost: nodedown

Commands to start an ejabberd node:
  start      Start an ejabberd node in server mode
  debug      Attach an interactive Erlang shell to a running ejabberd node
  iexdebug   Attach an interactive Elixir shell to a running ejabberd node
  live       Start an ejabberd node in live (interactive) mode
  iexlive    Start an ejabberd node in live (interactive) mode, within an Elixir shell
  foreground Start an ejabberd node in server mode (attached)

Optional parameters when starting an ejabberd node:
  --config-dir dir   Config ejabberd:    /usr/local/etc/ejabberd
  --config file      Config ejabberd:    /usr/local/etc/ejabberd/ejabberd.yml
  --ctl-config file  Config ejabberdctl: /usr/local/etc/ejabberd/ejabberdctl.cfg
  --logs dir         Directory for logs: /usr/local/var/log/ejabberd
  --spool dir        Database spool dir: /usr/local/var/lib/ejabberd
  --node nodename    ejabberd node name: ejabberd@localhost

Stopping ejabberd

/usr/local/sbin/ejabberdctl stop

Configuration file

To change the configuration file, you can edit /usr/local/etc/ejabberd/ejabberd.yml

If you have upgraded ejabberd and want to apply possible change to config file, you can check the new ejabberd.yml default file ejabberd.yml-new in the same directory.

Checking the logs

To troubleshoot ejabberd, you can check the logs in the directory /usr/local/var/log/ejabberd/

by Mickaël Rémond at February 19, 2020 12:49

February 18, 2020

Tigase Blog

BeagleIM 3.6 and SiskinIM 5.6 released

New versions of XMPP clients for Apple’s mobile and desktop platforms have been released.

Common changes

  • Improve DNS SRV resolver reliability
  • Added support for preauthenticated subscriptions and registration
  • Improve bookmarks support (Workaround for buggy PEP implementation in some servers)
  • Added conditional support for sending files for which HTTP File Upload server returned code 200

BeagleIM 3.6

The stable release of BeagleIM 3.6 contains the following changes

  • Fixed an issue with VCard editing
  • Fixed count of unread messages after restart of the app
  • Prepend groupchat items in chats list with sender nickname of last message
  • Minor changes to displaying subject of MUC room
  • Fixed crash on emoji in input field in MUC rooms
  • Fixed a crash while searching the messages

SiskinIM 5.6

The stable release of SiskinIM 5.6 contains the following changes:

  • Add QR code for accounts
  • Fixed an issue with files not being encrypted when only global encryption is enabled
  • Improved support for handling XMPP URI and account handling
  • Enable file transfer button and ask user for consent if he was not asked yet
  • Fixed crash related to keyboard animation
  • Fixed crash when rows are disappearing from the screen
  • Fixed crashes on iOS 11
  • Fixed a crash within roster view


You can download both application from their respective app-stores: Beagle IM from macOS appstore and Siskin IM from iOS appstore and star them on GitHub: Siskin IM on GitHub and Beagle IM on GitHub

February 18, 2020 12:40

Jérôme Poisson

SàT progress note 2020-W08

Hello everybody,

it's been a while since the last progress note, that's because I have very little free time at the moment, and I use it to code instead of writing blog posts.

So I'll try to summarize the last weeks progress without going too much into details.

Continuing my work on improving Cagou usability, I've added a panel which shows open chat rooms, all your contacts, and bookmarks. It was necessary to have a way to select easily a contact or room, as so far you had to enter part of the name and count on autocompletion. So now, by default you land into a screen showing you icons of contacts/rooms, and you just have to click on them.

chat selector demo

In chat mode with Cagou, you can slide between open discussions without having to go back and forth in the menu. The order in which you do the slide correspond to the order in which icons appears in the "chat selection" panel. They are sorted by alphabetical order for the moment, but it will be easy to add other way to sort, for instance by time of last received message.

sliding between chats demo

I've added a notification counter, so you know immediately where somebody has talked to you.

A chat notification

For now the icons are arranged in a grid, but it may be possible to add other layouts in the future, like showing the chats entities in a list (which would give more room to display extra data like the last message).

On Android, opening a system notification for a chat message now opens the right chat widget in Cagou.

I've also improved session reopening: when the frontend is closed on Android, the last connected profile will be reconnected automatically, as well as the last selected mode. This was also the occasion to implement profile auto connection on backend startup, which is particularly useful for components.

I had to fix SRV records handling on Android: this platform doesn't use /etc/resolv.conf which Twisted expects, and finding the DNS servers used is not trivial. Thanks to some hints I've found (notably here), I could implement a decent solution to work around that and make SRV records looking work.

On desktop, I've removed the main top menu, as it is redundant with features available elsewhere. Instead there is a new "extra" button in mode selector, which open a side menu (this is how you open the "about" screen for instance).

There have been also a bunch of improvements like logging the path of parsed config file(s), the implementation of a stable resource instead of the one given by server (something like sat.[ID]), the handling of runtime permissions on Android, a better management of header's input in Cagou, many bug fixes, etc. I won't enumerate everything, this note is to have a global overview of the work done or in progress, the direction taken, and the reasons behind some decisions.

I'm currently finishing the handling of file attachments in chats, I will then move on Libervia.

That's all for today.

by goffi at February 18, 2020 11:21

Monal IM

Expect to see 4.3 this week

Monal 4.3 will be in the app store this week. In conjunction with that I have updated the home page to reflect the app as it is going to be. Needless to say the front page is very non technical. On a related note, I now remember how making accurate screenshots for every iOS supported device, iPad and Mac is incredibly tedious. There is a reason I don’t do dramatic UI updates like this every day.

by Anu at February 18, 2020 04:36

February 17, 2020

Monal IM

Mac and iOS: improving error handling

As we march along to a release, I have added better error handling in the mac and iOS client. A lot of this is focused on OMEMO. The most recent update today includes these changes in addition to fixes to sending/receiving aesgcm images. In the new error messages I have tried my best to provide some debugging info or some action that could be taken to potentially resolve this issue. It also lets me know in user feedback where an error in Monal my be.

If someone sends a 16 byte iv message this is what you will see:

Encrypted message was sent in an older format Monal can’t decrypt. Please ask them to update their client. (GCM error)

If the key was decrypted but an error was returned by lib signal:

There was an error decrypting this encrypted message (Signal error). To resolve this, try sending an encrypted message to this person.

If the message was not encrypted for this device it would be nice ot know what this device meant for the other party to verify:

Message was not encrypted for this device. Please make sure the sender trusts deviceid 123456 and that they have you as a contact.

by Anu at February 17, 2020 03:57

Paul Schaub

Smack: Some more busy nights and 12 bytes of IV

In the last months I stayed up late some nights, so I decided to add some additional features to Smack.

Among the additions is support for some new XEPs, namely:

I also started working on an implementation of XEP-0245: Message Moderation, but that one is not yet finished and needs more work.

Direct MUC invitations are a method to invite users to a group chat. Smack already had support for another similar mechanism, but this one is recommended by the XMPP Compliance Suites 2020.

Message Fastening is a generalized mechanism to add information to messages. That might be a reaction, eg. a thumbs up which is added to a previous message.

Message Retraction is used to retract previously sent messages. Internally it is based on Message Fastening.

The Stanza Content Encryption pull request only teaches Smack what SCE elements are, but it doesn’t yet teach it how to use them. That is partly due to no E2EE specification actually using them yet. That will hopefully change soon 😉

Anu brought up the fact that the OMEMO XEP is not totally clear on the length of initialization vectors used for message encryption. Historically most clients use 16 bytes length, while normally you would want to use 12. Apparently some AES-GCM libraries on iOS only support 12 bytes length, so using 12 bytes is definitely desirable. Most OMEMO implementations already support receiving 12 bytes as well as 16 bytes IV.

That’s why Smack will soon also start sending OMEMO messages with 12 bytes IV.

by vanitasvitae at February 17, 2020 00:34

February 15, 2020

Monal IM

New builds (again)

There is a new Mac and iOS build up for testing. The changes fix:

  1. Message duplication (Receiving)
  2. Crashing on ios12

by Anu at February 15, 2020 03:05

February 14, 2020


Last Message Correction

From 10th to 14th February 2020 we had Hackweek 19 at SUSE. Part of that time I used to finally implement the long (since 2016!) sought after Last Message Correction feature, aka XEP-0308.

See my Hackweek project and the corresponding pull request.


To enable incoming and outgoing corrections users need to enable it with /correction on, see /help correction for more details.

Now we write a message to a friend /msg Martin Hey therr!.

Ouch! Already a typo.

Let’s make this right: /corr<TAB> <TAB> will autocomplete to /correct Hey therr! which then can easily be fixed and re-send.

mistake corrected


The feature is only available in the development version of Profanity. In the master branch on git. So it’s not yet ready for release.

Master branch corresponds always to our development and doesn’t guarantee anything. It’s where we develop test and experiment. We write these blogposts from time to time to inform our users and sponsors about what we are currently working on.

The LMC feature is in there. But for the correct behaviour we need to rewrite the UI code. We could hack a ‘from’ field in but we want to think more carefully how to implement it nicely. For this reason in the current state we don’t check the ‘from’ attribute of the sender. Because at the time of drawing so far we don’t have this information.

Since LMC is off by default noone is at harm. But people who choose to enable it need to be aware that in theory it would be possible for other users to send special messages where they could “correct” a message of someone else. We think the damage and likeliness from this is quite low. And once again, this is only in our development version of Profanity.

February 14, 2020 10:34

February 13, 2020

Monal IM

Monal 4.3 is coming out in about a week (even in France)

Monal 4.3 is going to be a huge update the iOS and Mac UI. It is feature complete and has been in testing for a few weeks. I expect to release it next week. When it comes out though, I will have switched to Apple’s GCM library this will also allow me to release in France. The change in libraries will prevent OMEMO from working with some other clients. Clients that send with a 16 byte iv will not be able to send to Monal anymore. Client that can’t accept the 12 byte iv will not be able to accept message from Monal anymore.

by Anu at February 13, 2020 15:04

February 12, 2020

Monal IM

New Mac and iOS builds

You may notice that the only mac builds are catalyst builds. I have removed the download links for the older versions. Catalyst is almost ready for release. There are new builds for both clients with the following fixes:

Unread/read status of chats fixed
Account selection for new contact
Account selection for new Group
Groups show up reliably when you join
Chats show up reliably when you add contacts

by Anu at February 12, 2020 05:34

February 10, 2020


ejabberd 20.01

We are pleased to announce ejabberd version 20.01. This release focuses on OAUTH support, logging performances improvement and configuration helper, as well as the usual various bug fixes.

New Features and improvements


We are now supporting OAUTH to authenticate with the embedded MQTT server.

This will only work for MQTT 5.0 connections. A client MUST set “Authentication Method” property of CONNECT packet to “X-OAUTH2” and MUST set the token in “Authentication Data” property of the same CONNECT packet. The server responses as usual with CONNACK.

On the server, you just have to enable OAUTH authentication like for XMPP, as described in the post about understanding ejabberd OAuth support.


We are now using the new logger introduced in OTP22, instead of lagger. This should greatly improve performance of the logging infrastructure.


A new configuration parser/validator was added, to check ejabberd.yml syntax and find configuration issues.

SCRAM support

The routine to convert password to SCRAM format now works for all backends, not only SQL.


We’ve started to add to support to use CockroachDB as database backend.

Technical changes

Database schema changes

To migrate from 19.09 to 20.01, you have to use the following commands on your existing database, after you’ve made a backup of it:


If you are using the legacy mysql.sql schema:

ALTER TABLE  oauth_client CHANGE `client` `client_id` text PRIMARY KEY;
ALTER TABLE  oauth_client CHANGE `secret` `client_name` text NOT NULL;

If you are using the newer schema:

CREATE TABLE oauth_client (
   client_id varchar(191) NOT NULL PRIMARY KEY,
   client_name text NOT NULL,
   grant_type text NOT NULL,
   options text NOT NULL


CREATE TABLE oauth_client (
    client_id text PRIMARY KEY,
    client_name text NOT NULL,
    grant_type text NOT NULL,
    options text NOT NULL
ALTER TABLE oauth_client RENAME COLUMN client TO client_id;
ALTER TABLE oauth_client RENAME COLUMN secret TO client_name;

Download and install ejabberd 20.01

The source package and binary installers are available at ProcessOne. If you installed a previous version, there are no additional upgrade steps, but as a good practice, plase backup your data.

As usual, the release is tagged in the Git source code repository on Github. If you suspect that you’ve found a bug, please search or fill a bug report in Issues.

Full changelog

* New features
– Implement OAUTH authentication in MQTT
– Make logging infrastructure use new logger introduced
in Erlang (requires OTP22)
– New configuration parser/validator
– Initial work on being able to use CockroachDB as database backend
– Add gc command
– Add option to disable using prepared statements on Postgresql
– Implement routine for converting password to SCRAM format for all backends not only SQL
– Add infrastructure for having module documentation directly in individual module source code
– Generate man page automatically
– Implement copy feature in mod_carboncopy

* Fixes
– Make webadmin work with configurable paths
– Fix handling of result in xmlrpc module
– Make webadmin work even when accessed through not declared domain
– Better error reporting in xmlrpc
– Limit ammount of results returned by disco queries to pubsub nodes
– Improve validation of configured JWT keys
– Fix race condition in Redis/SQL startup
– Fix loading order of third party modules
– Fix reloading of ACL rules
– Make account removal requests properly route response
– Improve handling of malformed inputs in send_message command
– Omit push notification if storing message in offline storage failed
– Fix crash in stream management when timeout was not set

by Jérôme Sautret at February 10, 2020 23:36

Erlang Solutions

Improving push notifications with MongooseIM

Customised, scalable enterprise Instant Messaging.

MongooseIM offers a completely customisable enterprise Instant Messaging solution. This helps large organisations build solutions that meet the unique requirements of their users. As a result, we’ve built many best-in-class instant messaging platforms for household names in social media, telecoms and the health industry. In our latest release, MongooseIM 3.6.0, we’ve continued to empower our application owners, and their end users by improving and evolving the push notification functionality. Find out more about how MongooseIM can build a bespoke instant messaging solution for your needs, or read on to find out more about the improvements to push notifications.

Creating a better Push Notification Experience in MongooseIM

MongooseIM is continuing its evolution to improve the user experience for mobile applications. Push notifications aren’t just a standard requirement for instant messaging applications; they are also one of the most used features for end-users. As a result, there is an increased need to have a seamless experience for both application owners and the user themselves. Push notifications were added to MongooseIM 3 years ago. The implementation was based on an XMPP extension XEP-0357: Push Notifications and a dedicated, standalone component called MongoosePush. Since then, we have been lucky enough to work with several customers using this functionality. We have also been given great feedback from our community including people who use MongooseIM, MongoosePush or both in their projects. We listened to them, observed their issues and decided to create a better experience in MongooseIM 3.6.0 and MongoosePush 2.0.

How has the MongooseIM end-user experience changed?

Immediate push notifications

Push notifications are delivered when the server observes a message addressed to a user who is offline. What does this mean exactly? From the server perspective, it means that the user has no connected devices. This works well enough in cases where users only have one device and don’t use session resumption as described in XEP-0198: Stream Management. Today, this is not the most common use case when it comes to mobile applications. First of all XEP-0198 is used because it helps to make sure that stanzas are delivered from the server to the client and the other way around. What is also important to note is that mobile applications are not always active. People switch applications or put their phone down. In this case, the app goes into the background and the network communication is limited to save battery. This leads to a situation where a device may not respond to regular TCP communication (because it’s disconnected or in the background) and the server still thinks the user is online. Push notifications are often used to notify the user that there is new information for them to check, so it is important that the notification is delivered in seconds, not minutes. In order to solve the problem, MongooseIM 3.6.0 and later versions, can send push notifications to such user sessions which are in the “undecided” state. More technical details and information on how to configure this behaviour can be found in the push notifications documentation.

Fine grained push notifications priority control

Not all Push Notifications will have the same level of priority. Sometimes you will want to change the priority in order to have a different behaviour on the client device. Before MongooseIM 3.6.0 it was not possible to change the priority level, even though MongoosePush, which talks to FCM or APNS, has that functionality. In order to address this limitation, we decided to give the control of the priority to the application developer. Now the priority can be set while enabling push notifications. Take a look at the enabling push notifications documentation to see the possible values and the other options you can set while enabling push notifications.

How has MongooseIM changed from for the operator?

No PubSub

The other thing we learned from our users was that they always use MongooseIM as both the instant messaging server and the service responsible for sending push notifications. The XEP-0357: Push Notifications is very generic and allows you to configure a PubSub service responsible for delivering push notifications on a different server. This was not the case in all the installations we were aware of. Because of that, we decided to bypass the PubSub communication in a situation where we know MongooseIM is responsible for sending push notifications. This makes the MongooseIM configuration easier, with no need to configure the PubSub service. What is more important is that it reduces the load on the nodes and minimises delays in delivering push notifications. In the PubSub-less configuration, MongooseIM can talk directly to MongoosePush in order to deliver push notifications. This was implemented in a way that allows smooth migrations for older versions of MongooseIM where push notifications were already used in the full version. More details about all the possible setups, their advantages and drawbacks can be found in our push notification tutorial.

RDBMS backend

In production systems it’s more convenient to store persistent data in an external database. It makes life easier when it comes to clustering MongooseIM and using it in containers. One of the previous releases introduced an RDBMS backend for PubSub but this kind of backend was still missing for push notifications. Now we have it, so you can start storing all the details, passed from the app when enabling push notifications and required to deliver them in Postgres, MySQL or even MSSQL.

Inactive device id removed

The device ids (in other words device tokens you get from APNS or FCM) are not valid indefinitely. Generating push notifications to expired tokens doesn’t make sense and introduces unneeded load in the system. Thanks to integrating with MongoosePush 2.0 and it’s new API v3 for push notifications, MongooseIM can detect if a push notification was sent to a device token which is no longer active and remove it from its database. Thanks to that we eliminate stale data as soon as we know it is no longer useful.

MongoosePush 2.0.0

The last 6 months were also busy around MongoosePush development. It’s a standalone service written in Elixir. It exposes a simple HTTP (1.1 and 2.0) API which can be used to trigger push notifications to FCM and APNS. The recent version added support for new authentication methods to APNS, support for new FCM v1 protocol and unified error codes which allows for instances to detect if the device token is active or not.

More information can be found in MongoosePush 2.0.0 changelog and its documentation on GitHub esl/MongoosePush.

Other changes

Push notification improvements are not the only change in MongooseIM 3.6.0. Take a look at 3.6.0 changelog to learn more and give it a try and share feedback!

Help us improve the MongooseIM platform:

  1. Star our repo: esl/MongooseIM
  2. Report issues: esl/MongooseIM/issues
  3. Share your thoughts via Twitter
  4. Download MongooseIM 3.6.0 Docker image
  5. Download MongoosePush 2.0.0 Docker image
  6. Sign up to our dedicated mailing list to stay up to date about MongooseIM, messaging innovations and industry news.
  7. Check out our MongooseIM product page for more information on the MongooseIM platform.

February 10, 2020 14:44

Monal IM

Catalyst looks more like a Mac App

The neat thing about catalyst apps is that while it is the iOS code and UI you can also adjust it to add Mac functionality. Rather than having to rebuild a second app, I am able add on Mac features or tweak the iOS ones to work like a mac. The next catalyst build will show some of this. New features:

Unified title bar (like first party apps)

Fully functional Mac menus:

Yes, the keyboard short cuts works
The ones here work as well and make editing the chats screen easier

Mac file dialogs instead of brining up the iOS photo selector/camera when you attach a file or change the background.

I will add drag and drop in a future update. This will also bring drag and drop and keyboard shortcuts to the iPad app. This is an example of how Catalyst has sped up development bu reducing the amount of code and testing needed. There is a lot to be excited about here for the Mac, I hope other developers are doing similar things.

by Anu at February 10, 2020 03:30