> ## Content Index
> Fetch the complete content index at: https://www.process-one.net/llms.txt
> Use this file to discover other available public pages before exploring further.

# 🚀 ejabberd 26.01
- URL: https://www.process-one.net/blog/ejabberd-26-01/
- Published: 2026-01-21T17:50:12.000Z
- Updated: 2026-01-21T17:50:12.000Z
- Description: 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.
- Author: Jérôme Sautret
- Tags: ejabberd, Release, XMPP

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

**Release Highlights:**

- **[Database Serialization](#database)**
- **[Roster Invites and Invite-based Account Registration](#invites)**

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:**

- **[SQL table for mod\_invites](#sqlinvites)**
- **[New replaced\_connection\_timeout](#replaced)**
- **[Improved mod\_http\_fileserver docroot option](#docroot)**
- **[Supported XEP Versions](#xep)**
- **[Erlang, Elixir and Container](#erlang)**
- **[Improved ERL\_DIST\_PORT](#erldistport)**
- **[New make relivectl](#relivectl)**
- **[WebAdmin Menu Links](#webadmin)**
- **[Acknowledgments](#ack)**
- **[Improvements in ejabberd Business Edition](#ebe)**
- **[ChangeLog](#changelog)**
- **[ejabberd 26.01 download & feedback](#download)**

Below is a detailed breakdown of the improvements and enhancements:

## Database Serialization

This feature adds new way for migrating data between [database backends](https://docs.ejabberd.im/admin/configuration/database/?ref=process-one.net) 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](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/?ref=process-one.net#export%5Fdb) command, changing configuration of ejabberd and switching modules to use new database backend, and then importing previously exported data using [import\_db](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/?ref=process-one.net#import%5Fdb) 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](https://docs.ejabberd.im/admin/guide/managing/?ref=process-one.net#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](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fregister)) or Web Registration ([mod\_register\_web](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fregister%5Fweb)), and then try to limit abuse with access limitations or [CAPTCHAs](https://docs.ejabberd.im/admin/configuration/basic/?ref=process-one.net#captcha). 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](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Finvites) 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:

- [mod\_invites documentation](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Finvites)
- [Great Invitations](https://blog.prosody.im/great-invitations/?ref=process-one.net), the original Prosody blog post that described this feature
- [XEP-0379: Pre-Authenticated Roster Subscription](https://xmpp.org/extensions/xep-0379.html?ref=process-one.net)
- [XEP-0401: Ad-hoc Account Invitation Generation](https://xmpp.org/extensions/xep-0401.html?ref=process-one.net)
- [XEP-0445: Pre-Authenticated In-Band Registration](https://xmpp.org/extensions/xep-0445.html?ref=process-one.net)
- This development was [funded by NLnet](https://nlnet.nl/project/ejabberd-invites/?ref=process-one.net)

Quick setup:

1. If using SQL storage for the modules and have disabled the [update\_sql\_schema](https://docs.ejabberd.im/admin/configuration/toplevel/?ref=process-one.net#update%5Fsql%5Fschema) toplevel option, then [create manually the SQL table](#sqlinvites), see below.
2. If you plan to use the landing page included with `mod_invites`, install JavaScript libraries [jQuery](https://jquery.com/?ref=process-one.net) version [3.7.1](https://code.jquery.com/jquery-3.7.1.min.js?ref=process-one.net) and [Bootstrap](https://getbootstrap.com/?ref=process-one.net) version [4.6.2](https://github.com/twbs/bootstrap/releases/download/v4.6.2/bootstrap-4.6.2-dist.zip?ref=process-one.net). 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:  
  ```shell  
  apt install libjs-jquery libjs-bootstrap4  
  ```
  - AlpineLinux and other operating systems where you can install `npm`, for example:  
  ```shell  
  apk -U add --no-cache nodejs npm ca-certificates  
  npm init -y \  
    && npm install --silent jquery@3.7.1 bootstrap@4.6.2  
  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:  
  ```shell  
  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:  
```yaml  
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](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fadhoc%5Fapi) is enabled, you can execute equivalent API Commands [generate\_invite](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/?ref=process-one.net#generate%5Finvite) and [generate\_invite\_with\_username](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/?ref=process-one.net#generate%5Finvite%5Fwith%5Fusername)
  - 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](https://docs.ejabberd.im/developer/extending-ejabberd/localization/?ref=process-one.net).

![](https://www.process-one.net/content/images/2026/01/ejabberd_blog_2601.png)

## [](sqlinvites)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](../../admin/configuration/toplevel.md#update%5Fsql%5Fschema) 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:  
```sql  
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:  
```sql  
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:  
```sql  
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:  
```sql  
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:  
```sql  
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:  
```sql  
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);  
```

## [](replaced)New replaced\_connection\_timeout toplevel option

The new [replaced\_connection\_timeout](https://docs.ejabberd.im/admin/configuration/toplevel/?ref=process-one.net#replaced%5Fconnection%5Ftimeout) 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](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fhttp%5Ffileserver) 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`:

```yaml
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](https://docs.ejabberd.im/admin/configuration/listen/?ref=process-one.net#ejabberd%5Fhttp).

## Supported XEP versions

ejabberd supports close to 90 [XMPP extension protocols (XEPs)](https://xmpp.org/extensions/?ref=process-one.net), either directly implemented in ejabberd source code, in the [libraries](https://docs.ejabberd.im/developer/repositories/?ref=process-one.net#mandatory) that implement many of the internal features, or in other ejabberd modules available in other repositories like [ejabberd-contrib](https://docs.ejabberd.im/admin/guide/modules/?ref=process-one.net#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](https://github.com/processone/xmpp/?ref=process-one.net) 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](https://xmpp.org/software/ejabberd/?ref=process-one.net) and [erlang-xmpp at XMPP.org](https://xmpp.org/software/erlang-elixir-xmpp/?ref=process-one.net).

## Erlang, Elixir and Container

ejabberd can be compiled with [Erlang/OTP](https://www.erlang.org/?ref=process-one.net) from 25.0 up to the latest 28.3.1\. Regarding [Elixir](https://elixir-lang.org/?ref=process-one.net) 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](https://docs.ejabberd.im/admin/install/binary-installer/?ref=process-one.net) 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](https://docs.ejabberd.im/CONTAINER/?ref=process-one.net), both `ejabberd` and `ecs` bring other minor changes: they expose more [ports](https://docs.ejabberd.im/admin/guide/security/?ref=process-one.net#firewall-settings): 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](https://docs.ejabberd.im/CONTAINER/?ref=process-one.net#macros-in-environment).

## Improved ERL\_DIST\_PORT

ejabberd uses [Erlang Distribution](https://docs.ejabberd.im/admin/guide/distribution/?ref=process-one.net) in the [ejabberdctl](https://docs.ejabberd.im/admin/guide/managing/?ref=process-one.net#ejabberdctl) shell script and also for building a cluster of ejabberd nodes.

That Erlang Distribution has historically used the [epmd](https://docs.ejabberd.im/admin/guide/distribution/?ref=process-one.net#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](https://docs.ejabberd.im/admin/guide/distribution/?ref=process-one.net#erl%5Fdist%5Fport) environment variable in the `ejabberdctl.cfg` file:

```sh
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](#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](https://docs.ejabberd.im/admin/guide/security/?ref=process-one.net), [Erlang Distribution](https://docs.ejabberd.im/admin/guide/distribution/?ref=process-one.net), and [Clustering](https://docs.ejabberd.im/admin/guide/clustering/?ref=process-one.net).

## New make relivectl

`make relive` was [introduced in ejabberd 22.05](https://www.process-one.net/blog/ejabberd-22-05/#new-make-relive). 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](https://www.process-one.net/blog/ejabberd-24-06/#support-for-code-automatic-update). 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](https://docs.ejabberd.im/admin/install/source/?ref=process-one.net#development-release).

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](https://github.com/processone/ejabberd/issues/1496?ref=process-one.net) | 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](https://www.process-one.net/blog/ejabberd-25-07/#link-to-converse-in-webadmin) a link in WebAdmin to the local Converse.js page in the left menu when the corresponding [mod\_conversejs](https://docs.ejabberd.im/admin/configuration/modules/?ref=process-one.net#mod%5Fconversejs) 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:

```yaml
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:

```yaml
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](https://docs.ejabberd.im/admin/guide/modules/?ref=process-one.net#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:

- [Stefan Strigler](https://github.com/sstrigler?ref=process-one.net) for new feature Great Invitations aka `mod_invites`
- [Kirill A. Korinsky](https://github.com/catap?ref=process-one.net) and [Greg Troxel](https://github.com/gdt?ref=process-one.net) for `ejabberdctl` support NetBSD and OpenBSD `su`
- [Christoph Scholz](https://github.com/ChaosKid42?ref=process-one.net) for fix preload\_rooms in case of SQL-DB
- [Mr. EddX](https://github.com/MrEddX?ref=process-one.net) and [Kiril Panayotov](https://github.com/zakrok?ref=process-one.net) for updating the Bulgarian translation
- [Sketch6580](https://hosted.weblate.org/user/Sketch6580/?ref=process-one.net) for updating the Chinese (Simplified) translation
- [poVoq](https://github.com/poVoq?ref=process-one.net), [Nautilusx](https://hosted.weblate.org/user/nautilusx/?ref=process-one.net) and [Stefan Strigler](https://github.com/sstrigler?ref=process-one.net) for updating the German translation
- [Stefan Strigler](https://github.com/sstrigler?ref=process-one.net) for updating the Swedish translation

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

## Improvements in ejabberd Business Edition

Customers of the [ejabberd Business Edition](https://www.process-one.net/en/ejabberd/), 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](https://github.com/processone/ejabberd/issues/4320?ref=process-one.net))
- `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](https://github.com/processone/ejabberd/issues/4489?ref=process-one.net))
- Announce `stable-id` feature from XEP-0045 1.31, supported since long ago
- Fix `preload_rooms` in case of SQL database ([#4476](https://github.com/processone/ejabberd/issues/4476?ref=process-one.net))
- Run new hooks: `registering_nickmuc` and `registered_nickmuc` ([#4478](https://github.com/processone/ejabberd/issues/4478?ref=process-one.net))
- When deleting account, unregister account's nicks in all MUC hosts ([#4478](https://github.com/processone/ejabberd/issues/4478?ref=process-one.net))
- `mod_muc_log`: Crash in `terminate/2` when stopping module ([#4486](https://github.com/processone/ejabberd/issues/4486?ref=process-one.net))
- `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](https://github.com/processone/ejabberd/issues/4503?ref=process-one.net))
- `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](https://github.com/processone/ejabberd/issues/4495?ref=process-one.net))
- 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](https://github.com/processone/ejabberd/issues/4488?ref=process-one.net))
- `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](https://github.com/processone/ejabberd/issues/3519?ref=process-one.net))
- `mod_http_fileserver`: Support map of paths in `docroot` option
- `mod_conversejs`: Add new Conversejs Paths and ContentTypes ([#4511](https://github.com/processone/ejabberd/issues/4511?ref=process-one.net))
- `mod_conversejs`: Use ContentType functions from `mod_http_fileserver` ([#4511](https://github.com/processone/ejabberd/issues/4511?ref=process-one.net))
- 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](https://github.com/processon4475e/ejabberd/issues/?ref=process-one.net))
- `ejabberd_commands`: Show meaningul error message when problem executing command ([#4506](https://github.com/processone/ejabberd/issues/4506?ref=process-one.net))
- `ejabberd_logger`: Append "color clean" only in console template, not file
- `ejabberd_oauth`: Log error if `oauth_list_tokens` executed with unsupported DB ([#4506](https://github.com/processone/ejabberd/issues/4506?ref=process-one.net))
- `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](https://github.com/processone/ejabberd/issues/4487?ref=process-one.net))

### Full Changelog

[https://github.com/processone/ejabberd/compare/25.10...26.01](https://github.com/processone/ejabberd/compare/25.10...26.01?ref=process-one.net)

##  ejabberd 26.01 download & feedback

As usual, the release is tagged in the Git source code repository on [GitHub](https://github.com/processone/ejabberd?ref=process-one.net).

The source package and installers are available in [ejabberd Downloads](https://www.process-one.net/en/ejabberd/downloads/) page. To check the `*.asc` signature files, see [How to verify ProcessOne downloads integrity](https://www.process-one.net/blog/verifying%5Fprocess%5Fone%5Fdownloads%5Fintegrity/).

For convenience, there are alternative download locations like the [ejabberd DEB/RPM Packages Repository](https://repo.process-one.net/?ref=process-one.net) and the [GitHub Release / Tags](https://github.com/processone/ejabberd/tags?ref=process-one.net).

The `ecs` container image is available in [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/?ref=process-one.net) and [ghcr.io/processone/ecs](https://github.com/processone/docker-ejabberd/pkgs/container/ecs?ref=process-one.net). The alternative `ejabberd` container image is available in [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd?ref=process-one.net).

If you consider that you've found a bug, please search or fill a bug report on [GitHub Issues](https://github.com/processone/ejabberd/issues?ref=process-one.net).