Skip to content

Release history

ejabberd releases

XMPP instant messaging server.

All releases

7 shown

26.04 Breaking risk
Security fixes
  • Added `max_stanza_elements`, `pre_auth_max_stanza_elements`, and `pre_auth_max_stanza_size` options to limit XML parser input, preventing potential Denial of Service attacks
Notable features
  • New listener options `max_stanza_elements`, `pre_auth_max_stanza_elements`, and `pre_auth_max_stanza_size` limit XML stanza size/memory usage
  • Keyword `DATABASE_PATH` points to Mnesia spool directory
  • HOST keyword supported in `sql_database` top‑level option with sensible default
Full changelog

Release notes copied from the original ejabberd 26.04 announcement post:

We are publishing this security release ejabberd 26.04, which includes options to limit XML parser, and other minor bugfixes. It is strongly encouraged that you update ejabberd as soon as possible.

Contents:

New limits options for XML parser

This release adds new options that limit max memory used by XML parser used to process XMPP payloads, to prevent potential Denial of Service attack. The default values for pre-auth provide sufficient protection for ejabberd against non-authenticated users on c2s and s2s, so there is no need to change your configuration.

The option max_stanza_elements sets a limit on the maximum number of XML elements that an individual stanza can contain. By default, this option is set to infinity.

The pair of options pre_auth_max_stanza_elements and pre_auth_max_stanza_size define separate limits for sessions that haven't authenticated yet. The session will switch to the limits defined by the options max_stanza_elements and max_stanza_size after the client has successfully authenticated. The default values for these options are: 32 for pre_auth_max_stanza_elements and 8192 for pre_auth_max_stanza_size.

All those options are recognized inside listener sections, and can be applied to ejabberd_c2s and ejabberd_s2s_in listeners.

ChangeLog

Core

  • Add new listener options to limit xml parser accepted input
  • Improve leave_cluster command to work even in own node
  • New predefined keyword DATABASE_PATH that points to the Mnesia spool dir
  • Support HOST keyword in sql_database toplevel option, set nice default value
  • Provide more details in log messages when using SQLite
  • Update documentation of jwt_key to match the Docs site
  • ejabberd_config: New default_ram_db/3 clause that checks module support
  • ejabberd_sm: Remove session_counter, used for get_vh_session_number now removed

Modules

  • mod_http_fileserver: Use integer in ejabberd_hooks:add as expected by "make hooks"
  • mod_invites: Add --enable-bootstrap=no to configure options to bypass download (#4558)
  • mod_invites: don't crash in get_invite_by_invitee_t for sql backend (#4566)
  • mod_invites: quick howto for creating integrity check checksums
  • mod_invites: remove dependency on jquery
  • mod_mqtt: Define RAM callbacks as optional
  • mod_mqtt: Use default_ram_db only if it really supports RAM storage
  • mod_roster: Fix bug introduced in 26.03 in commit d5c1440 (#4564)
  • mod_roster_sql: Cast approved integer as boolean when exporting Mnesia to SQL
  • mod_shared_roster_sql: Fix typo introduced 10 years ago in commit 0ea0ba30

Container and Installers

  • Bump Erlang/OTP 28.4.2
  • make-binaries: Bump OpenSSL to 3.5.6

Full Changelog

https://github.com/processone/ejabberd/compare/26.03...26.04

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

ejabberd 26.04 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

26.03 Breaking risk
Breaking changes
  • Adds `approved` boolean column to the `rosterusers` table; upgrade must run `ALTER TABLE rosterusers ADD COLUMN approved boolean NOT NULL AFTER subscription;`. If `update_sql_schema` is disabled, the change must be applied manually.
Notable features
  • Roster pre‑approval feature added via new `approved` column in `rosterusers`
Full changelog

Release notes copied from the original ejabberd 26.03 announcement post:

We are pleased to announce another bugfix release: ejabberd 26.03. This brings support for roster pre-approval, and more than 100 commits with bugfixes all around, many of them dedicated to the new mod_invites, including also many security fixes.

If you are upgrading from a previous version, there is a change in the SQL schemas, please read below. There are no changes in configuration, API commands or hooks.

Contents:

Changes in SQL schema

This release adds a new column to the rosterusers table in the SQL database schemas to support roster pre-approval. This task is performed automatically by ejabberd by default.

However, if your configuration file has disabled update_sql_schema toplevel option, you must perform the SQL schema update manually yourself. Those instructions are valid for MySQL, PostgreSQL and SQLite, both default and new schemas:

ALTER TABLE rosterusers ADD COLUMN approved boolean NOT NULL AFTER subscription;

SASL channel binding changes

This version adds ability to configure handling of client flag "wanted to use channel-bindings but was not offered one".
By default ejabberd will abort connections that present this flag, as that could mean that between server and client is
rogue MITM proxy that strips exchanged data with informations that are required for this.

This can cause problems for servers that use proxy server that terminated TLS connection (there is MITM proxy, but approved by server admin). To be able to handle this situation, we added code that ignore this flag, if server admin disable channel-binding handling by disabling -PLUS auth mechanisms in config file:

disable_sasl_mechanisms:
  - SCRAM-SHA-1-PLUS
  - SCRAM-SHA-256-PLUS
  - SCRAM-SHA-512-PLUS

We also ignore this flag for SASL2 connections if offered authentication methods filtered by available user passwords did disable all -PLUS mechanisms.

ChangeLog

Core

  • Fix mysql authentication for tls connections that required auth plugin switch
  • Improve handling of scram "wanted to use channel-bindings but was not offered one" flag
  • Add ability for mod_options values to depend on other options
  • Don't fail to classify stand-alone chat states
  • Fix some warnings compiling with Erlang/OTP 29 (#4527)
  • ejabberd_ctl: Document how to set empty lists in ejabberdctl and WebAdmin
  • ejabberd_http: Add handling of Etag and If-Modified-Since headers to files served by mod_http_upload
  • ejabberd_http: Ignore whitespaces at end of host header
  • SQL: Add ability to mark that column can be null in e_sql_schema
  • Tests: Add tests for sasl2
  • Tests: Make table cleanup in test more robust

Modules

  • mod_fast_auth: Offered methods are based on available channel bindings
  • mod_http_api: Always hide password in log entries
  • mod_mam: Call store_mam_message hook for messages that user_mucsub_from_muc_archive was filtering out
  • mod_mam_sql: Only provide the new XEP-0431 fulltext field, not old custom withtext
  • mod_muc_room: Fix duplicate stanza-id in muc mam responses generated from local history (#4544)
  • mod_muc_room: Fix hook name in commit 7732984 (#4526)
  • mod_pubsub_serverinfo: Don't use gen_server:call for resolving pubsub host
  • mod_roster: Add support for roster pre-approval (#4512)
  • mod_roster: Fix display of groups in WebAdmin when it's a list
  • mod_roster: in WebAdmin page, first execute SET actions, later GET
  • mod_roster_mnesia: Improve transformation code

mod_invites

  • Makefile: Run invites-deps only when files are missing
  • Fix path to bootstrap files
  • Check at start time the syntax of landing_page option (#4525)
  • Send 'Link' http header (#4531)
  • Set meta.pre-auth to skip redirect_url if token validated (#4535)
  • Many security fixes (#4539)
  • Add favicon and change color to match ejabberd branding
  • Enable dark mode
  • Add support for webchat_url
  • Migrate to bootstrap5 and update jquery
  • No inline scripts
  • Make format csrf token
  • Add csrf token to failed post
  • Include js/css deps in static dir
  • Correct hashes for bootstrap 4.6.2
  • Hint at type for landing_page opt
  • Many more security fixes (#4538)
  • Check CSRF token in register form
  • Add integrity hashes to scripts and css
  • Comment unused resources
  • Add security headers
  • Remove debug log of whole query parameters (including pw)
  • Don't crash on unknown host from http host header
  • Make creating invite transactional
  • Set overuse limits (#4540)
  • Fix broken path when behind proxy with prefix (#4547)

Container and Installers

  • Bump Erlang/OTP 28.4.1
  • make-binaries: Bump libexpat to 2.7.5
  • make-binaries: Bump zlib to 1.3.2
  • make-binaries: Enable missing crypto features (#4542)

Translations

  • Update Bulgarian translation
  • Update Catalan and Spanish translations
  • Update Chinese Simplified translation
  • Update Czech translation
  • Update French translation
  • Update German translation

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following changes:

  • Add p1db backend for mod_auth_fast
  • Fix issue when cleaning MAM messages stored in p1db
  • mod_unread fixes
  • Web push fixes

Full Changelog

https://github.com/processone/ejabberd/compare/26.02...26.03

ejabberd 26.03 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

26.02 Breaking risk
Breaking changes
  • Removes the `mod_muc_occupantid` module; its occupant‑ID handling is now part of `mod_muc`. Configurations referencing `mod_muc_occupantid` must be removed.
Full changelog

Release notes copied from the original ejabberd 26.02 announcement post:

Contents:

ChangeLog

  • Fixes issue with adding hats data in presences send by group chats (#4516)
  • Removes mod_muc_occupantid modules, and integrates its functionality directly into mod_muc (#4521)
  • Fixes issue with reset occupant-id values after restart of ejabberd (#4521)
  • Improves handling of mediated group chat invitations in mod_block_stranger (#4523)
  • Properly install mod_invites templates in make install call (#4514)
  • Better errors in mod_invites (#4515)
  • Accessibility improvements in mod_invites (#4524)
  • Improves handling of request with invalid url encoded values in request handled by ejabberd_http
  • Improves handling of invalid responses to disco queries in mod_pubsub_serverinfo
  • Fixes conversion of MUC room configs from ejabberd older than 21.12
  • Fixes to autologin in WebAdmin

If you are upgrading from a previous version, there are no changes in SQL schemas, configuration, API commands or hooks.

Notice that mod_muc now incorporates the feature from mod_muc_occupantid, and that module has been removed. You can remove mod_muc_occupantid in your configuration file as it is unnecessary now, and ejabberd simply ignores it.

Check also the commit log: https://github.com/processone/ejabberd/compare/26.01...26.02

Acknowledgments

We would like to thank the contributions to the source code and translations provided by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following change:

  • Change default_ram_db from mnesia to p1db when using p1db cluster_backend

ejabberd 26.02 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

26.01 Breaking risk
⚠ Upgrade required
  • If `update_sql_schema` is disabled, manually create the `invite_token` SQL table for mod_invites
  • New `replaced_connection_timeout` toplevel option can be set to mitigate presence‑collision issues
  • mod_http_fileserver now accepts a map of paths in its `docroot` option
Security fixes
  • mod_invites prevents open registrations by requiring invitation tokens, closing abuse vectors
Notable features
  • Database serialization commands (export_db, import_db) for migrating between backends
  • mod_invites supporting roster invites and invite‑based account registration with optional landing page
Full changelog

Release notes copied from the original ejabberd 26.01 announcement post:

We are pleased to announce ejabberd 26.01. This release addresses real operational pain points: export your data from one database backend and import it into another, and let your users invite others without opening the gates to spam.

This release is the result of three months of development, implementing those new features, and fixing bugs.

Release Highlights:

If you are upgrading from a previous version, there are no mandatory changes in SQL schemas, configuration, API commands or hooks. However new mod_invites uses a new table in databases, see below.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

Database Serialization

This feature adds new way for migrating data between database backends by exporting data from one backend to a file and importing that into different backend (or possibly to same backend but on different machine).

Migrating data using this can be executed by first exporting all data with export_db command, changing configuration of ejabberd and switching modules to use new database backend, and then importing previously exported data using import_db command.

This mechanism works by calling those new command from ejabberdctl, for exporting data:

  • ejabberdctl export_db <host name> <path to directory where exported files should be placed>
  • ejabberdctl export_db_abort <host name>
  • ejabberdctl export_db_status <host name>

and for importing:

  • ejabberdctl import_db <host name> <path to directory with exported data>
  • ejabberdctl import_db_abort <host name>
  • ejabberdclt import_db_status <host name>

Exporting and importing work in background after starting them from ejabberdctl (commands executed by ejabberdctl have time limit for how long they can work, with this setup there should be not issue with export or import getting aborted by that), and current progress of background operation can be tracked by calling corresponding *_db_status command. Operation in progress can be also aborted by executing *_db_abort command.

Roster Invites and Invite-based Account Registration

Until now the canonical method to register an account in ejabberd was to let anybody register accounts using In-Band Registration (IBR) (mod_register) or Web Registration (mod_register_web), and then try to limit abuse with access limitations or CAPTCHAs. Often this process got abused, with the result that account registration had to be disabled and rely on manual registration by administrators.

The new mod_invites implements support for invite-based account registration: administrators can generate invitation URLs, and send them to the desired users (by email or whatever). Then the user that receives an invitation can visit this invitation URL to register a new account.

On top of that, mod_invites lets you create Roster Invites: you can send a link to some other person so they can connect to you in a very user-friendly and intuitive way that doesn't require any further interaction. If account creation is allowed, these links will also allow to setup an account in case the recipient doesn't have one yet.

Relevant links:

Quick setup:

  1. If using SQL storage for the modules and have disabled the update_sql_schema toplevel option, then create manually the SQL table, see below.

  2. If you plan to use the landing page included with mod_invites, install JavaScript libraries jQuery version 3.7.1 and Bootstrap version 4.6.2. This example configuration will assume they are installed in /usr/share/javascript. The ejabberd container image already includes those libraries. Some quick examples, in case you need some help:

    • Debian and related:

      apt install libjs-jquery libjs-bootstrap4
      
    • AlpineLinux and other operating systems where you can install npm, for example:

      apk -U add --no-cache nodejs npm ca-certificates
      
      npm init -y \
        && npm install --silent [email protected] [email protected]
      
      mkdir -p /usr/share/javascript/jquery
      mkdir -p /usr/share/javascript/bootstrap4/{css,js}
      cp node_modules/jquery/dist/jquery.min.js /usr/share/javascript/jquery/
      cp node_modules/bootstrap/dist/css/bootstrap.min.css /usr/share/javascript/bootstrap4/css/
      cp node_modules/bootstrap/dist/js/bootstrap.min.js /usr/share/javascript/bootstrap4/js/
      
    • Generic method using the included script:

      tools/dl_invites_page_deps.sh /usr/share/javascript
      
  3. Configure ejabberd to serve the JavaScript libraries in path /share; serve mod_invites in any path of your selection; and enable mod_invites with some basic options. Remember to setup mod_register to allow registering accounts using mod_invites. For example:

    listen:
      - port: 5443
        ip: "::"
        module: ejabberd_http
        tls: true
        request_handlers:
          /invites: mod_invites
          /share: mod_http_fileserver
    
     modules:
      mod_http_fileserver:
        docroot:
          /share: /usr/share/javascript
      mod_invites:
        access_create_account: configure
        landing_page: auto
      mod_register:
        allow_modules:
          - mod_invites
    
  4. There are many ways to generate invitations:

    • Login with an admin account, then you can execute Ad-Hoc Commands like "Invite User" and "Create Account"
    • If mod_adhoc_api is enabled, you can execute equivalent API Commands generate_invite and generate_invite_with_username
    • Run those API Commands from the command-line, for example: ejabberdctl generate_invite localhost
  5. All those methods give you an invitation URL that you can send it to the desired user, and looks like

    https://localhost:5443/invites/Yrw5nuC1Kpxy9ymbRzmVGzWQ
    
  6. The destination user (or yourself) can visit that invitation URL and follow the instructions to register the account and download a compatible client.

If the user has installed already a compatible XMPP client, you don't no need to install JavaScript libraries and setup a landing page. In that case, when generating an invitation you will get only the XMPP URI; when the user opens that URI in a web browser, it will automatically open the XMPP client and the corresponding registration window.

Probably you don't want to expose the port directly, then you need to setup Nginx or Apache to act as a "reverse" proxy and change your landing_page parameter accordingly, for example just https://@HOST@/invites/{{ invite.token }}

Notice that the landing page can be fully translated using the existing ejabberd localization feature.

SQL table for mod_invites

There is a new table invite_token in SQL schemas, used by the new mod_invites. If you want to use this module, there are two methods to update the SQL schema of your existing database:

If using MySQL or PosgreSQL, you can enable the option update_sql_schema and ejabberd will take care to update the SQL schema when needed: add in your ejabberd configuration file the line update_sql_schema: true

Notice that support for MSSQL in mod_invites has not yet been implemented or tested.

If you are using other database, or prefer to update manually the SQL schema:

  • MySQL singlehost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        invitee text NOT NULL DEFAULT (''),
        created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        expires timestamp NOT NULL,
        type character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token(191))
    ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
    CREATE INDEX i_invite_token_username USING BTREE ON invite_token(username(191));
    
  • MySQL multihost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        server_host varchar(191) NOT NULL,
        invitee text NOT NULL DEFAULT '',
        created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        expires timestamp NOT NULL,
        type character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token(191)),
    ) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
    CREATE INDEX i_invite_token_username USING BTREE ON invite_token(username(191));
    
  • PostgreSQL singlehost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        invitee text NOT NULL DEFAULT '',
        created_at timestamp NOT NULL DEFAULT now(),
        expires timestamp NOT NULL,
        "type" character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token)
    );
    CREATE INDEX i_invite_token_username ON invite_token USING btree (username);
    
  • PostgreSQL multihost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        server_host text NOT NULL,
        invitee text NOT NULL DEFAULT '',
        created_at timestamp NOT NULL DEFAULT now(),
        expires timestamp NOT NULL,
        "type" character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token)
    );
    
    CREATE INDEX i_invite_token_username_server_host ON invite_token USING btree (username, server_host);
    
  • SQLite singlehost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        invitee text NOT NULL DEFAULT '',
        created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        expires timestamp NOT NULL,
        type character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token)
    );
    
    CREATE INDEX i_invite_token_username ON invite_token(username);
    
  • SQLite multihost schema:

    CREATE TABLE invite_token (
        token text NOT NULL,
        username text NOT NULL,
        server_host text NOT NULL,
        invitee text NOT NULL DEFAULT '',
        created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        expires timestamp NOT NULL,
        type character(1) NOT NULL,
        account_name text NOT NULL,
        PRIMARY KEY (token)
    );
    
    CREATE INDEX i_invite_token_username_server_host ON invite_token(username, server_host);
    

New replaced_connection_timeout toplevel option

The new replaced_connection_timeout toplevel option enables new session to wait for termination of session that it replaces.

This should mitigate problems where old session presences unavailable sometimes were delivered after new session sent it's presence available.

Improved mod_http_fileserver docroot option

mod_http_fileserver is a module to serve files from the local disk over HTTP, useful if you just want to serve some HTML or binary files that don't need PHP, and don't need to setup or configure a separate full-blown web server.

Now the docroot option may be a map of paths to serve, allowing this module to serve several paths with different directories for different purposes.

For example, let's serve some public content from /var/service/www, also shared JavaScript libraries, and for base URL let's serve from /var/www:

listen:
  -
    port: 5280
    module: ejabberd_http
    request_handlers:
      /pub/content: mod_http_fileserver
      /share: mod_http_fileserver
      /: mod_http_fileserver
modules:
  mod_http_fileserver:
    docroot:
      /pub/content: /var/service/www
      /share: /usr/share/javascript
      /: /var/www

Notice that ejabberd includes many modules that serve web services, that may be useful to save you from setting up a full-blown web server, see ejabberd_http.

Supported XEP versions

ejabberd supports close to 90 XMPP extension protocols (XEPs), either directly implemented in ejabberd source code, in the libraries that implement many of the internal features, or in other ejabberd modules available in other repositories like ejabberd-contrib.

Those XEPs are updated regularly to bring major improvements, minor changes, fixing typos, editorial or cosmetic changes... and this requires a regular review of those XEP updates in the software implementations to keep them up to date, or at least to document what exact version of the protocols are implemented.

In this sense, we have reviewed all the XEP versions that ejabberd and erlang xmpp library were not up-to-date, and have identified which ones are already up-to-date in their DOAP files. Now the pages at XMPP.org describe more accurately the supported protocol versions, see ejabberd at XMPP.org and erlang-xmpp at XMPP.org.

Erlang, Elixir and Container

ejabberd can be compiled with Erlang/OTP from 25.0 up to the latest 28.3.1. Regarding Elixir support, ejabberd supports from Elixir 1.14.0 up to the latest 1.19.5

Right now ejabberd compiles correctly with Erlang/OTP from git development branch and Elixir 1.20.0-RC1, so hopefully compatibility with the upcoming Erlang/OTP 29 and Elixir 1.20 will be easily achievable.

Binary installers and the ejabberd container now include Erlang/OTP 28.3.1 instead of 27.3, and Elixir 1.19.5 instead of 1.18.4.

Speaking of the container images, both ejabberd and ecs bring other minor changes: they expose more ports: 5478 UDP (STUN service), 7777 (SOCKS5 file transfer proxy) and 50000-50099 UDP (TURN service).
The container images in their ejabberd.yml file use new macros PORT_TURN_MIN, PORT_TURN_MAX, and STARTTLS_REQUIRED that you can setup easily without modifying ejabberd.yml, see macros in environment.

Improved ERL_DIST_PORT

ejabberd uses Erlang Distribution in the ejabberdctl shell script and also for building a cluster of ejabberd nodes.

That Erlang Distribution has historically used the epmd program to assign listening ports and discover ports of other nodes to connect. The problems of using epmd are that:

  • epmd must be running all the time in order to resolve name queries
  • epmd listens in port 4369
  • the ejabberd node listens in a random port number

How to avoid epmd since Erlang/OTP 23.1 and ejabberd 22.10 ? Simply set the ERL_DIST_PORT environment variable in the ejabberdctl.cfg file:

ERL_DIST_PORT=5210

Since now, ejabberdctl passes arguments to Erlang to listen for erlang distribution connections in TCP port 5210, and establish erlang distribution connections to remote ports 5210. That way you know exactly, in advance, what port number to open in the firewall or container.

This ejabberd release introduces some small improvements that facilitate using the ERL_DIST_PORT environment variable:

  • ejabberdctl prints an informative message when it detects that there may be a port number collision, which may happen if you start several ejabberd nodes in the same machine listening in the same ERL_DIST_PORT and same INET_DIST_INTERFACE.

  • When ejabberd is starting, now it prints the address and port number where it listens for erlang distribution:

    [info] ejabberd 26.01 is started in the node ejabberd@localhost in 1.90s
    [info] Elixir 1.19.4 (compiled with Erlang/OTP 28)
    [info] Erlang/OTP 29 [DEVELOPMENT] [erts-16.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
    
    [info] Start accepting TCP connections at 0.0.0.0:5210 for erlang distribution
    [info] Start accepting TCP connections at [::]:5222 for ejabberd_c2s
    [info] Start accepting TCP connections at [::]:5269 for ejabberd_s2s_in
    ...
    
  • A new make relivectl is introduced, which uses ejabberdctl script to start ejabberd (not like make relive), and starts ejabberd immediately without building a release (not like make dev).

  • The ejabberd Documentation site has improved and updated pages about Security, Erlang Distribution, and Clustering.

New make relivectl

make relive was introduced in ejabberd 22.05. It allows to start ejabberd in path _build/relive/ without installing it, by using rebar3 shell and mix run. It automatically compiles code at start and recompiles changed code at runtime. But it doesn't use the ejabberdctl script, and doesn't read ejabberdctl.cfg, this means that depending on what you are testing, it may not be useful and you had to switch to make dev.

A new make target is now introduced: make relivectl. This is similar, as it starts ejabberd without requiring installation, using path _build/relivectl/ to store the configuration, database and log files. The benefit over relive is that relivectl uses ejabberdctl and reads ejabberdctl.cfg. The drawback is that it doesn't recompile code automatically. The benefit over make dev is that relivectl doesn't build an OTP release, so it's faster to start.

Let's summarize all the make targets related to installation to determine their usage differences:

| make ... | install | install-rel | prod | dev | relivectl | relive |
|:---------------------|:-----------:|:---------------:|:--------:|:-------:|:-------------:|:----------:|
| Writes files in path | / | / | _build/
prod/|_build/
dev/| _build/
relivectl/ | _build/
relive/ |
| Installs | ✅ | ✅ | manually uncompress *.tar.gz| - | - | - |
| Uninstall with | uninstall
⚠️ incomplete| uninstall-rel
✅| manual remove | - | - | - |
| Start tool | ejabberdctl |ejabberdctl|ejabberdctl|ejabberdctl|ejabberdctl | rebar3/mix |
| Reads ejabberdctl.cfg| ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Recompiles | - | ✅ | ✅ | ✅ | ❌ | ✅ |
| Starts ejabberd | - | - | - | - | ✅ | ✅ |
| Recompiles at runtime| - | - | - | - | ❌ | ✅ |
| Execution time (s.) | 13 | 40 | 57 | 35 | 4 | 9 |

As seen in the table, make install / uninstall seem unnecessary nowadays, because install-rel / uninstall-rel allow to install and uninstall correctly all the files. Maybe in the future the implementation of make install / uninstall could get replaced with make install-rel / uninstall-rel...

In the same sense, make dev now apparently falls short between make prod (which is absolutely indispensable to build a full OTP release) and make relive/relivectl (useful, featureful, and fast for development and testing purposes).

WebAdmin Menu Links

Do you remember that ejabberd 25.07 introduced a link in WebAdmin to the local Converse.js page in the left menu when the corresponding mod_conversejs is enabled?

Technically speaking, until now the WebAdmin menu included a link to the first request_handler with mod_conversejs that the admin configured in ejabberd.yml. That link included the authentication credentials hashed as URI arguments if using HTTPS. Then process/2 extracted those arguments and passed them as autologin options to Converse.

From now, mod_conversejs automatically adds a request_handler nested in WebAdmin subpath. The WebAdmin menu links to that converse URI; this allows to access the HTTP auth credentials, no need to explicitly pass them. process/2 extracts this HTTP auth and passes autologin options to Converse. Now scram password storage is supported too.

In practice, what does all that mean? Just enable the mod_conversejs module, and WebAdmin will have a private Converse URL for the admin, linked in the WebAdmin menu, with autologin. No need to setup a public request_handler!

For example, let's configure conversejs only for admin usage:

listen:
  -
    port: 5443
    module: ejabberd_http
    tls: true
    request_handlers:
      /admin: ejabberd_web_admin
      /ws: ejabberd_http_ws

modules:
  mod_conversejs:
    conversejs_resources: "/home/conversejs/12.0.0/dist"

Of course, you can setup a public request_handler and tell your users to access the corresponding URL:

listen:
  -
    port: 5443
    module: ejabberd_http
    tls: true
    request_handlers:
      /admin: ejabberd_web_admin
      /public/web-client: mod_conversejs
      /ws: ejabberd_http_ws

modules:
  mod_conversejs:
    conversejs_resources: "/home/conversejs/12.0.0/dist"

With that configuration, what is the corresponding URL?

Login to the WebAdmin and look at the left menu: now it displays links to all the configured HTTP services: ejabberd_captcha, ejabberd_oauth, mod_conversejs, mod_http_fileserver, mod_register_web. Also mod_muc_log_http and mod_webpresence from ejabberd-contrib show links in the WebAdmin left menu. Additionally, the menu shows a lock if the page is encrypted HTTPS, and an ! if it is not.

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following changes:

  • New module mod_push_gate that can act as target service for mod_push, and which can deliver pushes using configured mod_gcm or mod_applepush instances.
  • New module mod_push_templates that can be used to have different push notifications for message class matching configured data patterns.
  • New database conversion routines targeting p1db backends

ChangeLog

This is a more complete list of changes in this ejabberd release:

Compile and Start

  • Remove dependencies, macros and code for Erlang/OTP older than 25
  • Require Elixir 1.14 or higher, that's the lowest we can test automatically
  • ejabberdctl: Support NetBSD and OpenBSD su (#4320)
  • ejabberdctl.template: Show meaningful error when ERL_DIST_PORT is in use
  • ejabberd_app: Print address and port where listens for erlang node connections
  • Makefile.in: Add make relivectl similar to relive but using ejabberdctl

Databases

  • Add db_serialize support in mnesia modules
  • Add db serialization to mod_muc_sql
  • New database export/import infrastructure
  • Add commands for new database export/import
  • Apply timestamp pass in ?SQL_INSERT queries
  • Update p1_mysql to bring fix for timestamp decoding
  • Extend timestamp type handling in sql macros
  • Revert changes to conversion of pgsql int types

Installer and Container

  • make-binaries: Bump Erlang/OTP 28.3.1 and Elixir 1.19.5
  • Dockerfile: Bump Erlang/OTP 28.3.1 and Elixir 1.19.5
  • Dockerfile: Expose also port 7777 for SOCKS5
  • Dockerfile: Configure TURN ports and expose 5478 50000-50099
  • Dockerfile: Try to fix error with recent freetds Alpine package
  • Container: Setup new macro STARTTLS_REQUIRED to allow easy disabling

MUC

  • Add muc_online_rooms_count API command
  • Set enable_hats room option true by default
  • Allow vcard queries even when IQ queries are disabled (#4489)
  • Announce stable-id feature from XEP-0045 1.31, supported since long ago
  • Fix preload_rooms in case of SQL database (#4476)
  • Run new hooks: registering_nickmuc and registered_nickmuc (#4478)
  • When deleting account, unregister account's nicks in all MUC hosts (#4478)
  • mod_muc_log: Crash in terminate/2 when stopping module (#4486)
  • mod_muc_occupantid: Keep salt per MUC service, not individual rooms
  • mod_muc_room: Rewrite hats code that gets xdata values
  • mod_muc_room: Handle hats without definition (#4503)
  • mod_muc_room: When user has no hats, don't store in hats_users

WebAdmin

  • ejabberd_http: Run new http_request_handlers_init fold hook
  • ejabberd_http: Add helper get_auto_urls/2 that returns all URLs and TLS
  • ejabberd_web_admin: Add helper functions make_menu_system
  • ejabberd_web_admin: Show menu system only when can view vhosts
  • ejabberd_web_admin: Pass Level in webadmin_menu_system_post and inside hooks
  • mod_conversejs: Improve link to conversejs in WebAdmin (#4495)
  • When epmd isn't running show explanation in Clustering WebAdmin page
  • Use improved WebAdmin menu system in more modules
  • When building WebAdmin menu system, {URLPATH} in link text is substituted

Web Services

  • rest: Use separate httpc profile
  • ejabberd_captcha: Use mod_host_meta:get_auto_url/2
  • ejabberd_http: Support repeated module in request_handlers
  • ejabberd_http: Get back handling when BOSH or WS are disabled
  • mod_host_meta: Move get_url functions from mod_host_meta to ejabberd_http
  • mod_host_meta: Allow calling get_url/2 for other modules, not only WebSocket
  • mod_host_meta: Cosmetic rename Module to Handler
  • mod_http_upload: New content_type option similar to mod_http_fileserver (#4488)
  • mod_http_upload: Pass ServerHost, not Host which may be "upload.HOST"
  • mod_http_upload: Amend the fix for #4450 to support IDNA correctly (#3519)
  • mod_http_fileserver: Support map of paths in docroot option
  • mod_conversejs: Add new Conversejs Paths and ContentTypes (#4511)
  • mod_conversejs: Use ContentType functions from mod_http_fileserver (#4511)
  • Use /websocket URL in default configuration like mod_conversejs, it's more meaningful

Core and Modules

  • Add replaced_connection_timeout toplevel option
  • Fix nasty SSL warnings (#4475)
  • ejabberd_commands: Show meaningul error message when problem executing command (#4506)
  • ejabberd_logger: Append "color clean" only in console template, not file
  • ejabberd_oauth: Log error if oauth_list_tokens executed with unsupported DB (#4506)
  • misc: Get back functions and mark them as deprecated
  • mod_adhoc_api: Show nice command name, as WebAdmin already does
  • mod_pubsub: Deliver pubsub notifications to remote servers for nodes with presence based delivery
  • mod_scram_update: Don't hard-code iteration count
  • Bump many XEPs versions that are already supported
  • Improve documentation of install_contrib_modules (#4487)

Full Changelog

https://github.com/processone/ejabberd/compare/25.10...26.01

ejabberd 26.01 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

25.10 Breaking risk
⚠ Upgrade required
  • Update Erlang/OTP runtime to at least version 25.0 before upgrading.
  • When configuring ejabberd, replace `new_sql_schema: true` with `sql_schema_multihost: true` and use the new term names (`Multihost`, `Singlehost`).
Breaking changes
  • Removed support for Erlang/OTP older than version 25.0.
  • Renamed SQL schema terms: `New` → `Multihost`, `Default` → `Singlehost`.
Notable features
  • Added `archive_muc_as_mucsub` option in `mod_mam` to archive MUC messages as mucsub events.
  • Updated XEP‑0317 Hats support from version 0.2.0 to the latest 0.3.1.
Full changelog

Release notes copied from the original ejabberd 25.10 announcement post:

Release Highlights:

If you are upgrading from a previous version, there are no mandatory changes in SQL schemas, configuration, API commands or hooks.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

New option archive_muc_as_mucsub in mod_mam

When this option is enabled incoming groupchat messages for users that have MucSub subscription to a room from which message originated will have those messages archived after being converted to mucsub event messages.

Removed support for Erlang/OTP older than 25.0

The ejabberd 24.12 release announcement explained that support for Erlang/OTP older than 25.0 was discouraged, it would be deprecated in future releases, and completely removed sometime after ejabberd 25.01. That explanation was mentioned several times in the subsequent ejabberd releases.

The initial reason to require Erlang/OTP 25 was that this version is the lowest we can easily use nowadays for running the CI tests.

Other reasons to remove support for Erlang lower than 25 are: to support maybe expression, and to remove duplicate code.

In order to support both new and very old Erlang/OTP versions, ejabberd source code included many duplicate code. All that duplicate code that is nowadays useless will be removed in a future ejabberd release.

Support for the new Erlang 'maybe' expression

The new maybe expression is supported since Erlang/OTP 25 (requires being enabled), and it is enabled by default since 27.

Now that ejabberd requires Erlang/OTP 25, and it enables the maybe expression, this can be used freely in ejabberd source code and modules.

See:

Rename 'New' SQL schema to 'Multihost', and 'Default' to 'Singlehost'

When ejabberd first got support for SQL storage, it only supported one vhost, so it made sense to not store the host in the SQL tables. Additionally, the SQL schema in ejabberd followed that of jabberd14, which didn't support multiple vhosts either.

When ejabberd got support for multiple vhosts, if several of them want to use SQL storage, the solution is to configure a different SQL database for each vhost using the host_config toplevel option.

However, when there are many vhosts configured in ejabberd, all of them using SQL storage, it is preferable to setup one single SQL database, and store the vhost in the tables. When that feature was added to ejabberd, it got the name of "new SQL schema". And the previous SQL schema was called "legacy", "old", and nowadays "default".

The problem with the terms "default" and "new" is that they are circumstantial, and do not really describe the schema features or purposes.

Now those terms have been renamed:

  • "default SQL schema" ⟹ "singlehost SQL schema"
  • "new SQL schema" ⟹ "multihost SQL schema"

Right now all names are supported, the previous (obsolete) and the renamed (preferred). No changes are needed in your existing configuration file or building instructions, but it is preferable if you can update your setup to the new terms:

When preparing configuration, the old and new arguments are:

./configure --enable-new-sql-schema
./configure --enable-multihost-sql-schema

When configuring ejabberd, the old and new toplevel options are:

new_sql_schema: true
sql_schema_multihost: true

When developing source code, the old and new functions are:

ejabberd_sql:use_new_schema()
ejabberd_sql:use_multihost_schema()

New API Commands

Several ejabberd modules implement new API Commands, most of them inspired by XEP-0133:

Added more Ad-Hoc Commands from XEP-0133

XEP-0133 describes 31 administrative tasks that should be available as ad-hoc commands.

ejabberd already implemented many of those ad-hoc commands in mod_configure, but there were a few missing that nowadays are fairly easy to implement: this new ejabberd release supports all of them... except 5.

The five ad-hoc commands from XEP-0133 that are not supported are:

  • 6. Get User Password, because it was already retracted in the XEP and should not be implemented
  • 12. Edit Whitelist, because the corresponding feature is not implemented in ejabberd
  • 27. Set Welcome Message, because in ejabberd this message is set in the configuration file, option welcome_message of mod_register
  • 28. Delete Welcome Message, for similar reason
  • 29. Edit Admin List, because in ejabberd the administrative rights to accounts are granted in the configuration file, toplevel option acl.

On the other hand, ejabberd implements more than 200 API commands in all over its source code, providing those and many other administrative tasks. And you can execute those API commands using the command line, ReST calls, XML-RPC, WebAdmin, ... and ad-hoc commands too!!! See the available API frontends.

Nowadays, all the ad-hoc commands described in XEP-0133 have a similar API command in ejabberd that you can execute using ad-hoc commands too:

| Ad-hoc command in XEP-0133 | Status in ejabberd 25.10 | Equivalent API command |
| :--- | :--- | :--- |
Add User | 〽️ (no vCard arguments) | register
Delete User | ✅ | unregister
Disable User | ✅ | ban_account
Re-Enable User | ✅ | unban_account
End User Session | 〽️ (argument) | kick_session
Get User Password (retracted) | ▶️ (retracted) | check_password
Change User Password | ✅ | change_password
Get User Roster | 〽️ (result syntax) | get_roster
Get User Last Login Time | ✅ | get_last
Get User Statistics | ✅ | user_sessions_info
Edit Blacklist | ▶️ | add_blocked_domain
Edit Whitelist | ❌ | -
Get Number of Registered Users | ✅ | stats
Get Number of Disabled Users | ✅ | count_banned
Get Number of Online Users | ✅ | stats
Get Number of Active Users | ✅ | status_num
Get Number of Idle Users | ✅ | status_num
Get List of Registered Users | ✅ | registered_users
Get List of Disabled Users | ✅ | list_banned
Get List of Online Users | ✅ | connected_users
Get List of Active Users | ✅ | status_list
Get List of Idle Users | ✅ | status_list
Send Announcement to Online Users | ✅ | announce_send_online
Set Message of the Day | ✅ | announce_motd_set_online
Edit Message of the Day | ✅ | announce_motd_update
Delete Message of the Day | ✅ | announce_motd_delete
Set Welcome Message | ▶️ | (option welcome_message in mod_register)
Delete Welcome Message | ▶️ | (option welcome_message in mod_register)
Edit Admin List | ▶️ | (option acl)
Restart Service | ✅ | restart_kindly
Shut Down Service | ✅ | stop_kindly

Status legend:

  • ✅ Implemented in ejabberd exactly as XEP-0133 describes it
  • 〽️ Implemented with same command name, but different arguments or results
  • ▶️ Not implemented as XEP-0133 says, but we have an alternative solution
  • ❌ Not implemented in ejabberd in any way

Updated support for XEP-0317 Hats

Support for XEP-0317 Hats is improved from 0.2.0 to the latest 0.3.1.

Previously, the XEP lacked some use cases, and ejabberd implemented them as custom additional features, as documented in MUC Hats. Now that the XEP includes all those additions, ejabberd strictly follows XEP-0317 version 0.3.1.

Improved GitHub Workflows

The ejabberd git repository contains several GitHub Workflows to test automatically the source code with static and dynamic tools, build installers and containers.

Those workflows recently got several improvements:

  • Run agnostic-database tests only once, not for every backend
  • Add local composite actions to manage ejabberd and databases
  • Reorganize steps in the CI workflow to run in parallel jobs
  • Use ARM runners to build ARM installers and containers, no need for cross compiling
  • Use ARM runners instead of x86 when possible, as they run faster
  • Cache dependencies and download from CDNs when possible

With all those improvements, the workflows complete (or give some error report) in less than 10 minutes, instead of the 30 minutes that were common before.

For details about those changes, check PR 4460

Acknowledgments

We would like to thank the contributions to the source code provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following changes:

  • The bulk_roster_update API command now accept a list of groups.
  • The mod_dedup module has been improved to handle received markers. This module was added in 4.2508 to prevent both delivery and storage of duplicates in archive.
  • Fixed a case where a mobile client was not able to retrieve all the messages received while it was offline after a temporarily loses of its data connection.

ChangeLog

This is a more complete list of changes in this ejabberd release:

Ad-hoc Commands

  • mod_configure: New ad-hoc commands that were missing from XEP-0133
  • mod_adhoc_api: Add support for asynchronous command calling
  • mod_adhoc_api: If argument is a list of jids, type is jid-multi
  • mod_adhoc_api: If field has several values, type is text-multi

API Commands

  • Add commands argument type binary_or_list
  • mod_http_api: Format sub elements for tuples from maps
  • mod_admin_extra: Improve roster API commands documentation
  • mod_announce: New API commands, reusing existing ad-hoc functions
  • ejabberd_admin: New API command restart_kindly, improve stop_kindly
  • mod_admin_extra: New API commands list_banned and count_banned
  • mod_admin_extra: Improve API command status_list: support for status to be a list
  • mod_muc_admin: New API commands muc_get_registered_nick and nicks (#4468)
  • Use mod_private:del_data in unban_account API command

Configuration

  • Rename New SQL schema to Multihost, and Default to Singlehost (#4456)
  • Add config transformer from use_new_schema -> sql_multihost_schema
  • mod_sip: Fix problem parsing via in yconf library (#4444)

Erlang/OTP support

  • Enable feature maybe_expr in the compiler for Erlang/OTP 26 (#4459)
  • Enable feature maybe_expr also in the runtime for Erlang/OTP 25
  • Runtime: Remove Erlang 24 which won't work anymore with maybe_expr
  • Remove EX_RULE and EX_STACK macros only used with ancient erlang

GitHub Workflows

  • CI: Bump XMPP-Interop-Testing/xmpp-interop-tests-action (#4469)
  • CI: Don't care to include commit details in the CT logs HTML page
  • CI and Runtime: Reorganize steps to run in parallel, and ARM runner (#4460)
  • Add local composite actions to manage ejabberd and databases
  • Container: Build ARM in native runner instead of QEMU, merge and clean
  • Installers: Generate ARM installers in native runner
  • Tests: Run agnostic-database tests only once, not for every backend
  • Tests: The odbc backend is not actually used in Commont Tests
  • Weekly: New workflow that condenses CI, test all erlang without caching

Installers and Containers

  • Bump Erlang/OTP version to 27.3.4.3 in installers and container
  • Bump Expat 2.7.3, OpenSSL 3.5.4, unixODBC 2.3.14 in installers

MUC

  • mod_mam: New option archive_muc_as_mucsub
  • mod_muc: Check if room is hibernated before calling mod_muc process
  • mod_muc: Update implementation of XEP-0317 Hats to version 0.3.1 (#4380)
  • mod_muc: Make mod_muc_sql properly handle new hats data (#4380)
  • mod_muc_room: Don't require password if user is owner of room
  • mod_muc_admin: Use in WebAdmin the new API commands that get nick registers

Core and Modules

  • ejabberd_http_ws: Pass HTTP headers from WS to C2S connection (#4471)
  • ejabberd_listener: Properly pass send_timeout option to listener sockets
  • ejabberdctl: When ping returns pang, return also status code 1 (#4327)
  • ext_mod: Print module status message after installation
  • misc: json_encode should always call json with our filter
  • mod_admin_update_sql: Use same index name than when creating database
  • mod_block_strangers: Clarify access and captcha documentation (#4221)
  • mod_http_upload: Encode URL before parsing, as done before bba1a1e3c (#4450)
  • mod_private: Add del_data/3, get_users_with_data/2, count_users_with_data/2
  • mod_pubsub: Don't catch exit:{aborted, _} inside mnesia transactions
  • mod_push: Run new hook push_send_notification (#4383)
  • WebAdmin: Respect newline and whitespace characters in results

Full Changelog

https://github.com/processone/ejabberd/compare/25.08...25.10

ejabberd 25.10 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

25.08 Security relevant
⚠ Upgrade required
  • ACME issues with Erlang/OTP 28.0.1 are resolved; use OTP 28.0.2 or stay on OTP 27.3 in production.
  • Minimum supported Erlang/OTP version raised to 24.
  • Erlang node name can be changed using the new `ejabberdctl mnesia_change` command.
Security fixes
  • Matrix gateway support for Hydra rooms fixes high‑severity protocol vulnerabilities (pre‑disclosure) affecting state resolution.
Notable features
  • Support for Hydra rooms (Matrix room version 12) in mod_matrix_gw
  • New `mod_providers` module to serve XMPP Providers files automatically
  • Option `conversejs_plugins` added to mod_conversejs for enabling OMEMO
Full changelog

Release notes copied from the original ejabberd 25.08 announcement post:

Release Highlights:

This release includes the support for Hydra rooms in our Matrix gateway, which fixes high severity protocol vulnerabilities.

If you are upgrading from a previous version, there are no changes in SQL schemas, configuration, API commands or hooks.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

Improvements in Matrix gateway

The ejabberd Matrix gateway now supports Hydra rooms (Matrix room version 12). This fix some high severity protocol vulnerabilities. The state resolution has been partially rewritten in our gateway.

A double colon is used for separating a matrix server from a room ID in JID with Hydra rooms.

Other changes to the matrix gateway:

  • The new option notary_servers of mod_matrix_gw can now be used to set a list of notary servers.
  • Add leave_timeout option to mod_matrix_gw (#4386)
  • Don't send empty direct Matrix messages (thanks to snoopcatt) (#4420)

Fixed ACME in Erlang/OTP 28.0.2

The ejabberd 25.07 release notes mentioned that Erlang/OTP 28.0.1 was not yet fully supported because there was a problem with ACME support.

Good news! this problem with ACME is fixed and tested to work when using Erlang/OTP 28.0.2, the latest p1_acme library, and ejabberd 25.08.

If you are playing with ejabberd and Erlang/OTP 28, please report any problem you find. If you are running ejabberd in production, better stick with Erlang/OTP 27.3, this is the one used in installers and container images.

New mod_providers to serve XMPP Providers file

mod_providers is a new module to serve easily XMPP Providers files.

The standard way to perform this task is to first generate the Provider File, store in the disk with the proper name, and then serve the file using an HTTP server or mod_http_fileserver. And repeat this for each vhost.

Now this can be replaced with mod_providers, which automatically sets some values according to your configuration. Try configuring ejabberd like:

listen:
  -
    port: 443
    module: ejabberd_http
    tls: true
    request_handlers:
      /.well-known/xmpp-provider-v2.json: mod_providers

modules:
  mod_providers: {}

Check the URL https://localhost:443/.well-known/xmpp-provider-v2.json, and finetune it by setting a few mod_providers options.

Improved Unicode support in configuration

When using non-latin characters in a vhost served by ejabberd, you can write it in the configuration file as unicode, or using the IDNA/punycode. For example:

hosts:
  - localhost1
  - locälhost2
  - xn--loclhost4-x2a
  - 日本語

host_config:
  "locälhost2":
    modules:
      mod_disco: {}
      mod_muc:
        host: "conference3.@HOST@"
  "xn--loclhost4-x2a":
    modules:
      mod_disco: {}
      mod_muc:
        host: "conference4.@HOST@"

This raises a problem in mod_http_upload if the option put_url contains the @HOST@ keyword. In that case, please use the new predefined keyword HOST_URL_ENCODE.

This change was also applied to ejabberd.yml.example.

New option conversejs_plugins to enable OMEMO

mod_conversejs gets a new option conversejs_plugins that points to additional local files to include as scripts in the homepage.

Right now this is useful to enable OMEMO encryption.

Please make sure those files are available in the path specified in conversejs_resources option, in subdirectory plugins/. For example, copy a file to path /home/ejabberd/conversejs-x.y.z/package/dist/plugins/libsignal-protocol.min.js and then configure like:

modules:
  mod_conversejs:
    conversejs_resources: "/home/ejabberd/conversejs-x.y.z/package/dist"
    conversejs_plugins: ["libsignal-protocol.min.js"]

If you are using the public Converse client, then you can set "libsignal", which gets replaced with the URL of the public library. For example:

modules:
  mod_conversejs:
    conversejs_plugins: ["libsignal"]
    websocket_url: "ws://@HOST@:5280/websocket"

Easier erlang node name change with mnesia_change

ejabberd uses by default the distributed Mnesia database. Being distributed, Mnesia enforces consistency of its file, so it stores the Erlang node name, which may include the hostname of the computer.

When the erlang node name changes (which may happen when changing the computer name, or moving ejabberd to another computer), then mnesia refused to start with an error message like this:

2025-08-21 11:06:31.831594+02:00 [critical]
  Erlang node name mismatch:
  I'm running in node [ejabberd2@localhost],
  but the mnesia database is owned by [ejabberd@localhost]
2025-08-21 11:06:31.831782+02:00 [critical]
  Either set ERLANG_NODE in ejabberdctl.cfg
  or change node name in Mnesia

To change the computer hostname in the mnesia database, it was required to follow a tutorial with 10 steps that starts ejabberd a pair of times and runs the mnesia_change_nodename API command.

Well, now all this tutorial is implemented in one single command for the ejabberdctl command line script. When mnesia refuses to start due to an erlang node name change, it mentions that new solution:

$ echo "ERLANG_NODE=ejabberd2@localhost" >>_build/relive/conf/ejabberdctl.cfg

$ ejabberdctl live
2025-08-21 11:06:31.831594+02:00 [critical]
  Erlang node name mismatch:
  I'm running in node [ejabberd2@localhost],
  but the mnesia database is owned by [ejabberd@localhost]
2025-08-21 11:06:31.831782+02:00 [critical]
  Either set ERLANG_NODE in ejabberdctl.cfg
  or change node name in Mnesia by running:
  ejabberdctl mnesia_change ejabberd@localhost

Let's use the new command to change the erlang node name stored in the mnesia database:

$ ejabberdctl mnesia_change ejabberd@localhost

==> This changes your mnesia database from node name 'ejabberd@localhost' to 'ejabberd2@localhost'

...

==> Finished, now you can start ejabberd normally

Great! Now ejabberd can start correctly:

$ ejabberdctl live
...
2025-08-21 11:18:52.154718+02:00 [info]
  ejabberd 25.07.51 is started in the node ejabberd2@localhost in 1.77s

Notice that the command mnesia_change must start and stop ejabberd a pair of times. For that reason, it cannot be implemented as an API command. Instead, it is implemented as an ejabberdctl command directly in the ejabberdctl command line script.

Colorized interactive log

When ejabberd starts with an erlang shell using Mix, it prints error lines in a remarkable color: orange for warnings and red for errors. This helps to detect those lines when reading the log interactively.

Now this is also supported when using Rebar3. To test it, start ejabberd either:

  • ejabberdctl live: to start interactive mode with erlang shell
  • ejabberdctl foreground: to start in server mode with attached log output

You will see log lines colorized with:

  • green+white for informative log messages
  • grey for debug
  • yellow for warnings
  • red for errors
  • magenta for messages coming from other Erlang libraries (xmpp, OTP library), not ejabberd itself

Document API Tags in modules

Many ejabberd modules implement their own API commands, and now the documentation of those modules mention which tags contain their commands.

See for example at the end of modules mod_muc_admin, mod_private or mod_antispam.

Unfortunately, many early API commands were implemented in mod_admin_extra, which includes commands related to account management, vcard, roster, private, ... and consequently those are not mentioned in their corresponding modules documentation.

Acknowledgments

We would like to thank the contributions to the source code provided for this release by:

  • mod_matrix_gw: Don't send empty direct Matrix messages (thanks to snoopcatt) (#4420)
  • Holger Weiß for improvements in the installers, HTTP file upload and mod_register
  • marc0s for the improvement in MUC

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following changes:

New module mod_dedup

This module removes duplicates of read receipts sent by concurrent sessions of single user, this will prevent both delivery and storage in archive of duplicates.

Limits in mod_unread queries

Queries issued to mod_unread can now declare maximum number and age of returned results. This can also be tweaked with new options of that module.

ChangeLog

This is a more complete list of changes in this ejabberd release:

API Commands

  • ban_account: Run sm_kick_user event when kicking account (#4415)
  • ban_account: No need to change password (#4415)
  • mnesia_change: New command in ejabberdctl script that helps changing the mnesia node name

Configuration

  • Rename auth_password_types_hidden_in_scram1 option to auth_password_types_hidden_in_sasl1
  • econf: If a host in configuration is encoded IDNA, decode it (#3519)
  • ejabberd_config: New predefined keyword HOST_URL_ENCODE
  • ejabberd.yml.example: Use HOST_URL_ENCODE to handle case when vhost is non-latin1
  • mod_conversejs: Add option conversejs_plugins (#4413)
  • mod_matrix_gw: Add leave_timeout option (#4386)

Documentation and Tests

  • COMPILE.md: Mention dependencies and add link to Docs (#4431)
  • ejabberd_doc: Document commands tags for modules
  • CI: bump XMPP-Interop-Testing/xmpp-interop-tests-action (#4425)
  • Runtime: Raise the minimum Erlang tested to Erlang/OTP 24

Installers and Container

  • Bump Erlang/OTP version to 27.3.4.2
  • Bump OpenSSL version to 3.5.2
  • make-binaries: Disable Linux-PAM's logind support

Core and Modules

  • Bump p1_acme to fix 'AttributePKCS-10' and OTP 28 (processone/p1_acme#4)
  • Prevent loops in xml_compress:decode with corrupted data
  • ejabberd_auth_mnesia: Fix issue with filtering duplicates in get_users()
  • ejabberd_listener: Add secret in temporary unix domain socket path (#4422)
  • ejabberd_listener: Log error when cannot set definitive unix socket (#4422)
  • ejabberd_listener: Try to create provisional socket in final directory (#4422)
  • ejabberd_logger: Print log lines colorized in console when using rebar3
  • mod_conversejs: Ensure assets_path ends in / as required by Converse (#4414)
  • mod_conversejs: Ensure plugins URL is separated with / (#4413)
  • mod_http_upload: Encode URLs into IDNA when showing to XMPP client (#3519)
  • mod_matrix_gw: Add support for null values in is_canonical_json (#4421)
  • mod_matrix_gw: Don't send empty direct Matrix messages (#4420)
  • mod_matrix_gw: Matrix gateway updates
  • mod_muc: Report db failures when restoring rooms
  • mod_muc: Unsubscribe users from members-only rooms when expelled (#4412)
  • mod_providers: New module to serve easily XMPP Providers files
  • mod_register: Don't duplicate welcome subject and message
  • mod_scram_upgrade: Fix format of passwords updates
  • mod_scram_upgrade: Only offer upgrades to methods that aren't already stored

Full Changelog

https://github.com/processone/ejabberd/compare/25.07...25.08

ejabberd 25.08 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

25.07 Breaking risk
⚠ Upgrade required
  • Erlang/OTP minimum version is now 25.0; upgrade your runtime accordingly.
  • If you still need to run ejabberd on Erlang/OTP versions below 25, bypass the check with `./configure --with-min-erlang=9.0.5` during compilation.
  • `default_host` configuration option for `ejabberd_http` is removed; migrate any usage to `hosts_alias` if needed.
Breaking changes
  • Minimum supported Erlang/OTP version raised to 25.0 (previously lower versions were allowed).
  • Removed `default_host` option from `ejabberd_http` listener configuration.
Security fixes
  • CVE-2025-4748 — zip module absolute‑path vulnerability mitigated with a workaround in ejabberd 25.07.
Notable features
  • New `mod_antispam` module with Real‑Time Block List (RTBL) support.
  • Support for XEP-0485 PubSub Server Information via new `mod_pubsub_serverinfo`.
  • XEP-0431 Full Text Search added to MAM (MySQL backend only).
Full changelog

Release notes copied from the original ejabberd 25.07 announcement post:

We are pleased to announce a new ejabberd release: ejabberd 25.07, with three months of work and more than 110 commits to bring new modules, new features, improvements and bugfixes.

Release Highlights:

This release focus on integration in a wider federated network, with support for spam fighting features, better compliance with Matrix network and native support for PubSub Server Information to have your server count as part of the wider XMPP network (for example, you can register your server on XMPP Network Graph.

If you are upgrading from a previous version, there are no changes in SQL schemas, configuration, API commands or hooks.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

Workaround for zip module in unpatched Erlang

A vulnerability was published three weeks ago that affects the zip library included in Erlang/OTP: CVE-2025-4748: Absolute path in zip module.

The ejabberd installers and the ejabberd container image already use a patched version Erlang/OTP 27.3.4.1, but the ecs container image uses Erlang/OTP 26.2.

ejabberd 25.07 includes a specific protection that workarounds that vulnerability regardless of what Erlang/OTP version you are using.

Erlang/OTP 28 supported

Updating ejabberd to support Erlang/OTP 28 has required quite some work due to the replacement of ancient ASN.1 modules from Erlang/OTP public_key library.

Improvements were done on ejabberd, fast_xml, p1_acme, xmpp libraries, and also rebar/rebar3 binaries were recompiled.

However, there is still one last problem not yet solved which implies that ACME support is broken when using Erlang/OTP 28.0.1. The fix will probably be included in the next Erlang/OTP 28 release.

Erlang/OTP 25 required

The minimum Erlang/OTP version supported since now is 25.0.

However, we are aware there are still a few specific cases where older Erlang/OTP versions are being used. For that reason, the source code support for those versions is still available, and static source code analysis tools like xref and dialyzer are still run with Erlang/OTP 20 in runtime.yml.

If you really need to use ejabberd with Erlang/OTP 20 - 24, you can bypass the version check during compilation with this ./configure option: ./configure --with-min-erlang=9.0.5

New mod_antispam with RTBL support

mod_antispam is a new module that filters spam messages and subscription requests received from remote servers based on Real-Time Block Lists (RTBL), text lists of known spammer JIDs and/or URLs mentioned in spam messages.

This module is based in mod_spam_filter which was originally published in ejabberd-contrib. If you were using that module, you can update your configuration and start using mod_antispam instead.

New mod_pubsub_serverinfo

mod_pubsub_serverinfo adds support for XEP-0485: PubSub Server Information to expose S2S information over the Pub/Sub service.

This module was originally published in ejabberd-contrib. If you were using that module, you can remove it, as now it's included in ejabberd.

Improvements in Matrix gateway

While we are preparing another big update for the Matrix gateway. The most important change is that we added support to a larger number of room versions. It allows users to let them join a lot of rooms that were already created a while back and running an older version of the room protocol.

Here is the main list of changes to the matrix gateway:

  • mod_matrix_gw: Support older Matrix rooms versions starting from version 4
  • mod_matrix_gw: Don't send empty messages in Matrix rooms (#4385)
  • mod_matrix_gw: Fix key validation in mod_matrix_gw_s2s:check_signature
  • mod_matrix_gw: When encoding JSON, handle term that is key-value list (#4379)

XEP-0431: Full Text Search in MAM

Support for XEP-0431: Full Text Search in MAM has been added. For now, it only works if mod_mam is using the MySQL storage backend.

New rest_proxy options

With those new options you can make modules using rest.erl module (like ejabberd_oauth_rest) use HTTP proxy when performing HTTP requests.

The related new top level options are:

  • rest_proxy: Address of a HTTP Connect proxy
  • rest_proxy_port: Port of a HTTP Connect proxy
  • rest_proxy_username: Username used to authenticate to HTTP Connect proxy (optional)
  • rest_proxy_password: Password used to authenticate to HTTP Connect proxy (optional)

New auth_password_types_hidden_in_scram1 option

This option was added to help with adding new password types in auth_stored_password_types option to existing installations. Adding new password type made server advertise it to clients, but that caused problems for users that didn't have new password type stored, and which clients used SASL1 authentication, if client tried to authenticate with it, authentications would fail.

With this new option, server admin can choose which password types should not be presented to SASL1 clients (they still will be offered to SASL2 clients for users that have password compatible with this type), to later after users update password to have new type, being able to enable them.

This option takes list of password types from auth_stored_password_types that should be disabled

auth_password_types_hidden_in_scram1:
  - scram_sha512
  - scram_sha256

New hosts_alias option

The new hosts_alias toplevel option is used by the ejabberd_http listener to resolve domain names into vhosts served by ejabberd.

For example, ejabberd is serving the vhost redacted.lan, but you configured DNS so xmpp.redacted.lan resolves to that host. If you configure in ejabberd:

hosts:
  - redacted.lan

hosts_alias:
  xmpp.redacted.lan: redacted.lan

listen:
  -
    port: 443
    ip: "::"
    tls: true
    module: ejabberd_http
    request_handlers:
      "/bosh": mod_bosh
      "/ws": ejabberd_http_ws
      "/conversejs": mod_conversejs

modules:
  mod_bosh:
  mod_conversejs:
    bosh_service_url: "https://xmpp.redacted.lan/bosh"
    websocket_url: "wss://xmpp.redacted.lan/ws"

then ejabberd_http will accept https://xmpp.redacted.lan/conversejs and deliver it to vhost redacted.lan

In previous ejabberd releases, an option called default_host was documented for the ejabberd_http listener, but it didn't work at all correctly.

New predefined keywords

A few months ago, ejabberd 25.03 introduced new predefined keywords like HOST, HOME, VERSION and SEMVER.

And now two more predefined keywords are added:

  • CONFIG_PATH: Path to the configuration directory, for example "/home/ejabberd/opt/ejabberd/conf"
  • LOG_PATH: Path to the log directory, for example "/home/ejabberd/opt/ejabberd/logs"

Those keywords are specially useful when configuring mod_antispam: you can copy text files to the configuration directory where the module will read them, and also configure the module to write the dump file on the log directory.

Link to Converse in WebAdmin

mod_conversejs has a new tiny improvement: it adds a link in the WebAdmin menu to the local Converse instance.

Additionally, when HTTPS with encryption is enabled, that link logins directly with the account used in WebAdmin.

Updates in source code formatting

A year ago, ejabberd 24.06 introduced make format and make indent.

Now that script uses Perl to work correctly in Mac OS too.

And there's a new section in the documentation, see Format that describes how to use that feature, and tips for Git hooks and Git alias.

New target test-group

ejabberd includes a Common Test suite with 1456 test cases, which typically takes around 10 minutes to run.

When developing new source code, you may want to run only tests from a specific group and a specific storage backend, as documented in the ejabberd testing documentation:

CT_BACKENDS=mnesia rebar3 ct --suite=test/ejabberd_SUITE --group=antispam_single

To facilitate this usage, a new target is available:

CT_BACKENDS=mnesia make test-antispam_single

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the following changes.

Monitoring

The following new metrics has been added to mod_mon:

  • message_receive_packet: number of message stanzas of any type received by the server on c2s connections
  • message_send_packet: number of message stanzas of any type send by the server on c2s connections
  • iq_receive_packet: number of IQ stanzas received by the server on c2s connections
  • iq_send_packet: number of IQ stanzas send by the server on c2s connections
  • iq_get_receive_packet: number of IQ stanzas of type get received by the server on c2s connections
  • iq_set_receive_packet: number of IQ stanzas of type set received by the server on c2s connections
  • iq_result_receive_packet: number of IQ stanzas of type result received by the server on c2s connections
  • iq_error_receive_packet: number of IQ stanzas of type error received by the server on c2s connections
  • iq_get_send_packet: number of IQ stanzas of type get send by the server on c2s connections
  • iq_set_send_packet: number of IQ stanzas of type set send by the server on c2s connections
  • iq_result_send_packet: number of IQ stanzas of type result send by the server on c2s connections
  • iq_error_send_packet: number of IQ stanzas of type error send by the server on c2s connections

The metrics c2s_receive & c2s_send now count all stanzas on c2s connections.

The cpu_usage probe now gives more reliable values.

Prometheus support has been improved.

A new mod_mon_dump command has been added to dump probe values to help debug the monitoring setup.

Mobile push

It is now possible to use rest_proxy* options to use a HTTP proxy for mod_applepush & mod_gcm outgoing HTTPS calls.

ChangeLog

This is a more complete list of changes in this ejabberd release:

Security fix

  • ext_mod: Add temporary workaround for zip including absolute path

Compilation

  • Raise the minimum Elixir tested version to 1.14.0 (#4281)
  • Raise Erlang/OTP minimum requirement to 25.0 (#4281)
  • configure.ac: Allow to specify minimal erlang version using --with-min-erlang
  • Makefile.in: Add target test-<group>
  • rebar3-format.sh: Replace csplit with perl
  • Container: Bump Erlang/OTP 27.3.4.1, Elixir 1.18.4
  • Installers: Bump Erlang/OTP 27.3.4.1, Elixir 1.18.4, libexpat 2.7.1, OpenSSL 3.5.1

Configuration and Tests

  • Add rest_proxy* options to configure proxy used by rest module
  • ejabberd_c2s: Add auth_password_types_hidden_in_scram1 option
  • ejabberd_http: Remove unused default_host option and state element
  • ejabberd_http: New option hosts_alias and function resolve_host_alias/1 (#4400)
  • New predefined keywords: CONFIG_PATH and LOG_PATH
  • Fix macro used in string options when defined in env var
  • Use auxiliary function to get $HOME, use Mnesia directory when not set (#4402)
  • ejabberd_config: Better lists:uniq substitute
  • Tests: update readme and compose to work with current sw versions
  • Update Elvis to 4.1.1, fix some warnings and enable their tests

Erlang/OTP 28 support

  • Add workaround in p1_acme for Jose 1.11.10 not supporting OTP 28 ecPrivkeyVer1 (#4393)
  • Bump fast_xml and xmpp for improved Erlang/OTP 28 support
  • Bump xmpp and p1_acme patched with Erlang/OTP 28 support
  • Fix make options in Erlang/OTP 28 (#4352)
  • Fix crash in rebar3 cover with Erlang/OTP 28 (#4353)
  • Rebar/Rebar3: Update binaries to work with Erlang/OTP 25-28 (#4354)
  • CI and Runtime: Add Erlang/OTP 28 to the versions matrix

SQL

  • Fix mnesia to sql exporter after changes to auth tables
  • Update code for switching to new schema type to users table changes
  • Add mssql specific implementation of delete_old_mam_messages
  • Make delete_old_mam_messages_batch work with sqlite
  • ejabberd_sm_sql: Use misc:encode_pid/1
  • mysql.sql: Fix typo in commit 7862c6a when creating users table
  • pg.sql: Fix missing comma in postgres schema (#4409)

Core and Modules

  • ejabberd_s2s_in: Allow S2S connections to accept client certificates that have only server purpose (#4392)
  • ext_mod: Recommend to write README.md instead txt (processone/ejabberd-contrib#363)
  • ext_mod: Support library path installed from Debian (processone/ejabberd-contrib#363)
  • ext_mod: When upgrading module, clean also the compiled directories
  • gen_mod: Add support to prepare module stopping before actually stopping any module
  • mod_antispam: Imported from ejabberd-contrib and improved (#4373)
  • mod_auth_fast: Clear tokens on kick, change pass and unregister (#4397)(#4398)(#4399)
  • mod_conversejs: Add link in WebAdmin to local Converse if configured
  • mod_mam: Present mam full text search in xep-431 compatible way
  • mod_mam_mnesia: Handle objects that don't need conversion in transform/0
  • mod_matrix_gw: Don't send empty messages in Matrix rooms (#4385)
  • mod_matrix_gw: Support older Matrix rooms versions starting from version 4
  • mod_matrix_gw: When encoding JSON, handle term that is key-value list (#4379)
  • mod_matrix_gw_s2s: Fix key validation in check_signature
  • mod_mix and mod_muc_rtbl: Support list of IDs in pubsub-items-retract (processone/xmpp#100)
  • mod_pubsub_serverinfo: Imported module from ejabberd-contrib (#4408)
  • mod_register: Normalize username when determining if user want to change pass
  • mod_register: Strip query data when returning errors
  • WebAdmin: New hooks webadmin_menu_system to add items to system menu

Full Changelog

https://github.com/processone/ejabberd/compare/25.04...25.07

ejabberd 25.07 download & feedback

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

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you've found a bug, please search or fill a bug report on GitHub Issues.

Beta — feedback welcome: [email protected]