Run Common Test suite for specific group only [rebar3]"
+ @echo " xref Run cross reference analysis [rebar3]"
+
+#.
+#'
+# vim: foldmarker=#',#. foldmethod=marker:
diff --git a/README.md b/README.md
index 7d526ee55..646cc4a17 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,36 @@
-
+
-
-
-
-
+
+
+
+
-
+
-
+
+
+
-
[ejabberd][im] is an open-source,
robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang],
that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service.
Check the features in [ejabberd.im][im], [ejabberd Docs][features],
-[ejabberd at ProcessOne][p1home], and a list of [supported protocols and XEPs][xeps].
-
+[ejabberd at ProcessOne][p1home], and the list of [supported protocols in ProcessOne][xeps]
+and [XMPP.org][xmppej].
Installation
------------
@@ -38,12 +38,16 @@ Installation
There are several ways to install ejabberd:
- Source code: compile yourself, see [COMPILE](COMPILE.md)
-- Installers from [ejabberd GitHub Releases][releases] (run/deb/rpm for x64 and arm64)
-- Container image from [ejabberd Docker Hub][hubecs], see [ecs README][docker-ecs-readme] (for x64)
-- Container image from [ejabberd Github Packages][packages], see [CONTAINER](CONTAINER.md) (for x64 and arm64)
+- Installers:
+ - [ProcessOne Download Page][p1download] or [GitHub Releases][releases] for releases.
+ - [GitHub Actions](https://github.com/processone/ejabberd/actions/workflows/installers.yml) for master branch (`run`/`deb`/`rpm` for `x64` and `arm64`)
+- Docker Containers:
+ - `ecs` container image: [Docker Hub][hubecs] and [Github Packages][packagesecs], see [ecs README][docker-ecs-readme] (for `x64`)
+ - `ejabberd` container image: [Github Packages][packages] for releases and master branch, see [CONTAINER](CONTAINER.md) (for `x64` and `arm64`)
- Using your [Operating System package][osp]
- Using the [Homebrew][homebrew] package manager
+More info can be found in the `Installation` part of [ejabberd Docs](https://docs.ejabberd.im/admin/install/).
Documentation
-------------
@@ -60,7 +64,6 @@ Once ejabberd is installed, try:
ejabberdctl help
man ejabberd.yml
-
Development
-----------
@@ -72,31 +75,37 @@ or in your local machine as explained in [Localization][localization].
Documentation for developers is available in [ejabberd docs: Developers][docs-dev].
+There are nightly builds of ejabberd, both for `master` branch and for Pull Requests:
+
+- Installers: go to [GitHub Actions: Installers](https://github.com/processone/ejabberd/actions/workflows/installers.yml), open the most recent commit, on the bottom of that commit page, download the `ejabberd-packages.zip` artifact.
+- `ejabberd` container image: go to [ejabberd Github Packages][packages]
+
Security reports or concerns should preferably be reported privately,
-please send an email to the address: contact [at] process-one [dot] net
+please send an email to the address: contact at process-one dot net
or some other method from [ProcessOne Contact][p1contact].
For commercial offering and support, including [ejabberd Business Edition][p1home]
and [Fluux (ejabberd in the Cloud)][fluux], please check [ProcessOne ejabberd page][p1home].
+Security
+--------
+
+For information on how to report security vulnerabilities, please refer to the [SECURITY.md](SECURITY.md) file. It contains guidelines on how to report vulnerabilities privately and securely, ensuring that any issues are addressed in a timely and confidential manner.
Community
---------
There are several places to get in touch with other ejabberd developers and administrators:
-- [ejabberd XMPP chatroom][muc]: ejabberd@conference.process-one.net
-- [Mailing list][list]
+- ejabberd XMPP chatroom: [ejabberd@conference.process-one.net][muc]
- [GitHub Discussions][discussions]
- [Stack Overflow][stackoverflow]
-
License
-------
-ejabberd is released under the GNU General Public License v2 (see [COPYING](COPYING.md)),
-and [ejabberd translations](https://github.com/processone/ejabberd-po/) under MIT License.
-
+- ejabberd is released under the __GNU General Public License v2__ (see [COPYING](COPYING))
+- [ejabberd translations](https://github.com/processone/ejabberd-po/) under __MIT License__.
[discussions]: https://github.com/processone/ejabberd/discussions
[docker-ecs-readme]: https://github.com/processone/docker-ejabberd/tree/master/ecs#readme
@@ -105,22 +114,23 @@ and [ejabberd translations](https://github.com/processone/ejabberd-po/) under MI
[erlang]: https://www.erlang.org/
[features]: https://docs.ejabberd.im/admin/introduction/
[fluux]: https://fluux.io/
-[github]: https://github.com/processone/ejabberd
-[homebrew]: https://docs.ejabberd.im/admin/installation/#homebrew
+[homebrew]: https://docs.ejabberd.im/admin/install/homebrew/
[hubecs]: https://hub.docker.com/r/ejabberd/ecs/
-[im]: https://ejabberd.im/
+[im]: https://www.ejabberd.im/
[issues]: https://github.com/processone/ejabberd/issues
-[list]: https://lists.jabber.ru/mailman/listinfo/ejabberd
[localization]: https://docs.ejabberd.im/developer/extending-ejabberd/localization/
[mqtt]: https://mqtt.org/
[muc]: xmpp:ejabberd@conference.process-one.net
-[osp]: https://docs.ejabberd.im/admin/installation/#operating-system-packages
-[p1contact]: https://www.process-one.net/en/company/contact/
-[p1home]: https://www.process-one.net/en/ejabberd/
+[osp]: https://docs.ejabberd.im/admin/install/os-package/
+[p1contact]: https://www.process-one.net/contact/
+[p1download]: https://www.process-one.net/download/ejabberd/
+[p1home]: https://www.process-one.net/ejabberd/
[packages]: https://github.com/processone/ejabberd/pkgs/container/ejabberd
+[packagesecs]: https://github.com/processone/docker-ejabberd/pkgs/container/ecs
[releases]: https://github.com/processone/ejabberd/releases
[sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol
[stackoverflow]: https://stackoverflow.com/questions/tagged/ejabberd?sort=newest
[weblate]: https://hosted.weblate.org/projects/ejabberd/ejabberd-po/
-[xeps]: https://www.process-one.net/en/ejabberd/protocols/
+[xeps]: https://www.process-one.net/ejabberd-features/
[xmpp]: https://xmpp.org/
+[xmppej]: https://xmpp.org/software/servers/ejabberd/
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..bb2292826
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,45 @@
+# Security Policy
+
+## Supported Versions
+
+We recommend that all users always use the latest version of ejabberd.
+
+To ensure the best experience and security, upgrade to the latest version available on [this repo](https://github.com/processone/ejabberd).
+
+## Reporting a Vulnerability
+
+### Private Reporting
+
+**Preferred Method**: Use GitHub's private vulnerability reporting system by clicking the "Report a Vulnerability" button in the [Security tab of this repository](https://github.com/processone/ejabberd/security). This ensures your report is securely transmitted and tracked.
+
+**Alternative**: If you cannot use the GitHub system, send an email to **`contact@process-one.net`** with the following details:
+
+- A clear description of the vulnerability.
+- Steps to reproduce the issue.
+- Any potential impact or exploitation scenarios.
+
+### Response Time
+
+We aim to acknowledge receipt of your report within 72 hours. You can expect regular updates on the status of your report.
+
+### Resolution
+
+If the vulnerability is confirmed, we will work on a patch or mitigation strategy.
+We will notify you once the issue is resolved and coordinate a public disclosure if needed.
+
+### Acknowledgements
+
+We value and appreciate the contributions of security researchers and community members.
+If you wish, we are happy to acknowledge your efforts publicly by listing your name (or alias) below in this document.
+Please let us know if you would like to be recognized when reporting the vulnerability.
+
+## Public Discussion
+
+For general inquiries or discussions about the project’s security, feel free to chat with us here:
+
+- XMPP room: `ejabberd@conference.process-one.net`
+- [GitHub Discussions](https://github.com/processone/ejabberd/discussions)
+
+However, please note that if the issue is **critical** or potentially exploitable, **do not share it publicly**. Instead, we strongly recommend you contact the maintainers directly via the private reporting methods outlined above to ensure a secure and timely response.
+
+Thank you for helping us improve the security of ejabberd!
diff --git a/config/runtime.exs b/config/runtime.exs
index b4e6dc5f1..adfc18c06 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -8,6 +8,8 @@ end
rootpath = System.get_env("RELEASE_ROOT", rootdefault)
config :ejabberd,
file: Path.join(rootpath, "conf/ejabberd.yml"),
- log_path: Path.join(rootpath, 'logs/ejabberd.log')
+ log_path: Path.join(rootpath, "logs/ejabberd.log")
config :mnesia,
- dir: Path.join(rootpath, 'database/')
+ dir: Path.join(rootpath, "database/")
+config :exsync,
+ reload_callback: {:ejabberd_admin, :update, []}
diff --git a/configure.ac b/configure.ac
index 560be9155..b91595dc5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,15 +2,26 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
-AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 22.10` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
-REQUIRE_ERLANG_MIN="8.3 (Erlang/OTP 19.3)"
+AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 25.08` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
+
+AC_ARG_WITH(min-erlang,
+ AS_HELP_STRING([--with-min-erlang=version],[set minimal required erlang version, default to OTP25]),
+[if test "X$withval" = "X"; then
+ REQUIRE_ERLANG_MIN="13.0 (Erlang/OTP 25.0)"
+else
+ REQUIRE_ERLANG_MIN="$withval"
+fi
+], [REQUIRE_ERLANG_MIN="13.0 (Erlang/OTP 25.0)"])
+
REQUIRE_ERLANG_MAX="100.0.0 (No Max)"
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_MAKE_SET
+AC_PROG_AWK
AC_PROG_INSTALL
+AC_PROG_MKDIR_P
AC_PROG_SED
if test "x$GCC" = "xyes"; then
@@ -28,18 +39,42 @@ fi
])
AC_ARG_WITH(rebar,
- AS_HELP_STRING([--with-rebar=bin],[use the rebar/rebar3/mix binary specified]),
+ AS_HELP_STRING([--with-rebar=bin],[use as build tool the rebar/rebar3/mix binary specified]),
[if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_rebar" = "X"; then
- rebar="rebar"
+ rebar="rebar3"
else
rebar="$with_rebar"
fi
-], [rebar="rebar"])
+], [rebar="unconfigured"])
AC_PATH_TOOL(ERL, erl, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(ERLC, erlc, , [${extra_erl_path}$PATH])
AC_PATH_TOOL(EPMD, epmd, , [${extra_erl_path}$PATH])
+AC_PATH_TOOL(REBAR, rebar, , [${extra_erl_path}$PATH])
+AC_PATH_TOOL(REBAR3, rebar3, , [${extra_erl_path}$PATH])
+AC_PATH_TOOL(ELIXIR, elixir, , [${extra_erl_path}$PATH])
+AC_PATH_TOOL(IEX, iex, , [${extra_erl_path}$PATH])
+AC_PATH_TOOL(MIX, mix, , [${extra_erl_path}$PATH])
+
+if test "$rebar" = unconfigured; then
+ if test "x$ELIXIR" = "x" -o "x$IEX" = "x" -o "x$MIX" = "x"; then
+ if test "x$REBAR3" = "x"; then
+ rebar="rebar3"
+ else
+ rebar=$REBAR3
+ fi
+ else
+ rebar=$MIX
+ fi
+fi
+if test "x$rebar" = "xrebar" -a "x$REBAR" = "x" ; then
+ rebar="./rebar"
+fi
+if test "x$rebar" = "xrebar3" -a "x$REBAR3" = "x" ; then
+ rebar="./rebar3"
+fi
+
AC_ERLANG_NEED_ERL
AC_ERLANG_NEED_ERLC
@@ -84,7 +119,7 @@ AC_ARG_ENABLE(debug,
esac],[if test "x$debug" = "x"; then debug=true; fi])
AC_ARG_ENABLE(elixir,
-[AS_HELP_STRING([--enable-elixir],[enable Elixir support (default: no)])],
+[AS_HELP_STRING([--enable-elixir],[enable Elixir support in Rebar3 (default: no)])],
[case "${enableval}" in
yes) elixir=true ;;
no) elixir=false ;;
@@ -112,7 +147,7 @@ esac],[full_xml=false])
ENABLEGROUP=""
AC_ARG_ENABLE(group,
- [AS_HELP_STRING([--enable-group[[[[=GROUP]]]]], [allow this system group to start ejabberd (default: no)])],
+ [AS_HELP_STRING([--enable-group[[=GROUP]]], [specify the group of the account defined in --enable-user (default: no)])],
[case "${enableval}" in
yes) ENABLEGROUP=`groups |head -n 1` ;;
no) ENABLEGROUP="" ;;
@@ -237,7 +272,7 @@ AC_ARG_ENABLE(system_deps,
esac],[if test "x$system_deps" = "x"; then system_deps=false; fi])
AC_ARG_ENABLE(tools,
-[AS_HELP_STRING([--enable-tools],[build development tools (default: no)])],
+[AS_HELP_STRING([--enable-tools],[include debugging/development tools (default: no)])],
[case "${enableval}" in
yes) tools=true ;;
no) tools=false ;;
@@ -246,7 +281,7 @@ esac],[if test "x$tools" = "x"; then tools=false; fi])
ENABLEUSER=""
AC_ARG_ENABLE(user,
- [AS_HELP_STRING([--enable-user[[[[=USER]]]]], [allow this system user to start ejabberd (default: no)])],
+ [AS_HELP_STRING([--enable-user[[=USER]]], [allow this system user to start ejabberd (default: no)])],
[case "${enableval}" in
yes) ENABLEUSER=`whoami` ;;
no) ENABLEUSER="" ;;
@@ -280,6 +315,8 @@ case "`uname`" in
;;
esac
+AC_MSG_RESULT([build tool to use (change using --with-rebar): $rebar])
+
AC_SUBST(roster_gateway_workaround)
AC_SUBST(new_sql_schema)
AC_SUBST(full_xml)
@@ -305,3 +342,28 @@ AC_SUBST(CPPFLAGS)
AC_SUBST(LDFLAGS)
AC_OUTPUT
+
+AS_CASE([$rebar],
+ [*rebar3], [
+ deps=""
+ AS_IF([test "x$stun" = "xfalse"], [deps="stun,$deps"])
+ AS_IF([test "x$sqlite" = "xfalse"], [deps="sqlite3,$deps"])
+ AS_IF([test "x$pgsql" = "xfalse"], [deps="p1_pgsql,$deps"])
+ AS_IF([test "x$mysql" = "xfalse"], [deps="p1_mysql,$deps"])
+ AS_IF([test "x$zlib" = "xfalse"], [deps="ezlib,$deps"])
+ AS_IF([test "x$sip" = "xfalse"], [deps="esip,$deps"])
+ AS_IF([test "x$redis" = "xfalse"], [deps="eredis,$deps"])
+ AS_IF([test "x$pam" = "xfalse"], [deps="epam,$deps"])
+ AS_IF([test "x$deps" = "x"], [],
+ [AC_MSG_NOTICE([unlocking disabled rebar3 dependencies: $deps])
+ $rebar unlock "$deps"])
+ deps=""
+ ERLANG_VERSION=m4_esyscmd([erl -noinput -noshell -eval 'erlang:display(list_to_integer(erlang:system_info(otp_release))), halt().'])
+ AS_IF([test "$ERLANG_VERSION" -lt "21"], [deps="luerl,$deps"])
+ AS_IF([test "$ERLANG_VERSION" -lt "22"], [deps="lager,$deps"])
+ AS_IF([test "$ERLANG_VERSION" -le "23"], [deps="jose,$deps"])
+ AS_IF([test "$ERLANG_VERSION" -ge "27"], [deps="jiffy,$deps"])
+ AS_IF([test "x$deps" = "x"], [],
+ [AC_MSG_NOTICE([unlocking rebar3 dependencies for old Erlang/OTP: $deps])
+ $rebar unlock "$deps"])
+ ])
diff --git a/ejabberd.doap b/ejabberd.doap
new file mode 100644
index 000000000..bfd3f5636
--- /dev/null
+++ b/ejabberd.doap
@@ -0,0 +1,849 @@
+
+
+
+ ejabberd
+ XMPP Server with MQTT Broker and SIP Service
+ Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP Server, MQTT Broker, SIP Service)
+ 2002-11-16
+ BSD
+ Linux
+ macOS
+ Windows
+ Erlang
+ C
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.9
+ 0.5.0
+ complete
+
+
+
+
+
+
+ 2.0
+ 0.5.0
+ complete
+ mod_last
+
+
+
+
+
+ 1.2
+ 16.02
+ complete
+ mod_offline
+
+
+
+
+
+ 1.6
+ 0.5.0
+ complete
+ mod_privacy
+
+
+
+
+
+ 1.4
+ 0.1.0
+ complete
+ mod_offline
+
+
+
+
+
+ 1.3
+ 0.7.5
+ complete
+ mod_offline
+
+
+
+
+
+ 2.4
+ 0.1.0
+ complete
+ mod_disco
+
+
+
+
+
+ 1.1
+ 15.04
+ complete
+ mod_multicast
+
+
+
+
+
+ 0.6.0
+ 0.1.0
+ complete
+ mod_stats
+
+
+
+
+
+ 1.25
+ 0.5.0
+ complete
+ mod_muc
+
+
+
+
+
+ 1.2
+ 0.5.0
+ complete
+ mod_pubsub
+
+
+
+
+
+ 1.2
+ 0.1.0
+ complete
+ mod_private
+
+
+
+
+
+ 1.2
+ 1.1.0
+ complete
+ mod_adhoc
+
+
+
+
+
+ 1.2
+ 0.1.0
+ complete
+ mod_vcard
+
+
+
+
+
+ 1.3
+ 0.1.0
+ complete
+ mod_vcard
+
+
+
+
+
+ 1.0
+ 2.1.0
+ complete
+
+
+
+
+
+
+ 1.14
+ 0.5.0
+ partial
+ mod_pubsub
+
+
+
+
+
+ 1.8
+ 2.0.0
+ complete
+ mod_proxy65
+
+
+
+
+
+ 2.4
+ 0.1.0
+ complete
+ mod_register
+
+
+
+
+
+ 2.5
+ 17.03
+ complete
+ mod_legacy_auth
+
+
+
+
+
+ 1.1.1
+ 2.1.0
+ complete
+
+
+
+
+
+
+ 2.1
+ 2.1.0
+ complete
+ mod_client_state
+
+
+
+
+
+ 1.0
+ 0.5.0
+ complete
+
+
+
+
+
+
+ 1.1
+ 0.1.0
+ complete
+ mod_version
+
+
+
+
+
+ 1.1
+ 0.5.0
+ complete
+
+
+
+
+
+
+ 1.6
+ 0.1.0
+ complete
+ ejabberd_service
+
+
+
+
+
+ 1.5
+ 2.1.4
+ complete
+ mod_caps
+
+
+
+
+
+ 1.11
+ 16.12
+ complete
+ ejabberd_bosh
+
+
+
+
+
+ 1.3.0
+ 13.10
+ partial
+ mod_configure
+
+
+
+
+
+ 2.1
+ 1.1.0
+ complete
+ ejabberd_c2s
+
+
+
+
+
+ 1.1
+ 17.09
+ complete
+ mod_vcard
+
+
+
+
+
+ 1.4.0
+ 22.05
+ complete
+ mod_host_meta
+
+
+
+
+
+ 1.0
+ 2.1.0
+ complete
+ mod_disco
+
+
+
+
+
+ 1.0
+ 2.1.0
+ complete
+ ejabberd_captcha
+
+
+
+
+
+ 1.0
+ 16.01
+ complete
+ mod_offline
+
+
+
+
+
+ 1.2
+ 2.0.0
+ complete
+ mod_pubsub
+
+
+
+
+
+ 1.0
+ 17.12
+ complete
+
+
+
+
+
+
+ 1.2
+ 1.1.0
+ complete
+ ejabberd_auth_anonymous
+
+
+
+
+
+ 1.1
+ 17.03
+ complete
+
+
+
+
+
+
+ 1.0
+ 17.03
+ complete
+ mod_s2s_dialback
+
+
+
+
+
+ 1.2
+ 2.1.7
+ complete
+ mod_blocking
+
+
+
+
+
+ 1.5.2
+ 14.05
+ complete
+ mod_stream_mgmt
+
+
+
+
+
+ 2.0
+ 2.1.0
+ complete
+ mod_ping
+
+
+
+
+
+ 2.0
+ 2.1.0
+ complete
+ mod_time
+
+
+
+
+
+ 2.0
+ 2.1.0
+ complete
+ mod_offline
+
+
+
+
+
+ 1.0
+ 1.1.2
+ complete
+
+
+
+
+
+
+ 1.4
+ 16.12
+ complete
+ ejabberd_bosh
+
+
+
+
+
+ 0.7
+ 20.04
+ complete
+ mod_stun_disco
+
+
+
+
+
+ 1.1.1
+ 17.03
+ complete
+ mod_s2s_dialback
+
+
+
+
+
+ 1.1.1
+ 2.0.0
+ complete
+ mod_pubsub
+
+
+
+
+
+ 1.1
+ 2.1.0
+ partial
+ ejabberd_piefxis
+
+
+
+
+
+ 1.0
+ 2.1.0
+ complete
+ ejabberd_captcha
+
+
+
+
+
+ 1.3
+ 2.1.0
+ complete
+ mod_roster
+
+
+
+
+
+ 0.2
+ 2.1.0
+ complete
+ mod_pubsub
+
+
+
+
+
+ 1.2
+ 0.5.0
+ complete
+ mod_muc
+
+
+
+
+
+ 0.2
+ 2.1.3
+ complete
+ mod_sic
+
+
+
+
+
+ 1.0.1
+ 13.06
+ complete
+ mod_carboncopy
+
+
+
+
+
+ 1.0.1
+ 24.10
+ complete
+ mod_s2s_bidi
+
+
+
+
+
+ 0.6.1
+ 15.06
+ complete
+ mod_mam
+
+
+
+
+
+ 0.3.1
+ 21.12
+ complete
+ mod_muc_room, 0.3.1 since 25.xx
+
+
+
+
+
+ 0.1
+ 19.09
+ complete
+ mod_jidprep
+
+
+
+
+
+ 0.2
+ 16.01
+ complete
+ mod_mam, mod_muc_log, mod_offline
+
+
+
+
+
+ 0.1
+ 14.12
+ complete
+ mod_client_state
+
+
+
+
+
+ 0.4.1
+ 16.09
+ complete
+ mod_delegation
+
+
+
+
+
+ 0.4.1
+ 24.10
+ complete
+ mod_privilege
+
+
+
+
+
+ 0.2
+ 17.08
+ complete
+ mod_push
+
+
+
+
+
+ 0.5.0
+ 15.09
+ complete
+ mod_mam
+
+
+
+
+
+ 0.3.0
+ 15.10
+ complete
+ mod_http_upload
+
+
+
+
+
+ 1.1.0
+ 17.09
+ complete
+
+
+
+
+
+
+ 0.14.1
+ 16.03
+ complete
+ mod_mix
+
+
+
+
+
+ 0.8.3
+ 21.12
+ complete
+ node_pep
+
+
+
+
+
+ 0.3.0
+ 24.02
+ complete
+
+
+
+
+
+
+ 0.4.0
+ 24.02
+ complete
+
+
+
+
+
+
+ 0.2.0
+ 18.03
+ complete
+ mod_avatar
+
+
+
+
+
+ 1.1.3
+ 23.10
+ complete
+ mod_private
+
+
+
+
+
+ 0.3.0
+ 19.02
+ complete
+ mod_mix_pam
+
+
+
+
+
+ 1.1.0
+ 18.12
+ complete
+ mod_muc_room
+
+
+
+
+
+ 0.2.0
+ 18.12
+ complete
+ mod_private
+
+
+
+
+
+ 0.1.0
+ 23.10
+ complete
+ mod_muc_occupantid
+
+
+
+
+
+ 0.4.2
+ 24.02
+ partial
+ mod_mam, Tombstones not implemented
+
+
+
+
+
+ 0.3.0
+ 24.06
+ complete
+ mod_mam
+
+
+
+
+
+ 0.2.0
+ 24.12
+ complete
+ mod_mam
+
+
+
+
+
+ 0.4.0
+ 24.02
+ complete
+
+
+
+
+
+
+ 0.2.0
+ 15.06
+ complete
+ mod_mam
+
+
+
+
+
+ 0.4.0
+ 24.02
+ complete
+ , 0.4.0 since 25.03
+
+
+
+
+
+ 0.2.0
+ 24.10
+ complete
+ mod_scram_upgrade
+
+
+
+
+
+ 0.2.0
+ 24.12
+ complete
+ mod_auth_fast
+
+
+
+
+
+ 0.1.1
+ 25.07
+ complete
+ mod_pubsub_serverinfo
+
+
+
+
+
+ 0.1.0
+ 24.07
+ complete
+ mod_muc
+
+
+
+
diff --git a/ejabberd.service.template b/ejabberd.service.template
index 685a104d0..902a81cb2 100644
--- a/ejabberd.service.template
+++ b/ejabberd.service.template
@@ -9,7 +9,6 @@ Group=@installuser@
LimitNOFILE=65536
Restart=on-failure
RestartSec=5
-WatchdogSec=30
ExecStart=@ctlscriptpath@/ejabberdctl foreground
ExecStop=/bin/sh -c '@ctlscriptpath@/ejabberdctl stop && @ctlscriptpath@/ejabberdctl stopped'
ExecReload=@ctlscriptpath@/ejabberdctl reload_config
diff --git a/ejabberd.yml.example b/ejabberd.yml.example
index 8eb038dd0..b9df7799b 100644
--- a/ejabberd.yml.example
+++ b/ejabberd.yml.example
@@ -36,17 +36,17 @@ listen:
-
port: 5223
ip: "::"
- tls: true
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
- starttls_required: true
+ tls: true
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
+ shaper: s2s_shaper
-
port: 5443
ip: "::"
@@ -67,7 +67,7 @@ listen:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
-
- port: 3478
+ port: 5478
ip: "::"
transport: udp
module: ejabberd_stun
@@ -111,11 +111,19 @@ access_rules:
api_permissions:
"console commands":
- from:
- - ejabberd_ctl
+ from: ejabberd_ctl
who: all
what: "*"
- "admin access":
+ "webadmin commands":
+ from: ejabberd_web_admin
+ who: admin
+ what: "*"
+ "adhoc commands":
+ from: mod_adhoc_api
+ who: admin
+ what: "*"
+ "http access":
+ from: mod_http_api
who:
access:
allow:
@@ -156,6 +164,7 @@ shaper_rules:
modules:
mod_adhoc: {}
+ mod_adhoc_api: {}
mod_admin_extra: {}
mod_announce:
access: announce
@@ -170,7 +179,7 @@ modules:
mod_fail2ban: {}
mod_http_api: {}
mod_http_upload:
- put_url: https://@HOST@:5443/upload
+ put_url: https://@HOST_URL_ENCODE@:5443/upload
custom_headers:
"Access-Control-Allow-Origin": "https://@HOST@"
"Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
@@ -196,6 +205,7 @@ modules:
default_room_options:
mam: true
mod_muc_admin: {}
+ mod_muc_occupantid: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
@@ -224,6 +234,7 @@ modules:
ip_access: trusted_network
mod_roster:
versioning: true
+ mod_s2s_bidi: {}
mod_s2s_dialback: {}
mod_shared_roster: {}
mod_stream_mgmt:
diff --git a/ejabberdctl.cfg.example b/ejabberdctl.cfg.example
index 8b15933db..88f99cd78 100644
--- a/ejabberdctl.cfg.example
+++ b/ejabberdctl.cfg.example
@@ -108,10 +108,11 @@
#.
#' ERL_OPTIONS: Additional Erlang options
#
-# The next variable allows to specify additional options passed to erlang while
-# starting ejabberd. Some useful options are -noshell, -detached, -heart. When
-# ejabberd is started from an init.d script options -noshell and -detached are
-# added implicitly. See erl(1) for more info.
+# The next variable allows to specify additional options passed to
+# all commands using erlang interpreter. This applies to starting
+# ejabberd server itself but also auxiliary commands like for example
+# starting debug shell. See erl(1) for list of commands that can be
+# used here.
#
# It might be useful to add "-pa /usr/local/lib/ejabberd/ebin" if you
# want to add local modules in this path.
@@ -120,6 +121,20 @@
#
#ERL_OPTIONS=""
+#.
+#' EJABBERD_OPTS: Additional Erlang options to start ejabberd
+#
+# The next variable allows to specify additional options passed to erlang while
+# starting ejabberd. Some useful options are -noshell, -detached, -heart. When
+# ejabberd is started from an init.d script options -noshell and -detached are
+# added implicitly. See erl(1) for more info.
+#
+# For example you can use value "-heart -env HEART_BEAT_TIMEOUT 120 -env ERL_CRASH_DUMP_SECONDS 60"
+#
+# Default: ""
+#
+#EJABBERD_OPTS=""
+
#.
#' ERLANG_NODE: Erlang node name
#
@@ -183,6 +198,17 @@
#
#CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules
+#.
+#' CTL_OVER_HTTP: Path to ejabberdctl HTTP listener socket
+#
+# To speedup ejabberdctl execution time for ejabberd commands,
+# you can setup an ejabberd_http listener with ejabberd_ctl handling requests,
+# listening in a unix domain socket.
+#
+# Default: disabled
+#
+#CTL_OVER_HTTP=sockets/ctl_over_http.sock
+
#.
#'
# vim: foldmarker=#',#. foldmethod=marker:
diff --git a/ejabberdctl.template b/ejabberdctl.template
index 758a85bca..0d124bead 100755
--- a/ejabberdctl.template
+++ b/ejabberdctl.template
@@ -15,8 +15,8 @@ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd -P)"
# shellcheck disable=SC2034
ERTS_VSN="{{erts_vsn}}"
ERL="{{erl}}"
-IEX="{{bindir}}/iex"
EPMD="{{epmd}}"
+IEX="{{iexpath}}"
INSTALLUSER="{{installuser}}"
# check the proper system user is used
@@ -66,18 +66,26 @@ done
# shellcheck source=ejabberdctl.cfg.example
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH"
[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG"
+[ "$ERLANG_NODE" = "${ERLANG_NODE%@*}" ] && ERLANG_NODE="$ERLANG_NODE@$(hostname -s)"
[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s"
: "${SPOOL_DIR:="{{spool_dir}}"}"
: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}"
+# backward support for old mnesia spool dir path
+: "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}"
+[ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD"
+
# define erl parameters
ERLANG_OPTS="+K $POLL +P $ERL_PROCESSES $ERL_OPTIONS"
if [ -n "$FIREWALL_WINDOW" ] ; then
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}"
fi
if [ -n "$INET_DIST_INTERFACE" ] ; then
- INET_DIST_INTERFACE2=$("$ERL" -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
+ INET_DIST_INTERFACE2=$("$ERL" $ERLANG_OPTS -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt)
if [ -n "$INET_DIST_INTERFACE2" ] ; then
+ if [ "$(echo "$INET_DIST_INTERFACE2" | grep -o "," | wc -l)" -eq 7 ] ; then
+ INET_DIST_INTERFACE2="$INET_DIST_INTERFACE2 -proto_dist inet6_tcp"
+ fi
ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2"
fi
fi
@@ -89,11 +97,12 @@ ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump
ERL_INETRC="$CONFIG_DIR"/inetrc
# define ejabberd parameters
-EJABBERD_OPTS="$EJABBERD_OPTS\
-$(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]\{1,\}\).*/ \1/;s/:[ \t]*\(infinity\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
-$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
-$(sed '/^log_burst_limit_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\
-$(sed '/^log_burst_limit_window_time/!d;s/:[ \t]*\([0-9]*[a-z]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")"
+EJABBERD_OPTS="\
+$(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]\{1,\}\).*/ \1/;s/:[ \t]*\(infinity\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\
+$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\
+$(sed '/^log_burst_limit_count/!d;s/:[ \t]*\([0-9]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\
+$(sed '/^log_burst_limit_window_time/!d;s/:[ \t]*\([0-9]*[a-z]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\
+$EJABBERD_OPTS"
[ -n "$EJABBERD_OPTS" ] && EJABBERD_OPTS="-ejabberd $EJABBERD_OPTS"
EJABBERD_OPTS="-mnesia dir \"$SPOOL_DIR\" $MNESIA_OPTIONS $EJABBERD_OPTS -s ejabberd"
@@ -121,7 +130,7 @@ set_dist_client()
exec_cmd()
{
case $EXEC_CMD in
- as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;;
+ as_install_user) su -s /bin/sh -c 'exec "$0" "$@"' "$INSTALLUSER" -- "$@" ;;
as_current_user) "$@" ;;
esac
}
@@ -149,9 +158,11 @@ debugwarning()
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
- echo "To detach this shell from ejabberd, press:"
- echo " control+c, control+c"
+ echo "To exit and detach this shell from ejabberd, press:"
+ echo " control+g and then q"
echo ""
+ #vt100 echo "Please do NOT use control+c in this debug shell !"
+ #vt100 echo ""
echo "--------------------------------------------------------------------"
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
echo " EJABBERD_BYPASS_WARNINGS=true"
@@ -172,8 +183,10 @@ livewarning()
echo "Please be extremely cautious with your actions,"
echo "and exit immediately if you are not completely sure."
echo ""
- echo "To exit this LIVE mode and stop ejabberd, press:"
- echo " q(). and press the Enter key"
+ echo "To stop ejabberd gracefully:"
+ echo " ejabberd:stop()."
+ echo "To quit erlang immediately, press:"
+ echo " control+g and then q"
echo ""
echo "--------------------------------------------------------------------"
echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:"
@@ -184,6 +197,39 @@ livewarning()
fi
}
+check_etop_result()
+{
+ result=$?
+ if [ $result -eq 1 ] ; then
+ echo ""
+ echo "It seems there was some problem running 'ejabberdctl etop'."
+ echo "Is the error message something like this?"
+ echo " Failed to load module 'etop' because it cannot be found..."
+ echo "Then probably ejabberd was compiled with development tools disabled."
+ echo "To use 'etop', recompile ejabberd with: ./configure --enable-tools"
+ echo ""
+ exit $result
+ fi
+}
+
+check_iex_result()
+{
+ result=$?
+ if [ $result -eq 127 ] ; then
+ echo ""
+ echo "It seems there was some problem finding 'iex' binary from Elixir."
+ echo "Probably ejabberd was compiled with Rebar3 and Elixir disabled, like:"
+ echo " ./configure"
+ echo "which is equivalent to:"
+ echo " ./configure --with-rebar=rebar3 --disable-elixir"
+ echo "To use 'iex', recompile ejabberd enabling Elixir or using Mix:"
+ echo " ./configure --enable-elixir"
+ echo " ./configure --with-rebar=mix"
+ echo ""
+ exit $result
+ fi
+}
+
help()
{
echo ""
@@ -212,16 +258,34 @@ help()
}
# dynamic node name helper
-uid()
-{
- uuid=$(uuidgen 2>/dev/null)
- random=$(awk 'BEGIN { srand(); print int(rand()*32768) }' /dev/null)
- [ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid)
- [ -z "$uuid" ] && uuid=$(printf "%X" "${random:-$$}$(date +%M%S)")
- uuid=$(printf '%s' $uuid | sed 's/^\(...\).*$/\1/')
- [ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}"
- [ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}"
- [ $# -eq 2 ] && echo "${uuid}-${1}@${2}"
+uid() {
+ ERTSVERSION="$("$ERL" -version 2>&1 | sed 's|.* \([0-9]*[0-9]\).*|\1|g')"
+ if [ $ERTSVERSION -lt 11 ] ; then # otp 23.0 includes erts 11.0
+ # Erlang/OTP lower than 23, which doesn's support dynamic node code
+ N=1
+ PF=$(( $$ % 97 ))
+ while
+ case $# in
+ 0) NN="${PF}-${N}-${ERLANG_NODE}"
+ ;;
+ 1) NN="${PF}-${N}-${1}-${ERLANG_NODE}"
+ ;;
+ 2) NN="${PF}-${N}-${1}@${2}"
+ ;;
+ esac
+ N=$(( N + 1 + ( $$ % 5 ) ))
+ "$EPMD" -names 2>/dev/null | grep -q " ${NN%@*} "
+ do :; done
+ echo $NN
+ else
+ # Erlang/OTP 23 or higher: use native dynamic node code
+ # https://www.erlang.org/patches/otp-23.0#OTP-13812
+ if [ "$ERLANG_NODE" != "${ERLANG_NODE%.*}" ]; then
+ echo "undefined@${ERLANG_NODE#*@}"
+ else
+ echo "undefined"
+ fi
+ fi
}
# stop epmd if there is no other running node
@@ -254,6 +318,13 @@ check_start()
# allow sync calls
wait_status()
{
+ wait_status_node "$ERLANG_NODE" $1 $2 $3
+}
+
+wait_status_node()
+{
+ CONNECT_NODE=$1
+ shift
# args: status try delay
# return: 0 OK, 1 KO
timeout="$2"
@@ -264,14 +335,71 @@ wait_status()
if [ $timeout -eq 0 ] ; then
status="$1"
else
- exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
- -extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null
+ exec_erl "$(uid ctl)" -hidden -noinput \
+ -eval 'net_kernel:connect_node('"'$CONNECT_NODE'"')' \
+ -s ejabberd_ctl \
+ -extra "$CONNECT_NODE" $NO_TIMEOUT status > /dev/null
status="$?"
fi
done
[ $timeout -gt 0 ]
}
+exec_other_command()
+{
+ exec_other_command_node $ERLANG_NODE "$@"
+}
+
+exec_other_command_node()
+{
+ CONNECT_NODE=$1
+ shift
+ if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
+ || [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
+ || [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
+ exec_erl "$(uid ctl)" -hidden -noinput \
+ -eval 'net_kernel:connect_node('"'$CONNECT_NODE'"')' \
+ -s ejabberd_ctl \
+ -extra "$CONNECT_NODE" $NO_TIMEOUT "$@"
+ result=$?
+ case $result in
+ 3) help;;
+ *) :;;
+ esac
+ return $result
+ else
+ exec_ctl_over_http_socket "$@"
+ fi
+}
+
+exec_ctl_over_http_socket()
+{
+ COMMAND=${1}
+ CARGS=""
+ while [ $# -gt 0 ]; do
+ [ -z "$CARGS" ] && CARGS="[" || CARGS="${CARGS}, "
+ CARGS="${CARGS}\"$1\""
+ shift
+ done
+ CARGS="${CARGS}]"
+ TEMPHEADERS=temp-headers.log
+ curl \
+ --unix-socket ${CTL_OVER_HTTP} \
+ --header "Content-Type: application/json" \
+ --header "Accept: application/json" \
+ --data "${CARGS}" \
+ --dump-header ${TEMPHEADERS} \
+ --no-progress-meter \
+ "http://localhost/ctl/${COMMAND}"
+ result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
+ rm ${TEMPHEADERS}
+ case $result in
+ 2|3) exec_other_command help ${COMMAND};;
+ *) :;;
+ esac
+ exit $result
+}
+
# ensure we can change current directory to SPOOL_DIR
[ -d "$SPOOL_DIR" ] || exec_cmd mkdir -p "$SPOOL_DIR"
cd "$SPOOL_DIR" || {
@@ -279,6 +407,103 @@ cd "$SPOOL_DIR" || {
exit 6
}
+printe()
+{
+ printf "\n"
+ printf "\e[1;40;32m==> %s\e[0m\n" "$1"
+}
+
+## Function copied from tools/make-installers
+user_agrees()
+{
+ question="$*"
+
+ if [ -t 0 ]
+ then
+ printe "$question (y/n) [n]"
+ read -r response
+ case "$response" in
+ [Yy]|[Yy][Ee][Ss])
+ return 0
+ ;;
+ [Nn]|[Nn][Oo]|'')
+ return 1
+ ;;
+ *)
+ echo 'Please respond with "yes" or "no".'
+ user_agrees "$question"
+ ;;
+ esac
+ else # Assume 'yes' if not running interactively.
+ return 0
+ fi
+}
+
+mnesia_change()
+{
+ ERLANG_NODE_OLD="$1"
+ [ "$ERLANG_NODE_OLD" = "" ] \
+ && echo "Error: Please provide the old erlang node name, for example:" \
+ && echo " ejabberdctl mnesia_change ejabberd@oldmachine" \
+ && exit 1
+
+ SPOOL_DIR_BACKUP=$SPOOL_DIR/$ERLANG_NODE_OLD-backup/
+ OLDFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE_OLD.backup
+ NEWFILE=$SPOOL_DIR_BACKUP/$ERLANG_NODE.backup
+
+ printe "This changes your mnesia database from node name '$ERLANG_NODE_OLD' to '$ERLANG_NODE'"
+
+ [ -d "$SPOOL_DIR_BACKUP" ] && printe "WARNING! A backup of old node already exists in $SPOOL_DIR_BACKUP"
+
+ if ! user_agrees "Do you want to proceed?"
+ then
+ echo 'Operation aborted.'
+ exit 1
+ fi
+
+ printe "Starting ejabberd with old node name $ERLANG_NODE_OLD ..."
+ exec_erl "$ERLANG_NODE_OLD" $EJABBERD_OPTS -detached
+ wait_status_node $ERLANG_NODE_OLD 0 30 2
+ result=$?
+ case $result in
+ 1) echo "There was a problem starting ejabberd with the old erlang node name. " \
+ && echo "Check for log errors in $EJABBERD_LOG_PATH" \
+ && exit $result;;
+ *) :;;
+ esac
+ exec_other_command_node $ERLANG_NODE_OLD "status"
+
+ printe "Making backup of old database to file $OLDFILE ..."
+ mkdir $SPOOL_DIR_BACKUP
+ exec_other_command_node $ERLANG_NODE_OLD backup "$OLDFILE"
+
+ printe "Changing node name in new backup file $NEWFILE ..."
+ exec_other_command_node $ERLANG_NODE_OLD mnesia_change_nodename "$ERLANG_NODE_OLD" "$ERLANG_NODE" "$OLDFILE" "$NEWFILE"
+
+ printe "Stopping old ejabberd..."
+ exec_other_command_node $ERLANG_NODE_OLD "stop"
+ wait_status_node $ERLANG_NODE_OLD 3 30 2 && stop_epmd
+
+ printe "Moving old mnesia spool files to backup subdirectory $SPOOL_DIR_BACKUP ..."
+ mv $SPOOL_DIR/*.DAT $SPOOL_DIR_BACKUP
+ mv $SPOOL_DIR/*.DCD $SPOOL_DIR_BACKUP
+ mv $SPOOL_DIR/*.LOG $SPOOL_DIR_BACKUP
+
+ printe "Starting ejabberd with new node name $ERLANG_NODE ..."
+ exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached
+ wait_status 0 30 2
+ exec_other_command "status"
+
+ printe "Installing fallback of new mnesia..."
+ exec_other_command install_fallback "$NEWFILE"
+
+ printe "Stopping new ejabberd..."
+ exec_other_command "stop"
+ wait_status 3 30 2 && stop_epmd
+
+ printe "Finished, now you can start ejabberd normally"
+}
+
# main
case $1 in
start)
@@ -305,25 +530,31 @@ case $1 in
;;
etop)
set_dist_client
- exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \
- -s erlang halt -output text
+ exec_erl "$(uid top)" -hidden -remsh "$ERLANG_NODE" -s etop \
+ -output text
+ check_etop_result
;;
iexdebug)
debugwarning
set_dist_client
exec_iex "$(uid debug)" --remsh "$ERLANG_NODE"
+ check_iex_result
;;
iexlive)
livewarning
- exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd
+ exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS"
+ check_iex_result
;;
ping)
PEER=${2:-$ERLANG_NODE}
[ "$PEER" = "${PEER%.*}" ] && PS="-s"
set_dist_client
exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \
- -noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
- -s erlang halt -output text
+ -noinput -hidden \
+ -eval 'net_kernel:connect_node('"'$PEER'"')' \
+ -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \
+ -eval 'halt(case net_adm:ping('"'$PEER'"') of pong -> 0; pang -> 1 end).' \
+ -output text
;;
started)
set_dist_client
@@ -333,15 +564,11 @@ case $1 in
set_dist_client
wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout
;;
+ mnesia_change)
+ mnesia_change $2
+ ;;
*)
set_dist_client
- exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \
- -extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
- result=$?
- case $result in
- 2|3) help;;
- *) :;;
- esac
- exit $result
+ exec_other_command "$@"
;;
esac
diff --git a/elvis.config b/elvis.config
new file mode 100644
index 000000000..4ac4df9e1
--- /dev/null
+++ b/elvis.config
@@ -0,0 +1,59 @@
+[
+ {
+ elvis,
+ [
+ {config,
+ [#{dirs => ["src"],
+ filter => "*.erl",
+ ignore => ['ELDAPv3', eldap_filter_yecc],
+ ruleset => erl_files,
+ rules => [{elvis_text_style, line_length, #{limit => 1000, skip_comments => false}},
+ {elvis_text_style, no_tabs, disable},
+ {elvis_style, atom_naming_convention, disable},
+ {elvis_style, consistent_variable_casing, disable},
+ {elvis_style, dont_repeat_yourself, #{min_complexity => 70}},
+ {elvis_style, export_used_types, disable},
+ {elvis_style, function_naming_convention, disable},
+ {elvis_style, god_modules, #{limit => 300}},
+ {elvis_style, invalid_dynamic_call, disable},
+ {elvis_style, macro_names, disable},
+ {elvis_style, max_function_arity, disable}, % #{max_arity => 15}},
+ {elvis_style, nesting_level, disable},
+ {elvis_style, no_author, disable},
+ {elvis_style, no_boolean_in_comparison, disable},
+ {elvis_style, no_catch_expressions, disable},
+ {elvis_style, no_debug_call, disable},
+ {elvis_style, no_if_expression, disable},
+ {elvis_style, no_import, disable},
+ {elvis_style, no_nested_try_catch, disable},
+ {elvis_style, no_operation_on_same_value, disable},
+ {elvis_style, no_receive_without_timeout, disable},
+ {elvis_style, no_single_clause_case, disable},
+ {elvis_style, no_spec_with_records, disable},
+ {elvis_style, no_throw, disable},
+ {elvis_style, operator_spaces, disable},
+ {elvis_style, param_pattern_matching, disable},
+ {elvis_style, private_data_types, disable},
+ {elvis_style, variable_naming_convention, disable}
+ ]
+ },
+
+ %#{dirs => ["include"],
+ % filter => "*.hrl",
+ % ruleset => hrl_files},
+
+ #{dirs => ["."],
+ filter => "Makefile.in",
+ ruleset => makefiles,
+ rules => [{elvis_text_style, line_length, #{limit => 400,
+ skip_comments => false}},
+ {elvis_style, dont_repeat_yourself, #{min_complexity => 20}}
+ ]
+ }
+ ]
+ }
+ ]
+ }
+].
+
+%% vim: set filetype=erlang tabstop=8:
diff --git a/erlang_ls.config b/erlang_ls.config
new file mode 100644
index 000000000..83e3e52a5
--- /dev/null
+++ b/erlang_ls.config
@@ -0,0 +1,32 @@
+#otp_path: "/usr/lib/erlang"
+#plt_path: "_build/default/rebar3_24.3.3_plt"
+#code_reload:
+# node: ejabberd@localhost
+apps_dirs:
+ - "_build/default/lib/*"
+deps_dirs:
+ - "_build/default/lib/*"
+include_dirs:
+ - "_build/default/lib"
+ - "_build/default/lib/*/include"
+ - "include"
+macros:
+ - name: DEPRECATED_GET_STACKTRACE
+ - name: HAVE_ERL_ERROR
+ - name: HAVE_URI_STRING
+ - name: OTP_BELOW_27
+ - name: SIP
+ - name: STUN
+diagnostics:
+ enabled:
+ - crossref
+ disabled:
+# - dialyzer
+ - unused_includes # Otherwise it complains about unused logger.hrl
+lenses:
+ disabled:
+ - ct-run-test
+ - function-references
+ - server-info
+ - show-behaviour-usages
+ - suggest-spec
diff --git a/examples/extauth/check_pass_null.pl b/examples/extauth/check_pass_null.pl
deleted file mode 100755
index cbf179202..000000000
--- a/examples/extauth/check_pass_null.pl
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/perl
-
-use Unix::Syslog qw(:macros :subs);
-
-my $domain = $ARGV[0] || "example.com";
-
-while(1)
- {
- # my $rin = '',$rout;
- # vec($rin,fileno(STDIN),1) = 1;
- # $ein = $rin;
- # my $nfound = select($rout=$rin,undef,undef,undef);
-
- my $buf = "";
- syslog LOG_INFO,"waiting for packet";
- my $nread = sysread STDIN,$buf,2;
- do { syslog LOG_INFO,"port closed"; exit; } unless $nread == 2;
- my $len = unpack "n",$buf;
- my $nread = sysread STDIN,$buf,$len;
-
- my ($op,$user,$host,$password) = split /:/,$buf;
- #$user =~ s/\./\//og;
- my $jid = "$user\@$domain";
- my $result;
-
- syslog(LOG_INFO,"request (%s)", $op);
-
- SWITCH:
- {
- $op eq 'auth' and do
- {
- $result = 1;
- },last SWITCH;
-
- $op eq 'setpass' and do
- {
- $result = 1;
- },last SWITCH;
-
- $op eq 'isuser' and do
- {
- # password is null. Return 1 if the user $user\@$domain exitst.
- $result = 1;
- },last SWITCH;
-
- $op eq 'tryregister' and do
- {
- $result = 1;
- },last SWITCH;
-
- $op eq 'removeuser' and do
- {
- # password is null. Return 1 if the user $user\@$domain exitst.
- $result = 1;
- },last SWITCH;
-
- $op eq 'removeuser3' and do
- {
- $result = 1;
- },last SWITCH;
- };
- my $out = pack "nn",2,$result ? 1 : 0;
- syswrite STDOUT,$out;
- }
-
-closelog;
diff --git a/examples/mtr/ejabberd b/examples/mtr/ejabberd
deleted file mode 100644
index 4328b0697..000000000
--- a/examples/mtr/ejabberd
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/sh
-#
-# PROVIDE: ejabberd
-# REQUIRE: DAEMON
-# KEYWORD: shutdown
-#
-
-HOME=/usr/pkg/jabber D=/usr/pkg/jabber/ejabberd export HOME
-
-name="ejabberd"
-rcvar=$name
-
-if [ -r /etc/rc.conf ]
-then
- . /etc/rc.conf
-else
- eval ${rcvar}=YES
-fi
-
-# $flags from environment overrides ${rcvar}_flags
-if [ -n "${flags}" ]
-then
- eval ${rcvar}_flags="${flags}"
-fi
-
-checkyesno()
-{
- eval _value=\$${1}
- case $_value in
- [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0 ;;
- [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1 ;;
- *)
- echo "\$${1} is not set properly."
- return 1
- ;;
- esac
-}
-
-cmd=${1:-start}
-case ${cmd} in
-force*)
- cmd=${cmd#force}
- eval ${rcvar}=YES
- ;;
-esac
-
-if checkyesno ${rcvar}
-then
-else
- exit 0
-fi
-
-case ${cmd} in
-start)
- if [ -x $D/src ]; then
- echo "Starting ${name}."
- cd $D/src
- ERL_MAX_PORTS=32000 export ERL_MAX_PORTS
- ulimit -n $ERL_MAX_PORTS
- su jabber -c "/usr/pkg/bin/erl -sname ejabberd -s ejabberd -heart -detached -sasl sasl_error_logger '{file, \"ejabberd-sasl.log\"}' &" \
- 1>/dev/null 2>&1
- fi
- ;;
-stop)
- echo "rpc:call('ejabberd@`hostname -s`', init, stop, [])." | \
- su jabber -c "/usr/pkg/bin/erl -sname ejabberdstop"
- ;;
-restart)
- echo "rpc:call('ejabberd@`hostname -s`', init, restart, [])." | \
- su jabber -c "/usr/pkg/bin/erl -sname ejabberdrestart"
- ;;
-*)
- echo "Usage: $0 {start|stop|restart}"
- exit 1
-esac
diff --git a/examples/mtr/ejabberd-netbsd.sh b/examples/mtr/ejabberd-netbsd.sh
deleted file mode 100644
index 31d01b6b8..000000000
--- a/examples/mtr/ejabberd-netbsd.sh
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/bin/sh
-
-echo '1. fetch, compile, and install erlang'
-
-if [ ! pkg_info erlang 1>/dev/null 2>&1 ]; then
- cd /usr/pkgsrc/lang/erlang
- make fetch-list|sh
- make
- make install
-fi
-if pkg_info erlang | grep -q erlang-9.1nb1; then
-else
- echo "erlang-9.1nb1 not installed" 1>&2
- exit 1
-fi
-
-
-echo '2. install crypt_drv.so'
-
-if [ ! -d /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib ] ; then
- mkdir -p /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
-fi
-if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/crypto_drv.so ]; then
- cp work/otp*/lib/crypto/priv/*/*/crypto_drv.so \
- /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
-fi
-
-
-echo '3. compile and install elibcrypto.so'
-
-if [ ! -f /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib/elibcrypto.so ]; then
-cd /usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/crypto/c_src
-ld -r -u CRYPTO_set_mem_functions -u MD5 -u MD5_Init -u MD5_Update \
- -u MD5_Final -u SHA1 -u SHA1_Init -u SHA1_Update -u SHA1_Final \
- -u des_set_key -u des_ncbc_encrypt -u des_ede3_cbc_encrypt \
- -L/usr/lib -lcrypto -o ../priv/obj/i386--netbsdelf/elibcrypto.o
-cc -shared \
- -L/usr/pkgsrc/lang/erlang/work/otp_src_R9B-1/lib/erl_interface/obj/i386--netbsdelf \
- -o ../priv/obj/i386--netbsdelf/elibcrypto.so \
- ../priv/obj/i386--netbsdelf/elibcrypto.o -L/usr/lib -lcrypto
-cp ../priv/obj/i386--netbsdelf/elibcrypto.so \
- /usr/pkg/lib/erlang/lib/crypto-1.1.2.1/priv/lib
-fi
-
-
-echo '4. compile and install ssl_esock'
-
-if [ ! -f /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/bin/ssl_esock ]; then
- cd /usr/pkg/lib/erlang/lib/ssl-2.3.5/priv/obj/
- make
-fi
-
-
-echo '5. initial ejabberd configuration'
-
-cd /usr/pkg/jabber/ejabberd/src
-./configure
-
-
-echo '6. edit ejabberd Makefiles'
-
-for M in Makefile mod_*/Makefile; do
- if [ ! -f $M.orig ]; then
- mv $M $M.orig
- sed -e s%/usr/local%/usr/pkg%g < $M.orig > $M
- fi
-done
-
-
-echo '7. compile ejabberd'
-
-gmake
-for A in mod_muc mod_pubsub; do
- (cd $A; gmake)
-done
-
-
-echo ''
-echo 'now edit ejabberd.cfg'
-echo ''
-echo 'to start ejabberd: erl -sname ejabberd -s ejabberd'
diff --git a/examples/mtr/ejabberd.cfg b/examples/mtr/ejabberd.cfg
deleted file mode 100644
index b1023ee0e..000000000
--- a/examples/mtr/ejabberd.cfg
+++ /dev/null
@@ -1,65 +0,0 @@
-% jabber.dbc.mtview.ca.us
-
-override_acls.
-
-{acl, admin, {user, "mrose", "jabber.dbc.mtview.ca.us"}}.
-
-
-{access, announce, [{allow, admin},
- {deny, all}]}.
-{access, c2s, [{deny, blocked},
- {allow, all}]}.
-{access, c2s_shaper, [{none, admin},
- {normal, all}]}.
-{access, configure, [{allow, admin},
- {deny, all}]}.
-{access, disco_admin, [{allow, admin},
- {deny, all}]}.
-{access, muc_admin, [{allow, admin},
- {deny, all}]}.
-{access, register, [{deny, all}]}.
-{access, s2s_shaper, [{fast, all}]}.
-
-
-{auth_method, internal}.
-{host, "jabber.dbc.mtview.ca.us"}.
-{outgoing_s2s_port, 5269}.
-{shaper, normal, {maxrate, 1000}}.
-{shaper, fast, {maxrate, 50000}}.
-{welcome_message, none}.
-
-
-{listen, [{5222, ejabberd_c2s,
- [{access, c2s},
- {shaper, c2s_shaper}]},
- {5223, ejabberd_c2s,
- [{access, c2s},
- {shaper, c2s_shaper},
- {ssl, [{certfile, "/etc/openssl/certs/ejabberd.pem"}]}]},
- {5269, ejabberd_s2s_in,
- [{shaper, s2s_shaper}]}]}.
-
-
-{modules, [
- {mod_register, []},
- {mod_roster, []},
- {mod_privacy, []},
- {mod_configure, []},
- {mod_disco, []},
- {mod_stats, []},
- {mod_vcard, []},
- {mod_offline, []},
- {mod_echo, [{host, "echo.jabber.dbc.mtview.ca.us"}]},
- {mod_private, []},
- {mod_muc, []},
- {mod_pubsub, []},
- {mod_time, []},
- {mod_last, []},
- {mod_version, []}
- ]}.
-
-
-
-% Local Variables:
-% mode: erlang
-% End:
diff --git a/include/bosh.hrl b/include/bosh.hrl
index e02675ed0..dd9f1b6a1 100644
--- a/include/bosh.hrl
+++ b/include/bosh.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_auth.hrl b/include/ejabberd_auth.hrl
index a29b2cc29..bf7660d3f 100644
--- a/include/ejabberd_auth.hrl
+++ b/include/ejabberd_auth.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -18,5 +18,5 @@
%%%
%%%----------------------------------------------------------------------
--record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$1',
+-record(passwd, {us = {<<"">>, <<"">>} :: {binary(), binary()} | {binary(), binary(), atom()} | '$1',
password = <<"">> :: binary() | scram() | '_'}).
diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl
index 9009f7bb2..14d19d2e1 100644
--- a/include/ejabberd_commands.hrl
+++ b/include/ejabberd_commands.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -19,13 +19,30 @@
%%%----------------------------------------------------------------------
-type aterm() :: {atom(), atype()}.
--type atype() :: integer | string | binary |
+-type atype() :: integer | string | binary | any | atom |
{tuple, [aterm()]} | {list, aterm()}.
-type rterm() :: {atom(), rtype()}.
--type rtype() :: integer | string | atom |
+-type rtype() :: integer | string | atom | any |
{tuple, [rterm()]} | {list, rterm()} |
rescode | restuple.
+%% The 'any' and 'atom' argument types and 'any' result type
+%% should only be used %% by commands with tag 'internal',
+%% which are meant to be used only internally in ejabberd,
+%% and not called using external frontends.
+
+%% The purpose of a command can either be:
+%% - informative: its purpose is to obtain information
+%% - modifier: its purpose is to produce some change in the server
+%%
+%% A modifier command should be designed just to produce its desired side-effect,
+%% and its result term should just be success or failure: rescode or restuple.
+%%
+%% ejabberd_web_admin:make_command/2 considers that commands
+%% with result type different than rescode or restuple
+%% are commands that can be safely executed automatically
+%% to get information and build the web page.
+
-type oauth_scope() :: atom().
%% ejabberd_commands OAuth ReST ACL definition:
@@ -67,42 +84,24 @@
args_example = none :: none | [any()] | '_',
result_example = none :: any()}).
-%% TODO Fix me: Type is not up to date
--type ejabberd_commands() :: #ejabberd_commands{name :: atom(),
- tags :: [atom()],
- desc :: string(),
- longdesc :: string(),
- version :: integer(),
- module :: atom(),
- function :: atom(),
- args :: [aterm()],
- policy :: open | restricted | admin | user,
- access :: [{atom(),atom(),atom()}|atom()],
- result :: rterm()}.
+-type ejabberd_commands() :: #ejabberd_commands{name :: atom(),
+ tags :: [atom()],
+ desc :: string(),
+ longdesc :: string(),
+ version :: integer(),
+ note :: string(),
+ weight :: integer(),
+ module :: atom(),
+ function :: atom(),
+ args :: [aterm()],
+ policy :: open | restricted | admin | user,
+ access :: [{atom(),atom(),atom()}|atom()],
+ definer :: atom(),
+ result :: rterm(),
+ args_rename :: [{atom(),atom()}],
+ args_desc :: none | [string()] | '_',
+ result_desc :: none | string() | '_',
+ args_example :: none | [any()] | '_',
+ result_example :: any()
+ }.
-%% @type ejabberd_commands() = #ejabberd_commands{
-%% name = atom(),
-%% tags = [atom()],
-%% desc = string(),
-%% longdesc = string(),
-%% module = atom(),
-%% function = atom(),
-%% args = [aterm()],
-%% result = rterm()
-%% }.
-%% desc: Description of the command
-%% args: Describe the accepted arguments.
-%% This way the function that calls the command can format the
-%% arguments before calling.
-
-%% @type atype() = integer | string | {tuple, [aterm()]} | {list, aterm()}.
-%% Allowed types for arguments are integer, string, tuple and list.
-
-%% @type rtype() = integer | string | atom | {tuple, [rterm()]} | {list, rterm()} | rescode | restuple.
-%% A rtype is either an atom or a tuple with two elements.
-
-%% @type aterm() = {Name::atom(), Type::atype()}.
-%% An argument term is a tuple with the term name and the term type.
-
-%% @type rterm() = {Name::atom(), Type::rtype()}.
-%% A result term is a tuple with the term name and the term type.
diff --git a/include/ejabberd_ctl.hrl b/include/ejabberd_ctl.hrl
index 37935ebe2..cad82da89 100644
--- a/include/ejabberd_ctl.hrl
+++ b/include/ejabberd_ctl.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl
index 92dfd870e..9e1373ce6 100644
--- a/include/ejabberd_http.hrl
+++ b/include/ejabberd_http.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_oauth.hrl b/include/ejabberd_oauth.hrl
index 7e7509454..4798d9070 100644
--- a/include/ejabberd_oauth.hrl
+++ b/include/ejabberd_oauth.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_sm.hrl b/include/ejabberd_sm.hrl
index d5286d793..54a828e1a 100644
--- a/include/ejabberd_sm.hrl
+++ b/include/ejabberd_sm.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_sql.hrl b/include/ejabberd_sql.hrl
index cfa238b48..d0ab55cba 100644
--- a/include/ejabberd_sql.hrl
+++ b/include/ejabberd_sql.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -34,12 +34,14 @@
format_query :: fun(),
format_res :: fun(),
args :: fun(),
+ flags :: non_neg_integer(),
loc :: {module(), pos_integer()}}).
-else.
-record(sql_query, {hash :: binary(),
format_query :: fun(),
format_res :: fun(),
args :: fun(),
+ flags :: non_neg_integer(),
loc :: {module(), {pos_integer(), pos_integer()}}}).
-endif.
@@ -48,3 +50,26 @@
boolean :: fun((boolean()) -> binary()),
in_array_string :: fun((binary()) -> binary()),
like_escape :: fun(() -> binary())}).
+
+
+-record(sql_index, {columns,
+ unique = false :: boolean(),
+ meta = #{}}).
+-record(sql_column, {name :: binary(),
+ type,
+ default = false,
+ opts = []}).
+-record(sql_table, {name :: binary(),
+ columns :: [#sql_column{}],
+ indices = [] :: [#sql_index{}],
+ post_create}).
+-record(sql_schema, {version :: integer(),
+ tables :: [#sql_table{}],
+ update = []}).
+-record(sql_references, {table :: binary(),
+ column :: binary()}).
+
+-record(sql_schema_info,
+ {db_type :: pgsql | mysql | sqlite,
+ db_version :: any(),
+ new_schema = true :: boolean()}).
diff --git a/include/ejabberd_sql_pt.hrl b/include/ejabberd_sql_pt.hrl
index fd61bdd03..f89f5c969 100644
--- a/include/ejabberd_sql_pt.hrl
+++ b/include/ejabberd_sql_pt.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_web_admin.hrl b/include/ejabberd_web_admin.hrl
index 99f27f8de..45e4beada 100644
--- a/include/ejabberd_web_admin.hrl
+++ b/include/ejabberd_web_admin.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -62,6 +62,11 @@
[{<<"type">>, Type}, {<<"name">>, Name},
{<<"value">>, Value}])).
+-define(INPUTPH(Type, Name, Value, PlaceHolder),
+ ?XA(<<"input">>,
+ [{<<"type">>, Type}, {<<"name">>, Name},
+ {<<"value">>, Value}, {<<"placeholder">>, PlaceHolder}])).
+
-define(INPUTT(Type, Name, Value),
?INPUT(Type, Name, (translate:translate(Lang, Value)))).
@@ -95,16 +100,27 @@
-define(XRES(Text),
?XAC(<<"p">>, [{<<"class">>, <<"result">>}], Text)).
+-define(DIVRES(Elements),
+ ?XAE(<<"div">>, [{<<"class">>, <<"result">>}], Elements)).
+
%% Guide Link
-define(XREST(Text), ?XRES((translate:translate(Lang, Text)))).
-define(GL(Ref, Title),
?XAE(<<"div">>, [{<<"class">>, <<"guidelink">>}],
[?XAE(<<"a">>,
- [{<<"href">>, <<"https://docs.ejabberd.im/admin/configuration/", Ref/binary>>},
+ [{<<"href">>, <<"https://docs.ejabberd.im/", Ref/binary>>},
{<<"target">>, <<"_blank">>}],
[?C(<<"docs: ", Title/binary>>)])])).
%% h1 with a Guide Link
--define(H1GL(Name, Ref, Title),
- [?XC(<<"h1">>, Name), ?GL(Ref, Title)]).
+-define(H1GLraw(Name, Ref, Title),
+ [?XC(<<"h1">>, Name), ?GL(Ref, Title), ?BR, ?BR]).
+-define(H1GL(Name, RefConf, Title),
+ ?H1GLraw(Name, <<"admin/configuration/", RefConf/binary>>, Title)).
+
+-define(ANCHORL(Ref),
+ ?XAE(<<"div">>, [{<<"class">>, <<"anchorlink">>}],
+ [?XAE(<<"a">>,
+ [{<<"href">>, <<"#", Ref/binary>>}],
+ [?C(unicode:characters_to_binary("¶"))])])).
diff --git a/include/eldap.hrl b/include/eldap.hrl
index 0787d1f98..0b6dc97e5 100644
--- a/include/eldap.hrl
+++ b/include/eldap.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/http_bind.hrl b/include/http_bind.hrl
index 8a5ceb8ab..ab1294e7d 100644
--- a/include/http_bind.hrl
+++ b/include/http_bind.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/logger.hrl b/include/logger.hrl
index ed62f3607..e41ab73dd 100644
--- a/include/logger.hrl
+++ b/include/logger.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -39,20 +39,46 @@
-else.
-include_lib("kernel/include/logger.hrl").
+-define(CLEAD, "\e[1"). % bold
+-define(CMID, "\e[0"). % normal
+-define(CCLEAN, "\e[0m"). % clean
+
+-define(CDEFAULT, ";49;95m"). % light magenta
+-define(CDEBUG, ";49;90m"). % dark gray
+-define(CINFO, ";49;92m"). % green
+-define(CWARNING, ";49;93m"). % light yellow
+-define(CERROR, ";49;91m"). % light magenta
+-define(CCRITICAL,";49;31m"). % light red
+
-define(DEBUG(Format, Args),
- begin ?LOG_DEBUG(Format, Args), ok end).
+ begin ?LOG_DEBUG(Format, Args,
+ #{clevel => ?CLEAD ++ ?CDEBUG,
+ ctext => ?CMID ++ ?CDEBUG}),
+ ok end).
-define(INFO_MSG(Format, Args),
- begin ?LOG_INFO(Format, Args), ok end).
+ begin ?LOG_INFO(Format, Args,
+ #{clevel => ?CLEAD ++ ?CINFO,
+ ctext => ?CCLEAN}),
+ ok end).
-define(WARNING_MSG(Format, Args),
- begin ?LOG_WARNING(Format, Args), ok end).
+ begin ?LOG_WARNING(Format, Args,
+ #{clevel => ?CLEAD ++ ?CWARNING,
+ ctext => ?CMID ++ ?CWARNING}),
+ ok end).
-define(ERROR_MSG(Format, Args),
- begin ?LOG_ERROR(Format, Args), ok end).
+ begin ?LOG_ERROR(Format, Args,
+ #{clevel => ?CLEAD ++ ?CERROR,
+ ctext => ?CMID ++ ?CERROR}),
+ ok end).
-define(CRITICAL_MSG(Format, Args),
- begin ?LOG_CRITICAL(Format, Args), ok end).
+ begin ?LOG_CRITICAL(Format, Args,
+ #{clevel => ?CLEAD++ ?CCRITICAL,
+ ctext => ?CMID ++ ?CCRITICAL}),
+ ok end).
-endif.
%% Use only when trying to troubleshoot test problem with ExUnit
diff --git a/include/mod_announce.hrl b/include/mod_announce.hrl
index 498dce8d0..77badf90e 100644
--- a/include/mod_announce.hrl
+++ b/include/mod_announce.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/ejabberd_stacktrace.hrl b/include/mod_antispam.hrl
similarity index 59%
rename from include/ejabberd_stacktrace.hrl
rename to include/mod_antispam.hrl
index 2d8fc6e43..c30f24620 100644
--- a/include/ejabberd_stacktrace.hrl
+++ b/include/mod_antispam.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -18,10 +18,19 @@
%%%
%%%----------------------------------------------------------------------
--ifdef(DEPRECATED_GET_STACKTRACE).
--define(EX_RULE(Class, Reason, Stack), Class:Reason:Stack).
--define(EX_STACK(Stack), Stack).
--else.
--define(EX_RULE(Class, Reason, _), Class:Reason).
--define(EX_STACK(_), erlang:get_stacktrace()).
--endif.
+-define(MODULE_ANTISPAM, mod_antispam).
+
+-type url() :: binary().
+-type filename() :: binary() | none | false.
+-type jid_set() :: sets:set(ljid()).
+-type url_set() :: sets:set(url()).
+
+-define(DEFAULT_RTBL_DOMAINS_NODE, <<"spam_source_domains">>).
+
+-record(rtbl_service,
+ {host = none :: binary() | none,
+ node = ?DEFAULT_RTBL_DOMAINS_NODE :: binary(),
+ subscribed = false :: boolean(),
+ retry_timer = undefined :: reference() | undefined}).
+
+-type rtbl_service() :: #rtbl_service{}.
diff --git a/include/mod_caps.hrl b/include/mod_caps.hrl
index 4bf404837..ee1bbe44e 100644
--- a/include/mod_caps.hrl
+++ b/include/mod_caps.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_last.hrl b/include/mod_last.hrl
index aed9bdc6f..b1c13621a 100644
--- a/include/mod_last.hrl
+++ b/include/mod_last.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_mam.hrl b/include/mod_mam.hrl
index 27c892abe..77ea54a5e 100644
--- a/include/mod_mam.hrl
+++ b/include/mod_mam.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -26,7 +26,8 @@
bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid(),
packet = #xmlel{} :: xmlel() | message(),
nick = <<"">> :: binary(),
- type = chat :: chat | groupchat}).
+ type = chat :: chat | groupchat,
+ origin_id = <<"">> :: binary()}).
-record(archive_prefs,
{us = {<<"">>, <<"">>} :: {binary(), binary()},
diff --git a/include/mod_matrix_gw.hrl b/include/mod_matrix_gw.hrl
new file mode 100644
index 000000000..cdb272e8e
--- /dev/null
+++ b/include/mod_matrix_gw.hrl
@@ -0,0 +1,36 @@
+%%%----------------------------------------------------------------------
+%%%
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
+%%%
+%%% This program is free software; you can redistribute it and/or
+%%% modify it under the terms of the GNU General Public License as
+%%% published by the Free Software Foundation; either version 2 of the
+%%% License, or (at your option) any later version.
+%%%
+%%% This program is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%%% General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License along
+%%% with this program; if not, write to the Free Software Foundation, Inc.,
+%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+%%%
+%%%----------------------------------------------------------------------
+
+-record(room_version,
+ {id :: binary(),
+ %% use the same field names as in Synapse
+ enforce_key_validity :: boolean(),
+ special_case_aliases_auth :: boolean(),
+ strict_canonicaljson :: boolean(),
+ limit_notifications_power_levels :: boolean(),
+ knock_join_rule :: boolean(),
+ restricted_join_rule :: boolean(),
+ restricted_join_rule_fix :: boolean(),
+ knock_restricted_join_rule :: boolean(),
+ enforce_int_power_levels :: boolean(),
+ implicit_room_creator :: boolean(),
+ updated_redaction_rules :: boolean(),
+ hydra :: boolean()
+ }).
diff --git a/include/mod_muc.hrl b/include/mod_muc.hrl
index ea096c9fe..f801b29e1 100644
--- a/include/mod_muc.hrl
+++ b/include/mod_muc.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl
index 48d72b111..5f81fe026 100644
--- a/include/mod_muc_room.hrl
+++ b/include/mod_muc_room.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
@@ -38,13 +38,13 @@
description = <<"">> :: binary(),
allow_change_subj = true :: boolean(),
allow_query_users = true :: boolean(),
- allow_private_messages = true :: boolean(),
+ allowpm = anyone :: anyone | participants | moderators | none,
allow_private_messages_from_visitors = anyone :: anyone | moderators | nobody ,
allow_visitor_status = true :: boolean(),
allow_visitor_nickchange = true :: boolean(),
public = true :: boolean(),
public_list = true :: boolean(),
- persistent = false :: boolean(),
+ persistent = false :: boolean() | {destroying, boolean()},
moderated = true :: boolean(),
captcha_protected = false :: boolean(),
members_by_default = true :: boolean(),
@@ -125,8 +125,9 @@
roles = #{} :: roles(),
history = #lqueue{} :: lqueue(),
subject = [] :: [text()],
- subject_author = <<"">> :: binary(),
- hats_users = #{} :: map(), % FIXME on OTP 21+: #{ljid() => #{binary() => binary()}},
+ subject_author = {<<"">>, #jid{}} :: {binary(), jid()},
+ hats_defs = #{} :: #{binary() => {binary(), binary()}},
+ hats_users = #{} :: #{ljid() => [binary()]},
just_created = erlang:system_time(microsecond) :: true | integer(),
activity = treap:empty() :: treap:treap(),
room_shaper = none :: ejabberd_shaper:shaper(),
diff --git a/include/mod_offline.hrl b/include/mod_offline.hrl
index ba04f9b87..e1bb236f6 100644
--- a/include/mod_offline.hrl
+++ b/include/mod_offline.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_privacy.hrl b/include/mod_privacy.hrl
index 99cd2310d..8118a6de6 100644
--- a/include/mod_privacy.hrl
+++ b/include/mod_privacy.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_private.hrl b/include/mod_private.hrl
index 14e3bc8e3..05adc7d8b 100644
--- a/include/mod_private.hrl
+++ b/include/mod_private.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_proxy65.hrl b/include/mod_proxy65.hrl
index 13f4d8c6a..4f017124a 100644
--- a/include/mod_proxy65.hrl
+++ b/include/mod_proxy65.hrl
@@ -2,7 +2,7 @@
%%% RFC 1928 constants.
%%%
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_push.hrl b/include/mod_push.hrl
index 161b68bdf..8a9de102b 100644
--- a/include/mod_push.hrl
+++ b/include/mod_push.hrl
@@ -1,5 +1,5 @@
%%%----------------------------------------------------------------------
-%%% ejabberd, Copyright (C) 2017-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2017-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_roster.hrl b/include/mod_roster.hrl
index 6ec05b3da..a056dd22c 100644
--- a/include/mod_roster.hrl
+++ b/include/mod_roster.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_shared_roster.hrl b/include/mod_shared_roster.hrl
index a18d37414..4c35878e8 100644
--- a/include/mod_shared_roster.hrl
+++ b/include/mod_shared_roster.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mod_vcard.hrl b/include/mod_vcard.hrl
index 14f8380b8..d97e5c900 100644
--- a/include/mod_vcard.hrl
+++ b/include/mod_vcard.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/include/mqtt.hrl b/include/mqtt.hrl
index 6458a1234..bf910368f 100644
--- a/include/mqtt.hrl
+++ b/include/mqtt.hrl
@@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov
-%%% @copyright (C) 2002-2022 ProcessOne, SARL. All Rights Reserved.
+%%% @copyright (C) 2002-2025 ProcessOne, SARL. All Rights Reserved.
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
diff --git a/include/pubsub.hrl b/include/pubsub.hrl
index 1811aa926..316be342a 100644
--- a/include/pubsub.hrl
+++ b/include/pubsub.hrl
@@ -1,6 +1,6 @@
%%%----------------------------------------------------------------------
%%%
-%%% ejabberd, Copyright (C) 2002-2022 ProcessOne
+%%% ejabberd, Copyright (C) 2002-2025 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
diff --git a/install-sh b/install-sh
old mode 100644
new mode 100755
diff --git a/lib/ejabberd/config/attr.ex b/lib/ejabberd/config/attr.ex
index 9d17b157d..85d19191b 100644
--- a/lib/ejabberd/config/attr.ex
+++ b/lib/ejabberd/config/attr.ex
@@ -41,7 +41,7 @@ defmodule Ejabberd.Config.Attr do
"""
@spec validate([attr]) :: [{:ok, attr}] | [{:error, attr, atom()}]
def validate(attrs) when is_list(attrs), do: Enum.map(attrs, &valid_attr?/1)
- def validate(attr), do: validate([attr]) |> List.first
+ def validate(attr), do: validate([attr])
@doc """
Returns the type of an attribute, given its name.
diff --git a/lib/ejabberd/config/config.ex b/lib/ejabberd/config/config.ex
index a1b91858a..a8805e612 100644
--- a/lib/ejabberd/config/config.ex
+++ b/lib/ejabberd/config/config.ex
@@ -36,8 +36,8 @@ defmodule Ejabberd.Config do
case force do
true ->
- Ejabberd.Config.Store.stop
- Ejabberd.Config.Store.start_link
+ Ejabberd.Config.Store.stop()
+ Ejabberd.Config.Store.start_link()
do_init(file_path)
false ->
if not init_already_executed, do: do_init(file_path)
@@ -105,11 +105,8 @@ defmodule Ejabberd.Config do
Code.eval_file(file_path) |> extract_and_store_module_name()
# Getting start/0 config
- Ejabberd.Config.Store.get(:module_name)
- |> case do
- nil -> IO.puts "[ ERR ] Configuration module not found."
- [module] -> call_start_func_and_store_data(module)
- end
+ [module] = Ejabberd.Config.Store.get(:module_name)
+ call_start_func_and_store_data(module)
# Fetching git modules and install them
get_modules_parsed_in_order()
diff --git a/lib/ejabberd/config/ejabberd_hook.ex b/lib/ejabberd/config/ejabberd_hook.ex
index 8b7858d23..5f9de4aa0 100644
--- a/lib/ejabberd/config/ejabberd_hook.ex
+++ b/lib/ejabberd/config/ejabberd_hook.ex
@@ -13,7 +13,6 @@ defmodule Ejabberd.Config.EjabberdHook do
@doc """
Register a hook to ejabberd.
"""
- @spec start(EjabberdHook.t) :: none
def start(%EjabberdHook{hook: hook, opts: opts, fun: fun}) do
host = Keyword.get(opts, :host, :global)
priority = Keyword.get(opts, :priority, 50)
diff --git a/lib/ejabberd/config/ejabberd_module.ex b/lib/ejabberd/config/ejabberd_module.ex
index 6a74fe460..6d5b1e467 100644
--- a/lib/ejabberd/config/ejabberd_module.ex
+++ b/lib/ejabberd/config/ejabberd_module.ex
@@ -7,12 +7,13 @@ defmodule Ejabberd.Config.EjabberdModule do
the already existing Elixir.Module.
"""
- @type t :: %{module: atom, attrs: [Attr.t]}
-
- defstruct [:module, :attrs]
-
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validation
+ alias Ejabberd.Config.Attr
+
+ @type t :: %{module: atom, attrs: [Attr.attr]}
+
+ defstruct [:module, :attrs]
@doc """
Given a list of modules / single module
@@ -29,7 +30,6 @@ defmodule Ejabberd.Config.EjabberdModule do
a git attribute and tries to fetch the repo,
then, it install them through :ext_mod.install/1
"""
- @spec fetch_git_repos([EjabberdModule.t]) :: none()
def fetch_git_repos(modules) do
modules
|> Enum.filter(&is_git_module?/1)
@@ -60,7 +60,7 @@ defmodule Ejabberd.Config.EjabberdModule do
defp fetch_and_store_repo_source_if_not_exists(path, repo) do
unless File.exists?(path) do
IO.puts "[info] Fetching: #{repo}"
- :os.cmd('git clone #{repo} #{path}')
+ :os.cmd(~c"git clone #{repo} #{path}")
end
end
diff --git a/lib/ejabberd/config/logger/ejabberd_logger.ex b/lib/ejabberd/config/logger/ejabberd_logger.ex
index 90970ba73..822571916 100644
--- a/lib/ejabberd/config/logger/ejabberd_logger.ex
+++ b/lib/ejabberd/config/logger/ejabberd_logger.ex
@@ -17,9 +17,9 @@ defmodule Ejabberd.Config.EjabberdLogger do
end
defp do_log_errors({:ok, _mod}), do: nil
- defp do_log_errors({:error, _mod, errors}), do: Enum.each errors, &do_log_errors/1
- defp do_log_errors({:attribute, errors}), do: Enum.each errors, &log_attribute_error/1
- defp do_log_errors({:dependency, errors}), do: Enum.each errors, &log_dependency_error/1
+ defp do_log_errors({:error, _mod, errors}), do: (Enum.each errors, &do_log_errors/1)
+ defp do_log_errors({:attribute, errors}), do: (Enum.each errors, &log_attribute_error/1)
+ defp do_log_errors({:dependency, errors}), do: (Enum.each errors, &log_dependency_error/1)
defp log_attribute_error({{attr_name, _val}, :attr_not_supported}), do:
IO.puts "[ WARN ] Annotation @#{attr_name} is not supported."
diff --git a/lib/ejabberd/config/opts_formatter.ex b/lib/ejabberd/config/opts_formatter.ex
index b7010ddfe..3d3db926f 100644
--- a/lib/ejabberd/config/opts_formatter.ex
+++ b/lib/ejabberd/config/opts_formatter.ex
@@ -14,15 +14,12 @@ defmodule Ejabberd.Config.OptsFormatter do
Look at how Config.get_ejabberd_opts/0 is constructed for
more informations.
"""
- @spec format_opts_for_ejabberd([{atom(), any()}]) :: list()
+ @spec format_opts_for_ejabberd(map) :: list()
def format_opts_for_ejabberd(opts) do
opts
|> format_attrs_for_ejabberd
end
- defp format_attrs_for_ejabberd(opts) when is_list(opts),
- do: Enum.map opts, &format_attrs_for_ejabberd/1
-
defp format_attrs_for_ejabberd({:listeners, mods}),
do: {:listen, format_listeners_for_ejabberd(mods)}
@@ -32,6 +29,9 @@ defmodule Ejabberd.Config.OptsFormatter do
defp format_attrs_for_ejabberd({key, opts}) when is_atom(key),
do: {key, opts}
+ defp format_attrs_for_ejabberd(opts),
+ do: (Enum.map opts, &format_attrs_for_ejabberd/1)
+
defp format_mods_for_ejabberd(mods) do
Enum.map mods, fn %EjabberdModule{module: mod, attrs: attrs} ->
{mod, attrs[:opts]}
diff --git a/lib/ejabberd/config/validator/validation.ex b/lib/ejabberd/config/validator/validation.ex
index af582676e..227a3545f 100644
--- a/lib/ejabberd/config/validator/validation.ex
+++ b/lib/ejabberd/config/validator/validation.ex
@@ -3,12 +3,12 @@ defmodule Ejabberd.Config.Validation do
Module used to validate a list of modules.
"""
- @type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
- @type mod_validation_result :: {:ok, EjabberdModule.t} | {:error, EjabberdModule.t, map}
-
alias Ejabberd.Config.EjabberdModule
alias Ejabberd.Config.Validator
+ @type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
+ @type mod_validation_result :: {:ok, EjabberdModule.t} | {:error, EjabberdModule.t, map}
+
@doc """
Given a module or a list of modules it runs validators on them
and returns {:ok, mod} or {:error, mod, errors}, for each
diff --git a/lib/ejabberd/config/validator/validator_attrs.ex b/lib/ejabberd/config/validator/validator_attrs.ex
index 6a85c068d..e0e133b61 100644
--- a/lib/ejabberd/config/validator/validator_attrs.ex
+++ b/lib/ejabberd/config/validator/validator_attrs.ex
@@ -3,11 +3,12 @@ defmodule Ejabberd.Config.Validator.Attrs do
Validator module used to validate attributes.
"""
- # TODO: Duplicated from validator.ex !!!
- @type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
-
import Ejabberd.Config.ValidatorUtility
alias Ejabberd.Config.Attr
+ alias Ejabberd.Config.EjabberdModule
+
+ # TODO: Duplicated from validator.ex !!!
+ @type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
@doc """
Given a module (with the form used for validation)
@@ -17,9 +18,9 @@ defmodule Ejabberd.Config.Validator.Attrs do
@spec validate(mod_validation) :: mod_validation
def validate({modules, mod, errors}) do
errors = Enum.reduce mod.attrs, errors, fn(attr, err) ->
- case Attr.validate(attr) do
- {:ok, _attr} -> err
- {:error, attr, cause} -> put_error(err, :attribute, {attr, cause})
+ case Attr.validate([attr]) do
+ [{:ok, _attr}] -> err
+ [{:error, attr, cause}] -> put_error(err, :attribute, {attr, cause})
end
end
diff --git a/lib/ejabberd/config/validator/validator_dependencies.ex b/lib/ejabberd/config/validator/validator_dependencies.ex
index d44c8a136..4eb466663 100644
--- a/lib/ejabberd/config/validator/validator_dependencies.ex
+++ b/lib/ejabberd/config/validator/validator_dependencies.ex
@@ -4,6 +4,8 @@ defmodule Ejabberd.Config.Validator.Dependencies do
with the @dependency annotation.
"""
+ alias Ejabberd.Config.EjabberdModule
+
# TODO: Duplicated from validator.ex !!!
@type mod_validation :: {[EjabberdModule.t], EjabberdModule.t, map}
import Ejabberd.Config.ValidatorUtility
diff --git a/lib/ejabberd/config/validator/validator_utility.ex b/lib/ejabberd/config/validator/validator_utility.ex
index 17805f748..6047618b6 100644
--- a/lib/ejabberd/config/validator/validator_utility.ex
+++ b/lib/ejabberd/config/validator/validator_utility.ex
@@ -4,8 +4,6 @@ defmodule Ejabberd.Config.ValidatorUtility do
Imports utility functions for working with validation structures.
"""
- alias Ejabberd.Config.EjabberdModule
-
@doc """
Inserts an error inside the errors collection, for the given key.
If the key doesn't exists then it creates an empty collection
@@ -22,7 +20,6 @@ defmodule Ejabberd.Config.ValidatorUtility do
Given a list of modules it extracts and returns a list
of the module names (which are Elixir.Module).
"""
- @spec extract_module_names(EjabberdModule.t) :: [atom]
def extract_module_names(modules) when is_list(modules) do
modules
|> Enum.map(&Map.get(&1, :module))
diff --git a/lib/ejabberd/config_util.ex b/lib/ejabberd/config_util.ex
index 6592104a2..71d854f15 100644
--- a/lib/ejabberd/config_util.ex
+++ b/lib/ejabberd/config_util.ex
@@ -7,7 +7,7 @@ defmodule Ejabberd.ConfigUtil do
@doc """
Returns true when the config file is based on elixir.
"""
- @spec is_elixir_config(list) :: boolean
+ @spec is_elixir_config(binary) :: boolean
def is_elixir_config(filename) when is_list(filename) do
is_elixir_config(to_string(filename))
end
diff --git a/lib/ejabberd/module.ex b/lib/ejabberd/module.ex
deleted file mode 100644
index 9fb3f040c..000000000
--- a/lib/ejabberd/module.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule Ejabberd.Module do
-
- defmacro __using__(opts) do
- logger_enabled = Keyword.get(opts, :logger, true)
-
- quote do
- @behaviour :gen_mod
- import Ejabberd.Module
-
- unquote(if logger_enabled do
- quote do: import Ejabberd.Logger
- end)
- end
- end
-
- # gen_mod callbacks
- def depends(_host, _opts), do: []
- def mod_opt_type(_), do: []
-end
diff --git a/lib/ejabberd_auth_example.ex b/lib/ejabberd_auth_example.ex
new file mode 100644
index 000000000..5bc37e093
--- /dev/null
+++ b/lib/ejabberd_auth_example.ex
@@ -0,0 +1,44 @@
+defmodule Ejabberd.Auth.Example do
+
+ @moduledoc """
+ Example ejabberd auth method written in Elixir.
+
+ This is an example to demonstrate the usage of Elixir to
+ create ejabberd auth methods.
+
+ Example configuration:
+ auth_method: 'Ejabberd.Auth.Example'
+ """
+
+ @behaviour :ejabberd_auth
+ import Ejabberd.Logger
+
+ @impl true
+ def start(host) do
+ info("Starting Ejabberd.Auth.Example to authenticate '#{host}' users")
+ nil
+ end
+
+ @impl true
+ def stop(host) do
+ info("Stopping Ejabberd.Auth.Example to authenticate '#{host}' users")
+ nil
+ end
+
+ @impl true
+ def check_password("alice", _authz_id, _host, "secret"), do: {:nocache, true}
+ def check_password(_username, _authz_id, _host, _secret), do: {:nocache, false}
+
+ @impl true
+ def user_exists("alice", _host), do: {:nocache, true}
+ def user_exists(_username, _host), do: {:nocache, false}
+
+ @impl true
+ def plain_password_required(_binary), do: true
+
+ @impl true
+ def store_type(_host), do: :external
+
+ @impl true
+ def use_cache(_host), do: false
+end
diff --git a/lib/mix/tasks/deps.tree.ex b/lib/mix/tasks/deps.tree.ex
index a3439c40b..e93b4aa48 100644
--- a/lib/mix/tasks/deps.tree.ex
+++ b/lib/mix/tasks/deps.tree.ex
@@ -14,15 +14,15 @@ defmodule Mix.Tasks.Ejabberd.Deps.Tree do
def run(_argv) do
# First we need to start manually the store to be available
# during the compilation of the config file.
- Ejabberd.Config.Store.start_link
+ Ejabberd.Config.Store.start_link()
Ejabberd.Config.init(:ejabberd_config.path())
- Mix.shell.info "ejabberd modules"
+ Mix.shell().info "ejabberd modules"
Ejabberd.Config.Store.get(:modules)
|> Enum.reverse # Because of how mods are stored inside the store
|> format_mods
- |> Mix.shell.info
+ |> Mix.shell().info
end
defp format_mods(mods) when is_list(mods) do
diff --git a/lib/mod_example.ex b/lib/mod_example.ex
new file mode 100644
index 000000000..12166810a
--- /dev/null
+++ b/lib/mod_example.ex
@@ -0,0 +1,46 @@
+defmodule Ejabberd.Module.Example do
+
+ @moduledoc """
+ Example ejabberd module written in Elixir.
+
+ This is an example to demonstrate the usage of Elixir to
+ create ejabberd modules.
+
+ Example configuration:
+ modules:
+ 'Ejabberd.Module.Example': {}
+ """
+
+ @behaviour :gen_mod
+ import Ejabberd.Logger
+
+ def start(host, _opts) do
+ info("Starting Ejabberd.Module.Example for host '#{host}'")
+ Ejabberd.Hooks.add(:set_presence_hook, host, __MODULE__, :on_presence, 50)
+ :ok
+ end
+
+ def stop(host) do
+ info("Stopping Ejabberd.Module.Example for host '#{host}'")
+ Ejabberd.Hooks.delete(:set_presence_hook, host, __MODULE__, :on_presence, 50)
+ :ok
+ end
+
+ def on_presence(user, _server, _resource, _packet) do
+ info("Receive presence for #{user}")
+ :none
+ end
+
+ def depends(_host, _opts) do
+ []
+ end
+
+ def mod_options(_host) do
+ []
+ end
+
+ def mod_doc() do
+ %{:desc => "This is just a demonstration."}
+ end
+
+end
diff --git a/lib/mod_presence_demo.ex b/lib/mod_presence_demo.ex
deleted file mode 100644
index f41a53a31..000000000
--- a/lib/mod_presence_demo.ex
+++ /dev/null
@@ -1,33 +0,0 @@
-defmodule ModPresenceDemo do
- use Ejabberd.Module
-
- def start(host, _opts) do
- info('Starting ejabberd module Presence Demo')
- Ejabberd.Hooks.add(:set_presence_hook, host, __MODULE__, :on_presence, 50)
- :ok
- end
-
- def stop(host) do
- info('Stopping ejabberd module Presence Demo')
- Ejabberd.Hooks.delete(:set_presence_hook, host, __MODULE__, :on_presence, 50)
- :ok
- end
-
- def on_presence(user, _server, _resource, _packet) do
- info('Receive presence for #{user}')
- :none
- end
-
- def depends(_host, _opts) do
- []
- end
-
- def mod_options(_host) do
- []
- end
-
- def mod_doc() do
- %{:desc => 'This is just a demonstration.'}
- end
-
-end
diff --git a/m4/erlang-extra.m4 b/m4/erlang-extra.m4
index 4a7311bad..95c4b138d 100644
--- a/m4/erlang-extra.m4
+++ b/m4/erlang-extra.m4
@@ -75,7 +75,7 @@ EOF
if test "x`cat conftest.out`" != "xok"; then
AC_MSG_RESULT([failed])
X="`cat conftest.out`"
- if test "[$3]" == "warn"; then
+ if test "[$3]" = "warn"; then
AC_MSG_WARN([$X])
else
AC_MSG_FAILURE([$X])
diff --git a/man/ejabberd.yml.5 b/man/ejabberd.yml.5
index a14a5c730..aa42e20b2 100644
--- a/man/ejabberd.yml.5
+++ b/man/ejabberd.yml.5
@@ -2,12 +2,12 @@
.\" Title: ejabberd.yml
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot
-.\" Date: 10/12/2022
+.\" Date: 08/22/2025
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "EJABBERD\&.YML" "5" "10/12/2022" "\ \&" "\ \&"
+.TH "EJABBERD\&.YML" "5" "08/22/2025" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -82,17 +82,17 @@ All options can be changed in runtime by running \fIejabberdctl reload\-config\f
.sp
Some options can be specified for particular virtual host(s) only using \fIhost_config\fR or \fIappend_host_config\fR options\&. Such options are called \fIlocal\fR\&. Examples are \fImodules\fR, \fIauth_method\fR and \fIdefault_db\fR\&. The options that cannot be defined per virtual host are called \fIglobal\fR\&. Examples are \fIloglevel\fR, \fIcertfiles\fR and \fIlisten\fR\&. It is a configuration mistake to put \fIglobal\fR options under \fIhost_config\fR or \fIappend_host_config\fR section \- ejabberd will refuse to load such configuration\&.
.sp
-It is not recommended to write ejabberd\&.yml from scratch\&. Instead it is better to start from "default" configuration file available at https://github\&.com/processone/ejabberd/blob/22\&.10/ejabberd\&.yml\&.example\&. Once you get ejabberd running you can start changing configuration options to meet your requirements\&.
+It is not recommended to write ejabberd\&.yml from scratch\&. Instead it is better to start from "default" configuration file available at https://github\&.com/processone/ejabberd/blob/25\&.08/ejabberd\&.yml\&.example\&. Once you get ejabberd running you can start changing configuration options to meet your requirements\&.
.sp
Note that this document is intended to provide comprehensive description of all configuration options that can be consulted to understand the meaning of a particular option, its format and possible values\&. It will be quite hard to understand how to configure ejabberd by reading this document only \- for this purpose the reader is recommended to read online Configuration Guide available at https://docs\&.ejabberd\&.im/admin/configuration\&.
.SH "TOP LEVEL OPTIONS"
.sp
-This section describes top level options of ejabberd\&.
+This section describes top level options of ejabberd 25\&.08\&. The options that changed in this version are marked with 🟤\&.
.PP
-\fBaccess_rules\fR: \fI{AccessName: {allow|deny: ACLRules|ACLName}}\fR
+\fBaccess_rules\fR: \fI{AccessName: {allow|deny: ACLName|ACLDefinition}}\fR
.RS 4
This option defines
-Access Rules\&. Each access rule is assigned a name that can be referenced from other parts of the configuration file (mostly from
+\fIbasic\&.md#access\-rules|Access Rules\fR\&. Each access rule is assigned a name that can be referenced from other parts of the configuration file (mostly from
\fIaccess\fR
options of ejabberd modules)\&. Each rule definition may contain arbitrary number of
\fIallow\fR
@@ -138,7 +138,8 @@ access_rules:
.PP
\fBacl\fR: \fI{ACLName: {ACLType: ACLValue}}\fR
.RS 4
-The option defines access control lists: named sets of rules which are used to match against different targets (such as a JID or an IP address)\&. Every set of rules has name
+This option defines
+\fI\&.\&./configuration/basic\&.md#acl|access control lists\fR: named sets of rules which are used to match against different targets (such as a JID or an IP address)\&. Every set of rules has name
\fIACLName\fR: it can be any string except
\fIall\fR
or
@@ -247,7 +248,7 @@ is in the form of "regexp", the rule matches any JID with node part matching reg
.PP
\fBacme\fR: \fIOptions\fR
.RS 4
-ACME
+\fIbasic\&.md#acme|ACME\fR
configuration, to automatically obtain SSL certificates for the domains served by ejabberd, which means that certificate requests and renewals are performed to some CA server (aka "ACME server") in a fully automated mode\&. The
\fIOptions\fR
are:
@@ -303,7 +304,9 @@ acme:
.PP
\fBallow_contrib_modules\fR: \fItrue | false\fR
.RS 4
-Whether to allow installation of third\-party modules or not\&. The default value is
+Whether to allow installation of third\-party modules or not\&. See
+\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
+documentation section\&. The default value is
\fItrue\fR\&.
.RE
.PP
@@ -317,7 +320,9 @@ means that the same username can be taken multiple times in anonymous login mode
.PP
\fBanonymous_protocol\fR: \fIlogin_anon | sasl_anon | both\fR
.RS 4
-Define what anonymous protocol will be used:
+Define what
+\fIauthentication\&.md#anonymous\-login\-and\-sasl\-anonymous|anonymous\fR
+protocol will be used:
.sp
.RS 4
.ie n \{\
@@ -361,16 +366,13 @@ The default value is \fIsasl_anon\fR\&.
\fBapi_permissions\fR: \fI[Permission, \&.\&.\&.]\fR
.RS 4
Define the permissions for API access\&. Please consult the ejabberd Docs web → For Developers → ejabberd ReST API →
-API Permissions\&.
+\fI\&.\&./\&.\&./developer/ejabberd\-api/permissions\&.md|API Permissions\fR\&.
.RE
.PP
\fBappend_host_config\fR: \fI{Host: Options}\fR
.RS 4
-To define specific ejabberd modules in a virtual host, you can define the global
-\fImodules\fR
-option with the common modules, and later add specific modules to certain virtual hosts\&. To accomplish that,
-\fIappend_host_config\fR
-option can be used\&.
+Add a few specific options to a certain
+\fI\&.\&./configuration/basic\&.md#virtual\-hosting|virtual host\fR\&.
.RE
.PP
\fBauth_cache_life_time\fR: \fItimeout()\fR
@@ -397,9 +399,22 @@ Same as
will be used\&.
.RE
.PP
+\fBauth_external_user_exists_check\fR: \fItrue | false\fR
+.RS 4
+\fINote\fR
+about this option: added in 23\&.10\&. Supplement check for user existence based on
+\fImod_last\fR
+data, for authentication methods that don\(cqt have a way to reliably tell if a user exists (like is the case for
+\fIjwt\fR
+and certificate based authentication)\&. This helps with processing offline message for those users\&. The default value is
+\fItrue\fR\&.
+.RE
+.PP
\fBauth_method\fR: \fI[mnesia | sql | anonymous | external | jwt | ldap | pam, \&.\&.\&.]\fR
.RS 4
-A list of authentication methods to use\&. If several methods are defined, authentication is considered successful as long as authentication of at least one of the methods succeeds\&. The default value is
+A list of
+\fIauthentication\&.md|authentication\fR
+methods to use\&. If several methods are defined, authentication is considered successful as long as authentication of at least one of the methods succeeds\&. The default value is
\fI[mnesia]\fR\&.
.RE
.PP
@@ -408,15 +423,16 @@ A list of authentication methods to use\&. If several methods are defined, authe
This is used by the contributed module
\fIejabberd_auth_http\fR
that can be installed from the
-ejabberd\-contrib
+\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
Git repository\&. Please refer to that module\(cqs README file for details\&.
.RE
-.sp
-\fINote\fR about the next option: improved in 20\&.01:
.PP
\fBauth_password_format\fR: \fIplain | scram\fR
.RS 4
-The option defines in what format the users passwords are stored:
+\fINote\fR
+about this option: improved in 20\&.01\&. The option defines in what format the users passwords are stored, plain text or in
+\fIauthentication\&.md#scram|SCRAM\fR
+format:
.sp
.RS 4
.ie n \{\
@@ -426,7 +442,7 @@ The option defines in what format the users passwords are stored:
.sp -1
.IP \(bu 2.3
.\}
-\fIplain\fR: The password is stored as plain text in the database\&. This is risky because the passwords can be read if your database gets compromised\&. This is the default value\&. This format allows clients to authenticate using: the old Jabber Non\-SASL (XEP\-0078), SASL PLAIN, SASL DIGEST\-MD5, and SASL SCRAM\-SHA\-1\&.
+\fIplain\fR: The password is stored as plain text in the database\&. This is risky because the passwords can be read if your database gets compromised\&. This is the default value\&. This format allows clients to authenticate using: the old Jabber Non\-SASL (XEP\-0078), SASL PLAIN, SASL DIGEST\-MD5, and SASL SCRAM\-SHA\-1/256/512(\-PLUS)\&.
.RE
.sp
.RS 4
@@ -437,17 +453,39 @@ The option defines in what format the users passwords are stored:
.sp -1
.IP \(bu 2.3
.\}
-\fIscram\fR: The password is not stored, only some information that allows to verify the hash provided by the client\&. It is impossible to obtain the original plain password from the stored information; for this reason, when this value is configured it cannot be changed to plain anymore\&. This format allows clients to authenticate using: SASL PLAIN and SASL SCRAM\-SHA\-1\&. The default value is
-\fIplain\fR\&.
+\fIscram\fR: The password is not stored, only some information required to verify the hash provided by the client\&. It is impossible to obtain the original plain password from the stored information; for this reason, when this value is configured it cannot be changed to plain anymore\&. This format allows clients to authenticate using: SASL PLAIN and SASL SCRAM\-SHA\-1/256/512(\-PLUS)\&. The SCRAM variant depends on the
+\fIauth_scram_hash\fR
+option\&.
.RE
.RE
+.sp
+The default value is \fIplain\fR\&.
+.PP
+\fBauth_password_types_hidden_in_sasl1\fR: \fI[plain | scram_sha1 | scram_sha256 | scram_sha512]\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. List of password types that should not be offered in SASL1 authenticatication\&. Because SASL1, unlike SASL2, can\(cqt have list of available mechanisms tailored to individual user, it\(cqs possible that offered mechanisms will not be compatible with stored password, especially if new password type was added recently\&. This option allows disabling offering some mechanisms in SASL1, to a time until new password type will be available for all users\&.
+.RE
.PP
\fBauth_scram_hash\fR: \fIsha | sha256 | sha512\fR
.RS 4
-Hash algorithm that should be used to store password in SCRAM format\&. You shouldn\(cqt change this if you already have passwords generated with a different algorithm \- users that have such passwords will not be able to authenticate\&. The default value is
+Hash algorithm that should be used to store password in
+\fIauthentication\&.md#scram|SCRAM\fR
+format\&. You shouldn\(cqt change this if you already have passwords generated with a different algorithm \- users that have such passwords will not be able to authenticate\&. The default value is
\fIsha\fR\&.
.RE
.PP
+\fBauth_stored_password_types\fR: \fI[plain | scram_sha1 | scram_sha256 | scram_sha512]\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.03\&. List of password types that should be stored simultaneously for each user in database\&. When the user sets the account password, database will be updated to store the password in formats compatible with each type listed here\&. This can be used to migrate user passwords to a more secure format\&. If this option if set, it will override values set in
+\fIauth_scram_hash\fR
+and
+\fIauth_password_format\fR
+options\&. The default value is
+[]\&.
+.RE
+.PP
\fBauth_use_cache\fR: \fItrue | false\fR
.RS 4
Same as
@@ -463,9 +501,9 @@ Full path to a file containing one or more CA certificates in PEM format\&. All
field\&. There is no default value\&.
.RE
.sp
-You can use host_config to specify this option per\-vhost\&.
+You can use \fIhost_config\fR to specify this option per\-vhost\&.
.sp
-To set a specific file per listener, use the listener\(cqs cafile option\&. Please notice that \fIc2s_cafile\fR overrides the listener\(cqs \fIcafile\fR option\&.
+To set a specific file per listener, use the listener\(cqs \fIlisten\-options\&.md#cafile|cafile\fR option\&. Please notice that \fIc2s_cafile\fR overrides the listener\(cqs \fIcafile\fR option\&.
.PP
\fBc2s_ciphers\fR: \fI[Cipher, \&.\&.\&.]\fR
.RS 4
@@ -491,7 +529,8 @@ c2s_ciphers:
.PP
\fBc2s_dhfile\fR: \fIPath\fR
.RS 4
-Full path to a file containing custom DH parameters to use for c2s connections\&. Such a file could be created with the command "openssl dhparam \-out dh\&.pem 2048"\&. If this option is not specified, 2048\-bit MODP Group with 256\-bit Prime Order Subgroup will be used as defined in RFC5114 Section 2\&.3\&.
+Full path to a file containing custom DH parameters to use for c2s connections\&. Such a file could be created with the command
+\fI"openssl dhparam \-out dh\&.pem 2048"\fR\&. If this option is not specified, 2048\-bit MODP Group with 256\-bit Prime Order Subgroup will be used as defined in RFC5114 Section 2\&.3\&.
.RE
.PP
\fBc2s_protocol_options\fR: \fI[Option, \&.\&.\&.]\fR
@@ -526,7 +565,7 @@ Whether to enable or disable TLS compression for c2s connections\&. The default
Path to a file of CA root certificates\&. The default is to use system defined file if possible\&.
.RE
.sp
-For server connections, this \fIca_file\fR option is overridden by the s2s_cafile option\&.
+For server connections, this \fIca_file\fR option is overridden by the \fIs2s_cafile\fR option\&.
.PP
\fBcache_life_time\fR: \fItimeout()\fR
.RS 4
@@ -559,14 +598,21 @@ A maximum number of items (not memory!) in cache\&. The rule of thumb, for all t
\fIrouter_cache_size\fR, and
\fIsm_cache_size\fR\&.
.RE
-.sp
-\fINote\fR about the next option: improved in 21\&.10:
.PP
-\fBcaptcha_cmd\fR: \fIPath\fR
+\fBcaptcha_cmd\fR: \fIPath | ModuleName\fR
.RS 4
-Full path to a script that generates
-CAPTCHA
-images\&. @VERSION@ is replaced with ejabberd version number in XX\&.YY format\&. @SEMVER@ is replaced with ejabberd version number in semver format when compiled with Elixir\(cqs mix, or XX\&.YY format otherwise\&. There is no default value: when this option is not set, CAPTCHA functionality is completely disabled\&.
+\fINote\fR
+about this option: improved in 23\&.01\&. Full path to a script that generates
+\fIbasic\&.md#captcha|CAPTCHA\fR
+images\&. The keyword
+\fI@VERSION@\fR
+is replaced with ejabberd version number in
+\fIXX\&.YY\fR
+format\&. The keyword
+\fI@SEMVER@\fR
+is replaced with ejabberd version number in semver format when compiled with Elixir\(cqs mix, or XX\&.YY format otherwise\&. Alternatively, it can be the name of a module that implements ejabberd CAPTCHA support\&. There is no default value: when this option is not set, CAPTCHA functionality is completely disabled\&.
+.sp
+\fBExamples\fR:
.sp
When using the ejabberd installers or container image, the example captcha scripts can be used like this:
.sp
@@ -591,20 +637,28 @@ instead\&.
\fBcaptcha_limit\fR: \fIpos_integer() | infinity\fR
.RS 4
Maximum number of
-CAPTCHA
+\fIbasic\&.md#captcha|CAPTCHA\fR
generated images per minute for any given JID\&. The option is intended to protect the server from CAPTCHA DoS\&. The default value is
\fIinfinity\fR\&.
.RE
.PP
-\fBcaptcha_url\fR: \fIURL\fR
+\fBcaptcha_url\fR: \fIURL | auto | undefined\fR
.RS 4
-An URL where
-CAPTCHA
+\fINote\fR
+about this option: improved in 23\&.04\&. An URL where
+\fIbasic\&.md#captcha|CAPTCHA\fR
requests should be sent\&. NOTE: you need to configure
\fIrequest_handlers\fR
for
\fIejabberd_http\fR
-listener as well\&. There is no default value\&.
+listener as well\&. If set to
+\fIauto\fR, it builds the URL using a
+\fIrequest_handler\fR
+already enabled, with encryption if available\&. If set to
+\fIundefined\fR, it builds the URL using the deprecated
+\fIcaptcha_host\fR
+\fI+ /captcha\fR\&. The default value is
+\fIauto\fR\&.
.RE
.PP
\fBcertfiles\fR: \fI[Path, \&.\&.\&.]\fR
@@ -616,6 +670,8 @@ and so on\&. NOTE: if you modify the certificate files or change the value of th
\fIejabberdctl reload\-config\fR
in order to rebuild and reload the certificate chains\&.
.sp
+\fBExamples\fR:
+.sp
If you use
Let\(cqs Encrypt
certificates for your domain "domain\&.tld", the configuration will look like this:
@@ -646,23 +702,55 @@ A list of Erlang nodes to connect on ejabberd startup\&. This option is mostly i
.PP
\fBdefault_db\fR: \fImnesia | sql\fR
.RS 4
-Default persistent storage for ejabberd\&. Modules and other components (e\&.g\&. authentication) may have its own value\&. The default value is
+\fIdatabase\&.md#default\-database|Default database\fR
+to store persistent data in ejabberd\&. Some components can be configured with specific toplevel options like
+\fIoauth_db_type\fR\&. Many modules can be configured with specific module options, usually named
+db_type\&. The default value is
\fImnesia\fR\&.
.RE
.PP
\fBdefault_ram_db\fR: \fImnesia | redis | sql\fR
.RS 4
-Default volatile (in\-memory) storage for ejabberd\&. Modules and other components (e\&.g\&. session management) may have its own value\&. The default value is
+Default volatile (in\-memory) storage for ejabberd\&. Some components can be configured with specific toplevel options like
+\fIrouter_db_type\fR
+and
+\fIsm_db_type\fR\&. Some modules can be configured with specific module options, usually named
+ram_db_type\&. The default value is
\fImnesia\fR\&.
.RE
.PP
-\fBdefine_macro\fR: \fI{MacroName: MacroValue}\fR
+\fBdefine_keyword\fR: \fI{NAME: Value}\fR
.RS 4
-Defines a macro\&. The value can be any valid arbitrary YAML value\&. For convenience, it\(cqs recommended to define a
-\fIMacroName\fR
-in capital letters\&. Duplicated macros are not allowed\&. Macros are processed after additional configuration files have been included, so it is possible to use macros that are defined in configuration files included before the usage\&. It is possible to use a
-\fIMacroValue\fR
-in the definition of another macro\&.
+\fINote\fR
+about this option: added in 25\&.03\&. Allows to define configuration
+\fI\&.\&./configuration/file\-format\&.md#macros\-and\-keywords|keywords\fR\&.
+.sp
+\fBExample\fR:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+define_keyword:
+ SQL_USERNAME: "eja\&.global"
+
+host_config:
+ localhost:
+ define_keyword:
+ SQL_USERNAME: "eja\&.localhost"
+
+sql_username: "prefix\&.@SQL_USERNAME@"
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+\fBdefine_macro\fR: \fI{NAME: Value}\fR
+.RS 4
+\fINote\fR
+about this option: improved in 25\&.03\&. Allows to define configuration
+\fI\&.\&./configuration/file\-format\&.md#macros\-and\-keywords|macros\fR\&.
.sp
\fBExample\fR:
.sp
@@ -696,9 +784,19 @@ or
is case\-insensitive\&. The default value is an empty list, i\&.e\&. no mechanisms are disabled by default\&.
.RE
.PP
+\fBdisable_sasl_scram_downgrade_protection\fR: \fItrue | false\fR
+.RS 4
+Allows to disable sending data required by
+\fIXEP\-0474: SASL SCRAM Downgrade Protection\fR\&. There are known buggy clients (like those that use strophejs 1\&.6\&.2) which will not be able to authenticatate when servers sends data from that specification\&. This options allows server to disable it to allow even buggy clients connects, but in exchange decrease MITM protection\&. The default value of this option is
+\fIfalse\fR
+which enables this extension\&.
+.RE
+.PP
\fBdomain_balancing\fR: \fI{Domain: Options}\fR
.RS 4
-An algorithm to load balance the components that are plugged on an ejabberd cluster\&. It means that you can plug one or several instances of the same component on each ejabberd node and that the traffic will be automatically distributed\&. The algorithm to deliver messages to the component(s) can be specified by this option\&. For any component connected as
+An algorithm to
+\fI\&.\&./guide/clustering\&.md#service\-load\-balancing|load\-balance\fR
+the components that are plugged on an ejabberd cluster\&. It means that you can plug one or several instances of the same component on each ejabberd node and that the traffic will be automatically distributed\&. The algorithm to deliver messages to the component(s) can be specified by this option\&. For any component connected as
\fIDomain\fR, available
\fIOptions\fR
are:
@@ -708,28 +806,43 @@ are:
The number of components to balance\&.
.RE
.PP
-\fBtype\fR: \fIrandom | source | destination | bare_source | bare_destination\fR
+\fBtype\fR: \fIValue\fR
.RS 4
-How to deliver stanzas to connected components:
-\fIrandom\fR
-\- an instance is chosen at random;
-\fIdestination\fR
-\- an instance is chosen by the full JID of the packet\(cqs
+How to deliver stanzas to connected components\&. The default value is
+\fIrandom\fR\&. Possible values:
+.RE
+.PP
+\fB\- bare_destination\fR
+.RS 4
+by the bare JID (without resource) of the packet\(cqs
\fIto\fR
-attribute;
-\fIsource\fR
-\- by the full JID of the packet\(cqs
+attribute
+.RE
+.PP
+\fB\- bare_source\fR
+.RS 4
+by the bare JID (without resource) of the packet\(cqs
\fIfrom\fR
-attribute;
-\fIbare_destination\fR
-\- by the the bare JID (without resource) of the packet\(cqs
+attribute is used
+.RE
+.PP
+\fB\- destination\fR
+.RS 4
+an instance is chosen by the full JID of the packet\(cqs
\fIto\fR
-attribute;
-\fIbare_source\fR
-\- by the bare JID (without resource) of the packet\(cqs
+attribute
+.RE
+.PP
+\fB\- random\fR
+.RS 4
+an instance is chosen at random
+.RE
+.PP
+\fB\- source\fR
+.RS 4
+by the full JID of the packet\(cqs
\fIfrom\fR
-attribute is used\&. The default value is
-\fIrandom\fR\&.
+attribute
.RE
.sp
\fBExample\fR:
@@ -777,18 +890,22 @@ Define the base URI when performing ReST requests\&. The default value is:
.PP
\fBextauth_pool_name\fR: \fIName\fR
.RS 4
-Define the pool name appendix, so the full pool name will be
+Define the pool name appendix in
+\fIauthentication\&.md#external\-script|external auth\fR, so the full pool name will be
\fIextauth_pool_Name\fR\&. The default value is the hostname\&.
.RE
.PP
\fBextauth_pool_size\fR: \fISize\fR
.RS 4
-The option defines the number of instances of the same external program to start for better load balancing\&. The default is the number of available CPU cores\&.
+The option defines the number of instances of the same
+\fIauthentication\&.md#external\-script|external auth\fR
+program to start for better load balancing\&. The default is the number of available CPU cores\&.
.RE
.PP
\fBextauth_program\fR: \fIPath\fR
.RS 4
-Indicate in this option the full path to the external authentication script\&. The script must be executable by ejabberd\&.
+Indicate in this option the full path to the
+\fIauthentication\&.md#external\-script|external authentication script\fR\&. The script must be executable by ejabberd\&.
.RE
.PP
\fBfqdn\fR: \fIDomain\fR
@@ -807,7 +924,8 @@ for backward compatibility\&.
.RS 4
The option is used to redefine
\fIOptions\fR
-for virtual host
+for
+\fI\&.\&./configuration/basic\&.md#virtual\-hosting|virtual host\fR
\fIHost\fR\&. In the example below LDAP authentication method will be used on virtual host
\fIdomain\&.tld\fR
and SQL method will be used on virtual host
@@ -838,16 +956,46 @@ host_config:
.PP
\fBhosts\fR: \fI[Domain1, Domain2, \&.\&.\&.]\fR
.RS 4
-The option defines a list containing one or more domains that
-\fIejabberd\fR
-will serve\&. This is a
+List of one or more
+\fI\&.\&./configuration/basic\&.md#host\-names|host names\fR
+(or domains) that ejabberd will serve\&. This is a
\fBmandatory\fR
option\&.
.RE
.PP
+\fBhosts_alias\fR: \fI{Alias: Host}\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. Define aliases for existing vhosts managed by ejabberd\&. An alias may be a regexp expression\&. This option is only consulted by the
+\fIejabberd_http\fR
+listener\&.
+.sp
+\fBExample\fR:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+hosts:
+ \- domain\&.tld
+ \- example\&.org
+
+hosts_alias:
+ xmpp\&.domain\&.tld: domain\&.tld
+ jabber\&.domain\&.tld: domain\&.tld
+ mytest\&.net: example\&.org
+ "exa*": example\&.org
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
\fBinclude_config_file\fR: \fI[Filename, \&.\&.\&.] | {Filename: Options}\fR
.RS 4
-Read additional configuration from
+Read and
+\fI\&.\&./configuration/file\-format\&.md#include\-additional\-files|include additional file\fR
+from
\fIFilename\fR\&. If the value is provided in
\fI{Filename: Options}\fR
format, the
@@ -867,9 +1015,20 @@ Disallows the usage of those options in the included file
.RE
.RE
.PP
+\fBinstall_contrib_modules\fR: \fI[Module, \&.\&.\&.]\fR
+.RS 4
+\fINote\fR
+about this option: added in 23\&.10\&. Modules to install from
+\fI\&.\&./\&.\&./admin/guide/modules\&.md#ejabberd\-contrib|ejabberd\-contrib\fR
+at start time\&. The default value is an empty list of modules:
+\fI[]\fR\&.
+.RE
+.PP
\fBjwt_auth_only_rule\fR: \fIAccessName\fR
.RS 4
-This ACL rule defines accounts that can use only this auth method, even if others are also defined in the ejabberd configuration file\&. In other words: if there are several auth methods enabled for this host (JWT, SQL, \&...), users that match this rule can only use JWT\&. The default value is
+This ACL rule defines accounts that can use only the
+\fIauthentication\&.md#jwt\-authentication|JWT\fR
+auth method, even if others are also defined in the ejabberd configuration file\&. In other words: if there are several auth methods enabled for this host (JWT, SQL, \&...), users that match this rule can only use JWT\&. The default value is
\fInone\fR\&.
.RE
.PP
@@ -877,18 +1036,24 @@ This ACL rule defines accounts that can use only this auth method, even if other
.RS 4
By default, the JID is defined in the
\fI"jid"\fR
-JWT field\&. This option allows to specify other JWT field name where the JID is defined\&.
+JWT field\&. In this option you can specify other
+\fIauthentication\&.md#jwt\-authentication|JWT\fR
+field name where the JID is defined\&.
.RE
.PP
\fBjwt_key\fR: \fIFilePath\fR
.RS 4
-Path to the file that contains the JWK Key\&. The default value is
+Path to the file that contains the
+\fIauthentication\&.md#jwt\-authentication|JWT\fR
+key\&. The default value is
\fIundefined\fR\&.
.RE
.PP
\fBlanguage\fR: \fILanguage\fR
.RS 4
-The option defines the default language of server strings that can be seen by XMPP clients\&. If an XMPP client does not possess
+Define the
+\fI\&.\&./configuration/basic\&.md#default\-language|default language\fR
+of server strings that can be seen by XMPP clients\&. If an XMPP client does not possess
\fIxml:lang\fR
attribute, the specified language is used\&. The default value is
\fI"en"\fR\&.
@@ -896,9 +1061,10 @@ attribute, the specified language is used\&. The default value is
.PP
\fBldap_backups\fR: \fI[Host, \&.\&.\&.]\fR
.RS 4
-A list of IP addresses or DNS names of LDAP backup servers\&. When no servers listed in
+A list of IP addresses or DNS names of LDAP backup servers (see
+\fI\&.\&./configuration/ldap\&.md#ldap\-connection|LDAP connection\fR)\&. When no servers listed in
\fIldap_servers\fR
-option are reachable, ejabberd will try to connect to these backup servers\&. The default is an empty list, i\&.e\&. no backup servers specified\&. WARNING: ejabberd doesn\(cqt try to reconnect back to the main servers when they become operational again, so the only way to restore these connections is to restart ejabberd\&. This limitation might be fixed in future releases\&.
+option are reachable, ejabberd connects to these backup servers\&. The default is an empty list, i\&.e\&. no backup servers specified\&. Please notice that ejabberd only connects to the next server when the existing connection is lost; it doesn\(cqt detect when a previously\-attempted server becomes available again\&.
.RE
.PP
\fBldap_base\fR: \fIBase\fR
@@ -915,10 +1081,23 @@ Whether to dereference aliases or not\&. The default value is
\fBldap_dn_filter\fR: \fI{Filter: FilterAttrs}\fR
.RS 4
This filter is applied on the results returned by the main filter\&. The filter performs an additional LDAP lookup to make the complete result\&. This is useful when you are unable to define all filter rules in
-\fIldap_filter\fR\&. You can define "%u", "%d", "%s" and "%D" pattern variables in
-\fIFilter\fR: "%u" is replaced by a user\(cqs part of the JID, "%d" is replaced by the corresponding domain (virtual host), all "%s" variables are consecutively replaced by values from the attributes in
+\fIldap_filter\fR\&. You can define
+\fI"%u"\fR,
+\fI"%d"\fR,
+\fI"%s"\fR
+and
+\fI"%D"\fR
+pattern variables in
+\fIFilter: "%u"\fR
+is replaced by a user\(cqs part of the JID,
+\fI"%d"\fR
+is replaced by the corresponding domain (virtual host), all
+\fI"%s"\fR
+variables are consecutively replaced by values from the attributes in
\fIFilterAttrs\fR
-and "%D" is replaced by Distinguished Name from the result set\&. There is no default value, which means the result is not filtered\&. WARNING: Since this filter makes additional LDAP lookups, use it only as the last resort: try to define all filter rules in
+and
+\fI"%D"\fR
+is replaced by Distinguished Name from the result set\&. There is no default value, which means the result is not filtered\&. WARNING: Since this filter makes additional LDAP lookups, use it only as the last resort: try to define all filter rules in
\fIldap_filter\fR
option if possible\&.
.sp
@@ -945,7 +1124,10 @@ Whether to encrypt LDAP connection using TLS or not\&. The default value is
\fBldap_filter\fR: \fIFilter\fR
.RS 4
An LDAP filter as defined in
-RFC4515\&. There is no default value\&. Example: "(&(objectClass=shadowAccount)(memberOf=XMPP Users))"\&. NOTE: don\(cqt forget to close brackets and don\(cqt use superfluous whitespaces\&. Also you must not use "uid" attribute in the filter because this attribute will be appended to the filter automatically\&.
+RFC4515\&. There is no default value\&. Example:
+\fI"(&(objectClass=shadowAccount)(memberOf=XMPP Users))"\fR\&. NOTE: don\(cqt forget to close brackets and don\(cqt use superfluous whitespaces\&. Also you must not use
+\fI"uid"\fR
+attribute in the filter because this attribute will be appended to the filter automatically\&.
.RE
.PP
\fBldap_password\fR: \fIPassword\fR
@@ -969,7 +1151,8 @@ Bind Distinguished Name\&. The default value is an empty string, which means "an
.PP
\fBldap_servers\fR: \fI[Host, \&.\&.\&.]\fR
.RS 4
-A list of IP addresses or DNS names of your LDAP servers\&. The default value is
+A list of IP addresses or DNS names of your LDAP servers (see
+\fI\&.\&./configuration/ldap\&.md#ldap\-connection|LDAP connection\fR)\&. ejabberd connects immediately to all of them, and reconnects infinitely if connection is lost\&. The default value is
\fI[localhost]\fR\&.
.RE
.PP
@@ -1007,34 +1190,45 @@ LDAP attributes which hold a list of attributes to use as alternatives for getti
\fIAttr\fR
is an LDAP attribute which holds the user\(cqs part of the JID and
\fIAttrFormat\fR
-must contain one and only one pattern variable "%u" which will be replaced by the user\(cqs part of the JID\&. For example, "%u@example\&.org"\&. If the value is in the form of
+must contain one and only one pattern variable
+\fI"%u"\fR
+which will be replaced by the user\(cqs part of the JID\&. For example,
+\fI"%\fR\fIu@example\fR\fI\&.org"\fR\&. If the value is in the form of
\fI[Attr]\fR
then
\fIAttrFormat\fR
-is assumed to be "%u"\&.
+is assumed to be
+\fI"%u"\fR\&.
.RE
.PP
\fBlisten\fR: \fI[Options, \&.\&.\&.]\fR
.RS 4
The option for listeners configuration\&. See the
-Listen Modules
+\fIlisten\&.md|Listen Modules\fR
section for details\&.
.RE
-.sp
-\fINote\fR about the next option: added in 22\&.10:
.PP
\fBlog_burst_limit_count\fR: \fINumber\fR
.RS 4
-The number of messages to accept in
+\fINote\fR
+about this option: added in 22\&.10\&. The number of messages to accept in
log_burst_limit_window_time
-period before starting to drop them\&. Default 500
+period before starting to drop them\&. Default
+500
.RE
-.sp
-\fINote\fR about the next option: added in 22\&.10:
.PP
\fBlog_burst_limit_window_time\fR: \fINumber\fR
.RS 4
-The time period to rate\-limit log messages by\&. Defaults to 1 second\&.
+\fINote\fR
+about this option: added in 22\&.10\&. The time period to rate\-limit log messages by\&. Defaults to
+1
+second\&.
+.RE
+.PP
+\fBlog_modules_fully\fR: \fI[Module, \&.\&.\&.]\fR
+.RS 4
+\fINote\fR
+about this option: added in 23\&.01\&. List of modules that will log everything independently from the general loglevel option\&.
.RE
.PP
\fBlog_rotate_count\fR: \fINumber\fR
@@ -1050,14 +1244,14 @@ crash\&.log\&.0\&.
\fBlog_rotate_size\fR: \fIpos_integer() | infinity\fR
.RS 4
The size (in bytes) of a log file to trigger rotation\&. If set to
-\fIinfinity\fR, log rotation is disabled\&. The default value is
-\fI10485760\fR
-(that is, 10 Mb)\&.
+\fIinfinity\fR, log rotation is disabled\&. The default value is 10 Mb expressed in bytes:
+\fI10485760\fR\&.
.RE
.PP
\fBloglevel\fR: \fInone | emergency | alert | critical | error | warning | notice | info | debug\fR
.RS 4
-Verbosity of log files generated by ejabberd\&. The default value is
+Verbosity of ejabberd
+\fI\&.\&./configuration/basic\&.md#logging|logging\fR\&. The default value is
\fIinfo\fR\&. NOTE: previous versions of ejabberd had log levels defined in numeric format (\fI0\&.\&.5\fR)\&. The numeric values are still accepted for backward compatibility, but are not recommended\&.
.RE
.PP
@@ -1069,15 +1263,15 @@ This option specifies the maximum number of elements in the queue of the FSM (Fi
.PP
\fBmodules\fR: \fI{Module: Options}\fR
.RS 4
-The option for modules configuration\&. See
-Modules
-section for details\&.
+Set all the
+\fImodules\&.md|modules\fR
+configuration options\&.
.RE
.PP
\fBnegotiation_timeout\fR: \fItimeout()\fR
.RS 4
Time to wait for an XMPP stream negotiation to complete\&. When timeout occurs, the corresponding XMPP stream is closed\&. The default value is
-\fI30\fR
+\fI120\fR
seconds\&.
.RE
.PP
@@ -1090,12 +1284,11 @@ This option can be used to tune tick time parameter of
.PP
\fBnew_sql_schema\fR: \fItrue | false\fR
.RS 4
-Whether to use
+Whether to use the
+\fIdatabase\&.md#default\-and\-new\-schemas|new SQL schema\fR\&. All schemas are located at
+https://github\&.com/processone/ejabberd/tree/25\&.08/sql\&. There are two schemas available\&. The default legacy schema stores one XMPP domain into one ejabberd database\&. The
\fInew\fR
-SQL schema\&. All schemas are located at
-https://github\&.com/processone/ejabberd/tree/22\&.10/sql\&. There are two schemas available\&. The default legacy schema allows to store one XMPP domain into one ejabberd database\&. The
-\fInew\fR
-schema allows to handle several XMPP domains in a single ejabberd database\&. Using this
+schema can handle several XMPP domains in a single ejabberd database\&. Using this
\fInew\fR
schema is best when serving several XMPP domains and/or changing domains from time to time\&. This avoid need to manage several databases and handle complex configuration changes\&. The default depends on configuration flag
\fI\-\-enable\-new\-sql\-schema\fR
@@ -1126,12 +1319,11 @@ Same as
\fIcache_missed\fR
will be used\&.
.RE
-.sp
-\fINote\fR about the next option: added in 21\&.01:
.PP
\fBoauth_cache_rest_failure_life_time\fR: \fItimeout()\fR
.RS 4
-The time that a failure in OAuth ReST is cached\&. The default value is
+\fINote\fR
+about this option: added in 21\&.01\&. The time that a failure in OAuth ReST is cached\&. The default value is
\fIinfinity\fR\&.
.RE
.PP
@@ -1203,26 +1395,27 @@ option)\&. Later, when memory drops below this
percents\&.
.RE
.PP
-\fBoutgoing_s2s_families\fR: \fI[ipv4 | ipv6, \&.\&.\&.]\fR
+\fBoutgoing_s2s_families\fR: \fI[ipv6 | ipv4, \&.\&.\&.]\fR
.RS 4
-Specify which address families to try, in what order\&. The default is
-\fI[ipv4, ipv6]\fR
-which means it first tries connecting with IPv4, if that fails it tries using IPv6\&.
+\fINote\fR
+about this option: changed in 23\&.01\&. Specify which address families to try, in what order\&. The default is
+\fI[ipv6, ipv4]\fR
+which means it first tries connecting with IPv6, if that fails it tries using IPv4\&. This option is obsolete and irrelevant when using ejabberd 23\&.01 and Erlang/OTP 22, or newer versions of them\&.
.RE
-.sp
-\fINote\fR about the next option: added in 20\&.12:
.PP
\fBoutgoing_s2s_ipv4_address\fR: \fIAddress\fR
.RS 4
-Specify the IPv4 address that will be used when establishing an outgoing S2S IPv4 connection, for example "127\&.0\&.0\&.1"\&. The default value is
+\fINote\fR
+about this option: added in 20\&.12\&. Specify the IPv4 address that will be used when establishing an outgoing S2S IPv4 connection, for example
+\fI"127\&.0\&.0\&.1"\fR\&. The default value is
\fIundefined\fR\&.
.RE
-.sp
-\fINote\fR about the next option: added in 20\&.12:
.PP
\fBoutgoing_s2s_ipv6_address\fR: \fIAddress\fR
.RS 4
-Specify the IPv6 address that will be used when establishing an outgoing S2S IPv6 connection, for example "::FFFF:127\&.0\&.0\&.1"\&. The default value is
+\fINote\fR
+about this option: added in 20\&.12\&. Specify the IPv6 address that will be used when establishing an outgoing S2S IPv6 connection, for example
+\fI"::FFFF:127\&.0\&.0\&.1"\fR\&. The default value is
\fIundefined\fR\&.
.RE
.PP
@@ -1241,13 +1434,17 @@ seconds\&.
.PP
\fBpam_service\fR: \fIName\fR
.RS 4
-This option defines the PAM service name\&. Refer to the PAM documentation of your operation system for more information\&. The default value is
+This option defines the
+\fIauthentication\&.md#pam\-authentication|PAM\fR
+service name\&. Refer to the PAM documentation of your operation system for more information\&. The default value is
\fIejabberd\fR\&.
.RE
.PP
\fBpam_userinfotype\fR: \fIusername | jid\fR
.RS 4
-This option defines what type of information about the user ejabberd provides to the PAM service: only the username, or the user\(cqs JID\&. Default is
+This option defines what type of information about the user ejabberd provides to the
+\fIauthentication\&.md#pam\-authentication|PAM\fR
+service: only the username, or the user\(cqs JID\&. Default is
\fIusername\fR\&.
.RE
.PP
@@ -1281,36 +1478,47 @@ option where file queues will be placed\&. The default value is
.PP
\fBredis_connect_timeout\fR: \fItimeout()\fR
.RS 4
-A timeout to wait for the connection to be re\-established to the Redis server\&. The default is
+A timeout to wait for the connection to be re\-established to the
+\fIdatabase\&.md#redis|Redis\fR
+server\&. The default is
\fI1 second\fR\&.
.RE
.PP
\fBredis_db\fR: \fINumber\fR
.RS 4
-Redis database number\&. The default is
+\fIdatabase\&.md#redis|Redis\fR
+database number\&. The default is
\fI0\fR\&.
.RE
.PP
\fBredis_password\fR: \fIPassword\fR
.RS 4
-The password to the Redis server\&. The default is an empty string, i\&.e\&. no password\&.
+The password to the
+\fIdatabase\&.md#redis|Redis\fR
+server\&. The default is an empty string, i\&.e\&. no password\&.
.RE
.PP
\fBredis_pool_size\fR: \fINumber\fR
.RS 4
-The number of simultaneous connections to the Redis server\&. The default value is
+The number of simultaneous connections to the
+\fIdatabase\&.md#redis|Redis\fR
+server\&. The default value is
\fI10\fR\&.
.RE
.PP
\fBredis_port\fR: \fI1\&.\&.65535\fR
.RS 4
-The port where the Redis server is accepting connections\&. The default is
+The port where the
+\fIdatabase\&.md#redis|Redis\fR
+server is accepting connections\&. The default is
\fI6379\fR\&.
.RE
.PP
\fBredis_queue_type\fR: \fIram | file\fR
.RS 4
-The type of request queue for the Redis server\&. See description of
+The type of request queue for the
+\fIdatabase\&.md#redis|Redis\fR
+server\&. See description of
\fIqueue_type\fR
option for the explanation\&. The default value is the value defined in
\fIqueue_type\fR
@@ -1319,9 +1527,13 @@ or
if the latter is not set\&.
.RE
.PP
-\fBredis_server\fR: \fIHostname\fR
+\fBredis_server\fR: \fIHost | IP Address | Unix Socket Path\fR
.RS 4
-A hostname or an IP address of the Redis server\&. The default is
+\fINote\fR
+about this option: improved in 24\&.12\&. A hostname, IP address or unix domain socket file of the
+\fIdatabase\&.md#redis|Redis\fR
+server\&. Setup the path to unix domain socket like:
+\fI"unix:/path/to/socket"\fR\&. The default value is
\fIlocalhost\fR\&.
.RE
.PP
@@ -1341,6 +1553,30 @@ XMPP Core: section 7\&.7\&.2\&.2\&. The default value is
\fIcloseold\fR\&.
.RE
.PP
+\fBrest_proxy\fR: \fIHost\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. Address of a HTTP Connect proxy used by modules issuing rest calls (like ejabberd_oauth_rest)
+.RE
+.PP
+\fBrest_proxy_password\fR: \fIstring()\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. Password used to authenticate to HTTP Connect proxy used by modules issuing rest calls (like ejabberd_oauth_rest)
+.RE
+.PP
+\fBrest_proxy_port\fR: \fI1\&.\&.65535\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. Port of a HTTP Connect proxy used by modules issuing rest calls (like ejabberd_oauth_rest)
+.RE
+.PP
+\fBrest_proxy_username\fR: \fIstring()\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.07\&. Username used to authenticate to HTTP Connect proxy used by modules issuing rest calls (like ejabberd_oauth_rest)
+.RE
+.PP
\fBrouter_cache_life_time\fR: \fItimeout()\fR
.RS 4
Same as
@@ -1392,7 +1628,7 @@ seconds\&.
\fBs2s_access\fR: \fIAccess\fR
.RS 4
This
-Access Rule
+\fIbasic\&.md#access\-rules|Access Rule\fR
defines to what remote servers can s2s connections be established\&. The default value is
\fIall\fR; no restrictions are applied, it is allowed to connect s2s to/from all remote servers\&.
.RE
@@ -1400,11 +1636,11 @@ defines to what remote servers can s2s connections be established\&. The default
\fBs2s_cafile\fR: \fIPath\fR
.RS 4
A path to a file with CA root certificates that will be used to authenticate s2s connections\&. If not set, the value of
-ca_file
+\fIca_file\fR
will be used\&.
.RE
.sp
-You can use host_config to specify this option per\-vhost\&.
+You can use \fIhost_config\fR to specify this option per\-vhost\&.
.PP
\fBs2s_ciphers\fR: \fI[Cipher, \&.\&.\&.]\fR
.RS 4
@@ -1430,7 +1666,8 @@ s2s_ciphers:
.PP
\fBs2s_dhfile\fR: \fIPath\fR
.RS 4
-Full path to a file containing custom DH parameters to use for s2s connections\&. Such a file could be created with the command "openssl dhparam \-out dh\&.pem 2048"\&. If this option is not specified, 2048\-bit MODP Group with 256\-bit Prime Order Subgroup will be used as defined in RFC5114 Section 2\&.3\&.
+Full path to a file containing custom DH parameters to use for s2s connections\&. Such a file could be created with the command
+\fI"openssl dhparam \-out dh\&.pem 2048"\fR\&. If this option is not specified, 2048\-bit MODP Group with 256\-bit Prime Order Subgroup will be used as defined in RFC5114 Section 2\&.3\&.
.RE
.PP
\fBs2s_dns_retries\fR: \fINumber\fR
@@ -1524,7 +1761,8 @@ XEP\-0138) or not\&. The default value is
.PP
\fBshaper\fR: \fI{ShaperName: Rate}\fR
.RS 4
-The option defines a set of shapers\&. Every shaper is assigned a name
+The option defines a set of
+\fI\&.\&./configuration/basic\&.md#shapers|shapers\fR\&. Every shaper is assigned a name
\fIShaperName\fR
that can be used in other parts of the configuration file, such as
\fIshaper_rules\fR
@@ -1554,9 +1792,11 @@ shaper:
.\}
.RE
.PP
-\fBshaper_rules\fR: \fI{ShaperRuleName: {Number|ShaperName: ACLRule|ACLName}}\fR
+\fBshaper_rules\fR: \fI{ShaperRuleName: {Number|ShaperName: ACLName|ACLDefinition}}\fR
.RS 4
-An entry allowing to declaring shaper to use for matching user/hosts\&. Semantics is similar to
+This option defines
+\fI\&.\&./configuration/basic\&.md#shaper\-rules|shaper rules\fR
+to use for matching user/hosts\&. Semantics is similar to
\fIaccess_rules\fR
option, the only difference is that instead using
\fIallow\fR
@@ -1642,19 +1882,29 @@ An SQL database name\&. For SQLite this must be a full path to a database file\&
\fIejabberd\fR\&.
.RE
.PP
+\fBsql_flags\fR: \fI[mysql_alternative_upsert]\fR
+.RS 4
+\fINote\fR
+about this option: added in 24\&.02\&. This option accepts a list of SQL flags, and is empty by default\&.
+\fImysql_alternative_upsert\fR
+forces the alternative upsert implementation in MySQL\&.
+.RE
+.PP
\fBsql_keepalive_interval\fR: \fItimeout()\fR
.RS 4
An interval to make a dummy SQL request to keep alive the connections to the database\&. There is no default value, so no keepalive requests are made\&.
.RE
-.sp
-\fINote\fR about the next option: added in 20\&.12:
.PP
\fBsql_odbc_driver\fR: \fIPath\fR
.RS 4
-Path to the ODBC driver to use to connect to a Microsoft SQL Server database\&. This option is only valid if the
+\fINote\fR
+about this option: added in 20\&.12\&. Path to the ODBC driver to use to connect to a Microsoft SQL Server database\&. This option only applies if the
\fIsql_type\fR
option is set to
-\fImssql\fR\&. The default value is:
+\fImssql\fR
+and
+\fIsql_server\fR
+is not an ODBC connection string\&. The default value is:
\fIlibtdsodbc\&.so\fR
.RE
.PP
@@ -1665,7 +1915,8 @@ The password for SQL authentication\&. The default is empty string\&.
.PP
\fBsql_pool_size\fR: \fISize\fR
.RS 4
-Number of connections to the SQL server that ejabberd will open for each virtual host\&. The default value is 10\&. WARNING: for SQLite this value is
+Number of connections to the SQL server that ejabberd will open for each virtual host\&. The default value is
+\fI10\fR\&. WARNING: for SQLite this value is
\fI1\fR
by default and it\(cqs not recommended to change it due to potential race conditions\&.
.RE
@@ -1680,14 +1931,13 @@ for PostgreSQL and
\fI1433\fR
for MS SQL\&. The option has no effect for SQLite\&.
.RE
-.sp
-\fINote\fR about the next option: added in 20\&.01:
.PP
\fBsql_prepared_statements\fR: \fItrue | false\fR
.RS 4
-This option is
+\fINote\fR
+about this option: added in 20\&.01\&. This option is
\fItrue\fR
-by default, and is useful to disable prepared statements\&. The option is valid for PostgreSQL\&.
+by default, and is useful to disable prepared statements\&. The option is valid for PostgreSQL and MySQL\&.
.RE
.PP
\fBsql_query_timeout\fR: \fItimeout()\fR
@@ -1708,17 +1958,28 @@ or
if the latter is not set\&.
.RE
.PP
-\fBsql_server\fR: \fIHost\fR
+\fBsql_server\fR: \fIHost | IP Address | ODBC Connection String | Unix Socket Path\fR
.RS 4
-A hostname or an IP address of the SQL server\&. The default value is
+\fINote\fR
+about this option: improved in 24\&.06\&. The hostname or IP address of the SQL server\&. For
+\fIsql_type\fR
+\fImssql\fR
+or
+\fIodbc\fR
+this can also be an ODBC connection string\&. When
+\fIsql_type\fR
+is
+\fImysql\fR
+or
+\fIpgsql\fR, this can be the path to a unix domain socket expressed like:
+\fI"unix:/path/to/socket"\fR\&.The default value is
\fIlocalhost\fR\&.
.RE
-.sp
-\fINote\fR about the next option: improved in 20\&.03:
.PP
\fBsql_ssl\fR: \fItrue | false\fR
.RS 4
-Whether to use SSL encrypted connections to the SQL server\&. The option is only available for MySQL and PostgreSQL\&. The default value is
+\fINote\fR
+about this option: improved in 20\&.03\&. Whether to use SSL encrypted connections to the SQL server\&. The option is only available for MySQL, MS SQL and PostgreSQL\&. The default value is
\fIfalse\fR\&.
.RE
.PP
@@ -1729,7 +1990,7 @@ A path to a file with CA root certificates that will be used to verify SQL conne
and
\fIsql_ssl_verify\fR
options are set to
-\fItrue\fR\&. There is no default which means certificate verification is disabled\&.
+\fItrue\fR\&. There is no default which means certificate verification is disabled\&. This option has no effect for MS SQL\&.
.RE
.PP
\fBsql_ssl_certfile\fR: \fIPath\fR
@@ -1737,7 +1998,7 @@ options are set to
A path to a certificate file that will be used for SSL connections to the SQL server\&. Implies
\fIsql_ssl\fR
option is set to
-\fItrue\fR\&. There is no default which means ejabberd won\(cqt provide a client certificate to the SQL server\&.
+\fItrue\fR\&. There is no default which means ejabberd won\(cqt provide a client certificate to the SQL server\&. This option has no effect for MS SQL\&.
.RE
.PP
\fBsql_ssl_verify\fR: \fItrue | false\fR
@@ -1747,7 +2008,7 @@ Whether to verify SSL connection to the SQL server against CA root certificates
option\&. Implies
\fIsql_ssl\fR
option is set to
-\fItrue\fR\&. The default value is
+\fItrue\fR\&. This option has no effect for MS SQL\&. The default value is
\fIfalse\fR\&.
.RE
.PP
@@ -1775,12 +2036,25 @@ A user name for SQL authentication\&. The default value is
Specify what proxies are trusted when an HTTP request contains the header
\fIX\-Forwarded\-For\fR\&. You can specify
\fIall\fR
-to allow all proxies, or specify a list of IPs, possibly with masks\&. The default value is an empty list\&. This allows, if enabled, to be able to know the real IP of the request, for admin purpose, or security configuration (for example using
+to allow all proxies, or specify a list of IPs, possibly with masks\&. The default value is an empty list\&. Using this option you can know the real IP of the request, for admin purpose, or security configuration (for example using
\fImod_fail2ban\fR)\&. IMPORTANT: The proxy MUST be configured to set the
\fIX\-Forwarded\-For\fR
header if you enable this option as, otherwise, the client can set it itself and as a result the IP value cannot be trusted for security rules in ejabberd\&.
.RE
.PP
+\fBupdate_sql_schema\fR: \fItrue | false\fR
+.RS 4
+\fINote\fR
+about this option: updated in 24\&.06\&. Allow ejabberd to update SQL schema in MySQL, PostgreSQL and SQLite databases\&. This option was added in ejabberd 23\&.10, and enabled by default since 24\&.06\&. The default value is
+\fItrue\fR\&.
+.RE
+.PP
+\fBupdate_sql_schema_timeout\fR: \fItimeout()\fR
+.RS 4
+\fINote\fR
+about this option: added in 24\&.07\&. Time allocated to SQL schema update queries\&. The default value is set to 5 minutes\&.
+.RE
+.PP
\fBuse_cache\fR: \fItrue | false\fR
.RS 4
Enable or disable cache\&. The default is
@@ -1812,7 +2086,8 @@ This option enables validation for
header to protect against connections from other domains than given in the configuration file\&. In this way, the lower layer load balancer can be chosen for a specific ejabberd implementation while still providing a secure WebSocket connection\&. The default value is
\fIignore\fR\&. An example value of the
\fIURL\fR
-is "https://test\&.example\&.org:8081"\&.
+is
+\fI"https://test\&.example\&.org:8081"\fR\&.
.RE
.PP
\fBwebsocket_ping_interval\fR: \fItimeout()\fR
@@ -1832,9 +2107,13 @@ seconds\&.
.RE
.SH "MODULES"
.sp
-This section describes options of all ejabberd modules\&.
+This section describes modules options of ejabberd 25\&.08\&. The modules that changed in this version are marked with 🟤\&.
.SS "mod_adhoc"
.sp
+def:ad\-hoc command
+.sp
+: Command that can be executed by an XMPP client using XEP\-0050\&.
+.sp
This module implements XEP\-0050: Ad\-Hoc Commands\&. It\(cqs an auxiliary module and is only needed by some of the other modules\&.
.sp
.it 1 an-trap
@@ -1851,45 +2130,74 @@ Provide the Commands item in the Service Discovery\&. Default value:
\fIfalse\fR\&.
.RE
.RE
+.SS "mod_adhoc_api"
+.sp
+\fINote\fR about this option: added in 25\&.03\&.
+.sp
+Execute (def:API commands) in a XMPP client using XEP\-0050: Ad\-Hoc Commands\&. This module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBdefault_version\fR: \fIinteger() | string()\fR
+.RS 4
+What API version to use\&. If setting an ejabberd version, it will use the latest API version that was available in that (def:c2s) ejabberd version\&. For example, setting
+\fI"24\&.06"\fR
+in this option implies
+\fI2\fR\&. The default value is the latest version\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+acl:
+ admin:
+ user: jan@localhost
+
+api_permissions:
+ "adhoc commands":
+ from: mod_adhoc_api
+ who: admin
+ what:
+ \- "[tag:roster]"
+ \- "[tag:session]"
+ \- stats
+ \- status
+
+modules:
+ mod_adhoc_api:
+ default_version: 2
+.fi
+.if n \{\
+.RE
+.\}
+.RE
.SS "mod_admin_extra"
.sp
This module provides additional administrative commands\&.
.sp
Details for some commands:
.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-\fIban\-acount\fR: This command kicks all the connected sessions of the account from the server\&. It also changes their password to a randomly generated one, so they can\(cqt login anymore unless a server administrator changes their password again\&. It is possible to define the reason of the ban\&. The new password also includes the reason and the date and time of the ban\&. See an example below\&.
-.RE
+\fIban_account\fR API: This command kicks all the connected sessions of the account from the server\&. It also changes their password to a randomly generated one, so they can\(cqt login anymore unless a server administrator changes their password again\&. It is possible to define the reason of the ban\&. The new password also includes the reason and the date and time of the ban\&. See an example below\&.
.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-\fIpushroster\fR: (and
-\fIpushroster\-all\fR) The roster file must be placed, if using Windows, on the directory where you installed ejabberd: C:/Program Files/ejabberd or similar\&. If you use other Operating System, place the file on the same directory where the \&.beam files are installed\&. See below an example roster file\&.
-.RE
+\fIpush_roster\fR API (and \fIpush_roster_all\fR API): The roster file must be placed, if using Windows, on the directory where you installed ejabberd: C:/Program Files/ejabberd or similar\&. If you use other Operating System, place the file on the same directory where the \&.beam files are installed\&. See below an example roster file\&.
.sp
-.RS 4
-.ie n \{\
-\h'-04'\(bu\h'+03'\c
-.\}
-.el \{\
-.sp -1
-.IP \(bu 2.3
-.\}
-\fIsrg\-create\fR: If you want to put a group Name with blankspaces, use the characters "\*(Aq and \*(Aq" to define when the Name starts and ends\&. See an example below\&.
-.RE
+\fIsrg_create\fR API: If you want to put a group Name with blank spaces, use the characters \fI"\fR\*(Aq and \fI\*(Aq"\fR to define when the Name starts and ends\&. See an example below\&.
.sp
The module has no options\&.
.sp
@@ -1922,7 +2230,7 @@ modules:
.RE
.\}
.sp
-Content of roster file for \fIpushroster\fR command:
+Content of roster file for \fIpush_roster\fR API:
.sp
.if n \{\
.RS 4
@@ -1936,44 +2244,60 @@ Content of roster file for \fIpushroster\fR command:
.RE
.\}
.sp
-With this call, the sessions of the local account which JID is boby@example\&.org will be kicked, and its password will be set to something like \fIBANNED_ACCOUNT\(em20080425T21:45:07\(em2176635\(emSpammed_rooms\fR
+With this call, the sessions of the local account which JID is \fIboby@example\&.org\fR will be kicked, and its password will be set to something like \fIBANNED_ACCOUNT\(em20080425T21:45:07\(em2176635\(emSpammed_rooms\fR
.sp
.if n \{\
.RS 4
.\}
.nf
-ejabberdctl vhost example\&.org ban\-account boby "Spammed rooms"
+ejabberdctl vhost example\&.org ban_account boby "Spammed rooms"
.fi
.if n \{\
.RE
.\}
.sp
-Call to srg\-create using double\-quotes and single\-quotes:
+Call to \fIsrg_create\fR API using double\-quotes and single\-quotes:
.sp
.if n \{\
.RS 4
.\}
.nf
-ejabberdctl srg\-create g1 example\&.org "\*(AqGroup number 1\*(Aq" this_is_g1 g1
+ejabberdctl srg_create g1 example\&.org "\*(AqGroup number 1\*(Aq" this_is_g1 g1
.fi
.if n \{\
.RE
.\}
+.sp
+\fBAPI Tags:\fR \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#accounts|accounts\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#erlang|erlang\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#last|last\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#private|private\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#purge|purge\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#roster|roster\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#session|session\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#shared_roster_group|shared_roster_group\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#stanza|stanza\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#statistics|statistics\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#vcard|vcard\fR
.RE
.SS "mod_admin_update_sql"
.sp
-This module can be used to update existing SQL database from the default to the new schema\&. Check the section Default and New Schemas for details\&. Please note that only PostgreSQL is supported\&. When the module is loaded use \fIupdate_sql\fR API\&.
+This module can be used to update existing SQL database from the default to the new schema\&. Check the section \fIdatabase\&.md#default\-and\-new\-schemas|Default and New Schemas\fR for details\&. Please note that only MS SQL, MySQL, and PostgreSQL are supported\&. When the module is loaded use \fIupdate_sql\fR API\&.
.sp
The module has no options\&.
.SS "mod_announce"
.sp
-This module enables configured users to broadcast announcements and to set the message of the day (MOTD)\&. Configured users can perform these actions with an XMPP client either using Ad\-hoc Commands or sending messages to specific JIDs\&.
+This module enables configured users to broadcast announcements and to set the message of the day (MOTD)\&. Configured users can perform these actions with an XMPP client either using Ad\-Hoc Commands or sending messages to specific JIDs\&.
+.if n \{\
.sp
-Note that this module can be resource intensive on large deployments as it may broadcast a lot of messages\&. This module should be disabled for instances of ejabberd with hundreds of thousands users\&.
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
.sp
-The Ad\-hoc Commands are listed in the Server Discovery\&. For this feature to work, \fImod_adhoc\fR must be enabled\&.
+This module can be resource intensive on large deployments as it may broadcast a lot of messages\&. This module should be disabled for instances of ejabberd with hundreds of thousands users\&.
+.sp .5v
+.RE
.sp
-The specific JIDs where messages can be sent are listed below\&. The first JID in each entry will apply only to the specified virtual host example\&.org, while the JID between brackets will apply to all virtual hosts in ejabberd:
+To send announcements using XEP\-0050: Ad\-Hoc Commands, this module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
+.sp
+To send announcements by sending messages to specific JIDs, these are the destination JIDs:
.sp
.RS 4
.ie n \{\
@@ -1983,7 +2307,7 @@ The specific JIDs where messages can be sent are listed below\&. The first JID i
.sp -1
.IP \(bu 2.3
.\}
-example\&.org/announce/all (example\&.org/announce/all\-hosts/all):: The message is sent to all registered users\&. If the user is online and connected to several resources, only the resource with the highest priority will receive the message\&. If the registered user is not connected, the message will be stored offline in assumption that offline storage (see
+\fIexample\&.org/announce/all\fR: Send the message to all registered users in that vhost\&. If the user is online and connected to several resources, only the resource with the highest priority will receive the message\&. If the registered user is not connected, the message is stored offline in assumption that offline storage (see
\fImod_offline\fR) is enabled\&.
.RE
.sp
@@ -1995,7 +2319,7 @@ example\&.org/announce/all (example\&.org/announce/all\-hosts/all):: The message
.sp -1
.IP \(bu 2.3
.\}
-example\&.org/announce/online (example\&.org/announce/all\-hosts/online):: The message is sent to all connected users\&. If the user is online and connected to several resources, all resources will receive the message\&.
+\fIexample\&.org/announce/online\fR: Send the message to all connected users\&. If the user is online and connected to several resources, all resources will receive the message\&.
.RE
.sp
.RS 4
@@ -2006,7 +2330,8 @@ example\&.org/announce/online (example\&.org/announce/all\-hosts/online):: The m
.sp -1
.IP \(bu 2.3
.\}
-example\&.org/announce/motd (example\&.org/announce/all\-hosts/motd):: The message is set as the message of the day (MOTD) and is sent to users when they login\&. In addition the message is sent to all connected users (similar to announce/online)\&.
+\fIexample\&.org/announce/motd\fR: Set the message of the day (MOTD) that is sent to users when they login\&. Also sends the message to all connected users (similar to
+\fIannounce/online\fR)\&.
.RE
.sp
.RS 4
@@ -2017,7 +2342,7 @@ example\&.org/announce/motd (example\&.org/announce/all\-hosts/motd):: The messa
.sp -1
.IP \(bu 2.3
.\}
-example\&.org/announce/motd/update (example\&.org/announce/all\-hosts/motd/update):: The message is set as message of the day (MOTD) and is sent to users when they login\&. The message is not sent to any currently connected user\&.
+\fIexample\&.org/announce/motd/update\fR: Set the message of the day (MOTD) that is sent to users when they login\&. This does not send the message to any currently connected user\&.
.RE
.sp
.RS 4
@@ -2028,7 +2353,64 @@ example\&.org/announce/motd/update (example\&.org/announce/all\-hosts/motd/updat
.sp -1
.IP \(bu 2.3
.\}
-example\&.org/announce/motd/delete (example\&.org/announce/all\-hosts/motd/delete):: Any message sent to this JID removes the existing message of the day (MOTD)\&.
+\fIexample\&.org/announce/motd/delete\fR: Remove the existing message of the day (MOTD) by sending a message to this JID\&.
+.RE
+.sp
+There are similar destination JIDs to apply to all virtual hosts in ejabberd:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIexample\&.org/announce/all\-hosts/all\fR: send to all registered accounts
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIexample\&.org/announce/all\-hosts/online\fR: send to online sessions
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIexample\&.org/announce/all\-hosts/motd\fR: set MOTD and send to online
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIexample\&.org/announce/all\-hosts/motd/update\fR: update MOTD
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+\fIexample\&.org/announce/all\-hosts/motd/delete\fR: delete MOTD
.RE
.sp
.it 1 an-trap
@@ -2081,6 +2463,186 @@ Same as top\-level
option, but applied to this module only\&.
.RE
.RE
+.SS "mod_antispam"
+.sp
+\fINote\fR about this option: added in 25\&.07\&.
+.sp
+Filter spam messages and subscription requests received from remote servers based on Real\-Time Block Lists (RTBL), lists of known spammer JIDs and/or URLs mentioned in spam messages\&. Traffic classified as spam is rejected with an error (and an \fI[info]\fR message is logged) unless the sender is subscribed to the recipient\(cqs presence\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBaccess_spam\fR: \fIAccess\fR
+.RS 4
+Access rule that controls what accounts may receive spam messages\&. If the rule returns
+\fIallow\fR
+for a given recipient, spam messages aren\(cqt rejected for that recipient\&. The default value is
+\fInone\fR, which means that all recipients are subject to spam filtering verification\&.
+.RE
+.PP
+\fBcache_size\fR: \fIpos_integer()\fR
+.RS 4
+Maximum number of JIDs that will be cached due to sending spam URLs\&. If that limit is exceeded, the least recently used entries are removed from the cache\&. Setting this option to
+\fI0\fR
+disables the caching feature\&. Note that separate caches are used for each virtual host, and that the caches aren\(cqt distributed across cluster nodes\&. The default value is
+\fI10000\fR\&.
+.RE
+.PP
+\fBrtbl_services\fR: \fI[Service]\fR
+.RS 4
+Query a RTBL service to get domains to block, as provided by
+xmppbl\&.org\&. Please note right now this option only supports one service in that list\&. For blocking spam and abuse on MUC channels, please use
+\fImod_muc_rtbl\fR
+for now\&. If only the host is provided, the default node names will be assumed\&. If the node name is different than
+\fIspam_source_domains\fR, you can setup the custom node name with the option
+\fIspam_source_domains_node\fR\&. The default value is an empty list of services\&.
+.sp
+\fBExample\fR:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+rtbl_services:
+ \- pubsub\&.server1\&.localhost:
+ spam_source_domains_node: actual_custom_pubsub_node
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+\fBspam_domains_file\fR: \fInone | Path\fR
+.RS 4
+Path to a plain text file containing a list of known spam domains, one domain per line\&. Messages and subscription requests sent from one of the listed domains are classified as spam if sender is not in recipient\(cqs roster\&. This list of domains gets merged with the one retrieved by an RTBL host if any given\&. Use an absolute path, or the
+\fI@CONFIG_PATH@\fR
+predefined keyword
+if the file is available in the configuration directory\&. The default value is
+\fInone\fR\&.
+.RE
+.PP
+\fBspam_dump_file\fR: \fIfalse | true | Path\fR
+.RS 4
+Path to the file to store blocked messages\&. Use an absolute path, or the
+\fI@LOG_PATH@\fR
+predefined keyword
+to store logs in the same place that the other ejabberd log files\&. If set to
+\fIfalse\fR, it doesn\(cqt dump stanzas, which is the default\&. If set to
+\fItrue\fR, it stores in
+\fI"@LOG_PATH@/spam_dump_@HOST@\&.log"\fR\&.
+.RE
+.PP
+\fBspam_jids_file\fR: \fInone | Path\fR
+.RS 4
+Path to a plain text file containing a list of known spammer JIDs, one JID per line\&. Messages and subscription requests sent from one of the listed JIDs are classified as spam\&. Messages containing at least one of the listed JIDsare classified as spam as well\&. Furthermore, the sender\(cqs JID will be cached, so that future traffic originating from that JID will also be classified as spam\&. Use an absolute path, or the
+\fI@CONFIG_PATH@\fR
+predefined keyword
+if the file is available in the configuration directory\&. The default value is
+\fInone\fR\&.
+.RE
+.PP
+\fBspam_urls_file\fR: \fInone | Path\fR
+.RS 4
+Path to a plain text file containing a list of URLs known to be mentioned in spam message bodies\&. Messages containing at least one of the listed URLs are classified as spam\&. Furthermore, the sender\(cqs JID will be cached, so that future traffic originating from that JID will be classified as spam as well\&. Use an absolute path, or the
+\fI@CONFIG_PATH@\fR
+predefined keyword
+if the file is available in the configuration directory\&. The default value is
+\fInone\fR\&.
+.RE
+.PP
+\fBwhitelist_domains_file\fR: \fInone | Path\fR
+.RS 4
+Path to a file containing a list of domains to whitelist from being blocked, one per line\&. If either it is in
+\fIspam_domains_file\fR
+or more realistically in a domain sent by a RTBL host (see option
+\fIrtbl_services\fR) then this domain will be ignored and stanzas from there won\(cqt be blocked\&. Use an absolute path, or the
+\fI@CONFIG_PATH@\fR
+predefined keyword
+if the file is available in the configuration directory\&. The default value is
+\fInone\fR\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+modules:
+ mod_antispam:
+ rtbl_services:
+ \- xmppbl\&.org
+ spam_jids_file: "@CONFIG_PATH@/spam_jids\&.txt"
+ spam_dump_file: "@LOG_PATH@/spam/host\-@HOST@\&.log"
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.SS "mod_auth_fast"
+.sp
+\fINote\fR about this option: added in 24\&.12\&.
+.sp
+The module adds support for XEP\-0484: Fast Authentication Streamlining Tokens that allows users to authenticate using self\-managed tokens\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBdb_type\fR: \fImnesia\fR
+.RS 4
+Same as top\-level
+\fIdefault_db\fR
+option, but applied to this module only\&.
+.RE
+.PP
+\fBtoken_lifetime\fR: \fItimeout()\fR
+.RS 4
+Time that tokens will be kept, measured from it\(cqs creation time\&. Default value set to 30 days
+.RE
+.PP
+\fBtoken_refresh_age\fR: \fItimeout()\fR
+.RS 4
+This time determines age of token, that qualifies for automatic refresh\&. Default value set to 1 day
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+modules:
+ mod_auth_fast:
+ token_lifetime: 14days
+.fi
+.if n \{\
+.RE
+.\}
+.RE
.SS "mod_avatar"
.sp
The purpose of the module is to cope with legacy and modern XMPP clients posting avatars\&. The process is described in XEP\-0398: User Avatar to vCard\-Based Avatars Conversion\&.
@@ -2130,7 +2692,7 @@ Limit any given JID by the number of avatars it is able to convert per minute\&.
.RE
.SS "mod_block_strangers"
.sp
-This module allows to block/log messages coming from an unknown entity\&. If a writing entity is not in your roster, you can let this module drop and/or log the message\&. By default you\(cqll just not receive message from that entity\&. Enable this module if you want to drop SPAM messages\&.
+This module blocks and logs any messages coming from an unknown entity\&. If a writing entity is not in your roster, you can let this module drop and/or log the message\&. By default you\(cqll just not receive message from that entity\&. Enable this module if you want to drop SPAM messages\&.
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -2171,7 +2733,7 @@ and some server\(cqs JID is in user\(cqs roster, then messages from any user of
\fBcaptcha\fR: \fItrue | false\fR
.RS 4
Whether to generate CAPTCHA or not in response to messages from strangers\&. See also section
-CAPTCHA
+\fIbasic\&.md#captcha|CAPTCHA\fR
of the Configuration Guide\&. The default value is
\fIfalse\fR\&.
.RE
@@ -2396,21 +2958,104 @@ While a client is inactive, queue presence stanzas that indicate (un)availabilit
.RE
.SS "mod_configure"
.sp
-The module provides server configuration functionality via XEP\-0050: Ad\-Hoc Commands\&. This module requires \fImod_adhoc\fR to be loaded\&.
+The module provides server configuration functionalities using XEP\-0030: Service Discovery and XEP\-0050: Ad\-Hoc Commands:
.sp
-The module has no options\&.
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+List and discover outgoing s2s, online client sessions and all registered accounts
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Most of the ad\-hoc commands defined in
+XEP\-0133: Service Administration
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Additional custom ad\-hoc commands specific to ejabberd
+.RE
+.sp
+This module requires \fImod_adhoc\fR (to execute the commands), and recommends \fImod_disco\fR (to discover the commands)\&.
+.sp
+Please notice that all the ad\-hoc commands implemented by this module have an equivalent API Command that you can execute using \fImod_adhoc_api\fR or any other API frontend\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBaccess\fR: \fIAccessName\fR
+.RS 4
+\fINote\fR
+about this option: added in 25\&.03\&. This option defines which access rule will be used to control who is allowed to access the features provided by this module\&. The default value is
+\fIconfigure\fR\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+acl:
+ admin:
+ user: sun@localhost
+
+access_rules:
+ configure:
+ allow: admin
+
+modules:
+ mod_configure:
+ access: configure
+.fi
+.if n \{\
+.RE
+.\}
+.RE
.SS "mod_conversejs"
.sp
+\fINote\fR about this option: improved in 25\&.07\&.
+.sp
This module serves a simple page for the Converse XMPP web browser client\&.
.sp
-This module is available since ejabberd 21\&.12\&. Several options were improved in ejabberd 22\&.05\&.
+To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → \fIlisten\-options\&.md#request_handlers|request_handlers\fR\&.
.sp
-To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → request_handlers\&.
-.sp
-Make sure either \fImod_bosh\fR or \fIejabberd_http_ws\fR request_handlers are enabled\&.
+Make sure either \fImod_bosh\fR or \fIlisten\&.md#ejabberd_http_ws|ejabberd_http_ws\fR are enabled in at least one \fIrequest_handlers\fR\&.
.sp
When \fIconversejs_css\fR and \fIconversejs_script\fR are \fIauto\fR, by default they point to the public Converse client\&.
.sp
+This module is available since ejabberd 21\&.12\&.
+.sp
.it 1 an-trap
.nr an-no-space-flag 1
.nr an-break-flag 1
@@ -2435,20 +3080,29 @@ Converse CSS URL\&. The keyword
is replaced with the hostname\&. The default value is
\fIauto\fR\&.
.RE
-.sp
-\fINote\fR about the next option: added in 22\&.05:
.PP
\fBconversejs_options\fR: \fI{Name: Value}\fR
.RS 4
-Specify additional options to be passed to Converse\&. See
+\fINote\fR
+about this option: added in 22\&.05\&. Specify additional options to be passed to Converse\&. See
Converse configuration\&. Only boolean, integer and string values are supported; lists are not supported\&.
.RE
-.sp
-\fINote\fR about the next option: added in 22\&.05:
+.PP
+\fBconversejs_plugins\fR: \fI[Filename]\fR
+.RS 4
+List of additional local files to include as scripts in the homepage\&. Please make sure those files are available in the path specified in
+\fIconversejs_resources\fR
+option, in subdirectory
+\fIplugins/\fR\&. If using the public Converse client, then
+\fI"libsignal"\fR
+gets replaced with the URL of the public library\&. The default value is
+\fI[]\fR\&.
+.RE
.PP
\fBconversejs_resources\fR: \fIPath\fR
.RS 4
-Local path to the Converse files\&. If not set, the public Converse client will be used instead\&.
+\fINote\fR
+about this option: added in 22\&.05\&. Local path to the Converse files\&. If not set, the public Converse client will be used instead\&.
.RE
.PP
\fBconversejs_script\fR: \fIauto | URL\fR
@@ -2469,9 +3123,9 @@ is replaced with the hostname\&. The default value is
.PP
\fBwebsocket_url\fR: \fIauto | WebSocketURL\fR
.RS 4
-A WebSocket URL to which Converse can connect to\&. The keyword
+A WebSocket URL to which Converse can connect to\&. The
\fI@HOST@\fR
-is replaced with the real virtual host name\&. If set to
+keyword is replaced with the real virtual host name\&. If set to
\fIauto\fR, it will build the URL of the first configured WebSocket request handler\&. The default value is
\fIauto\fR\&.
.RE
@@ -2503,6 +3157,7 @@ listen:
modules:
mod_bosh: {}
mod_conversejs:
+ conversejs_plugins: ["libsignal"]
websocket_url: "ws://@HOST@:5280/websocket"
.fi
.if n \{\
@@ -2526,7 +3181,9 @@ listen:
modules:
mod_conversejs:
- conversejs_resources: "/home/ejabberd/conversejs\-9\&.0\&.0/package/dist"
+ conversejs_resources: "/home/ejabberd/conversejs\-x\&.y\&.z/package/dist"
+ conversejs_plugins: ["libsignal\-protocol\&.min\&.js"]
+ # File path is: /home/ejabberd/conversejs\-x\&.y\&.z/package/dist/plugins/libsignal\-protocol\&.min\&.js
.fi
.if n \{\
.RE
@@ -2641,7 +3298,6 @@ acl:
server: sat\-pubsub\&.example\&.org
modules:
- \&.\&.\&.
mod_delegation:
namespaces:
urn:xmpp:mam:1:
@@ -2790,16 +3446,18 @@ hour\&.
The number of C2S authentication failures to trigger the IP ban\&. The default value is
\fI20\fR\&.
.RE
+.sp
+\fBAPI Tags:\fR \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#accounts|accounts\fR
.RE
.SS "mod_host_meta"
.sp
+\fINote\fR about this option: added in 22\&.05\&.
+.sp
This module serves small \fIhost\-meta\fR files as described in XEP\-0156: Discovering Alternative XMPP Connection Methods\&.
.sp
-This module is available since ejabberd 22\&.05\&.
+To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → \fIlisten\-options\&.md#request_handlers|request_handlers\fR\&.
.sp
-To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → request_handlers\&.
-.sp
-Notice it only works if ejabberd_http has tls enabled\&.
+Notice it only works if \fIlisten\&.md#ejabberd_http|ejabberd_http\fR has \fIlisten\-options\&.md#tls|tls\fR enabled\&.
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -2863,15 +3521,31 @@ modules:
.RE
.SS "mod_http_api"
.sp
-This module provides a ReST interface to call ejabberd API commands using JSON data\&.
+This module provides a ReST interface to call \fI\&.\&./\&.\&./developer/ejabberd\-api/index\&.md|ejabberd API\fR commands using JSON data\&.
.sp
-To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → request_handlers\&.
+To use this module, in addition to adding it to the \fImodules\fR section, you must also enable it in \fIlisten\fR → \fIejabberd_http\fR → \fIlisten\-options\&.md#request_handlers|request_handlers\fR\&.
.sp
-To use a specific API version N, when defining the URL path in the request_handlers, add a \fIvN\fR\&. For example: \fI/api/v2: mod_http_api\fR
+To use a specific API version N, when defining the URL path in the request_handlers, add a vN\&. For example: \fI/api/v2: mod_http_api\fR\&.
.sp
-To run a command, send a POST request to the corresponding URL: \fIhttp://localhost:5280/api/\fR
+To run a command, send a POST request to the corresponding URL: \fIhttp://localhost:5280/api/COMMAND\-NAME\fR
.sp
-The module has no options\&.
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBdefault_version\fR: \fIinteger() | string()\fR
+.RS 4
+\fINote\fR
+about this option: added in 24\&.12\&. What API version to use when none is specified in the URL path\&. If setting an ejabberd version, it will use the latest API version that was available in that ejabberd version\&. For example, setting
+\fI"24\&.06"\fR
+in this option implies
+\fI2\fR\&. The default value is the latest version\&.
+.RE
+.RE
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -2893,7 +3567,8 @@ listen:
/api: mod_http_api
modules:
- mod_http_api: {}
+ mod_http_api:
+ default_version: 2
.fi
.if n \{\
.RE
@@ -2984,25 +3659,20 @@ List of accounts that are allowed to use this service\&. Default value:
\fBExamples:\fR
.RS 4
.sp
-This example configuration will serve the files from the local directory \fI/var/www\fR in the address \fIhttp://example\&.org:5280/pub/archive/\fR\&. In this example a new content type \fIogg\fR is defined, \fIpng\fR is redefined, and \fIjpg\fR definition is deleted:
+This example configuration will serve the files from the local directory \fI/var/www\fR in the address \fIhttp://example\&.org:5280/pub/content/\fR\&. In this example a new content type \fIogg\fR is defined, \fIpng\fR is redefined, and \fIjpg\fR definition is deleted:
.sp
.if n \{\
.RS 4
.\}
.nf
listen:
- \&.\&.\&.
\-
port: 5280
module: ejabberd_http
request_handlers:
- \&.\&.\&.
- /pub/archive: mod_http_fileserver
- \&.\&.\&.
- \&.\&.\&.
+ /pub/content: mod_http_fileserver
modules:
- \&.\&.\&.
mod_http_fileserver:
docroot: /var/www
accesslog: /var/log/ejabberd/access\&.log
@@ -3016,7 +3686,6 @@ modules:
\&.ogg: audio/ogg
\&.png: image/png
default_content_type: text/html
- \&.\&.\&.
.fi
.if n \{\
.RE
@@ -3026,7 +3695,7 @@ modules:
.sp
This module allows for requesting permissions to upload a file via HTTP as described in XEP\-0363: HTTP File Upload\&. If the request is accepted, the client receives a URL for uploading the file and another URL from which that file can later be downloaded\&.
.sp
-In order to use this module, it must be enabled in \fIlisten\fR → \fIejabberd_http\fR → request_handlers\&.
+In order to use this module, it must be enabled in \fIlisten\fR → \fIejabberd_http\fR → \fIlisten\-options\&.md#request_handlers|request_handlers\fR\&.
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -3051,26 +3720,34 @@ This option specifies additional header fields to be included in all HTTP respon
.RS 4
This option defines the permission bits of the
\fIdocroot\fR
-directory and any directories created during file uploads\&. The bits are specified as an octal number (see the chmod(1) manual page) within double quotes\&. For example: "0755"\&. The default is undefined, which means no explicit permissions will be set\&.
+directory and any directories created during file uploads\&. The bits are specified as an octal number (see the
+\fIchmod(1)\fR
+manual page) within double quotes\&. For example:
+\fI"0755"\fR\&. The default is undefined, which means no explicit permissions will be set\&.
.RE
.PP
\fBdocroot\fR: \fIPath\fR
.RS 4
-Uploaded files are stored below the directory specified (as an absolute path) with this option\&. The keyword @HOME@ is replaced with the home directory of the user running ejabberd, and the keyword @HOST@ with the virtual host name\&. The default value is "@HOME@/upload"\&.
+Uploaded files are stored below the directory specified (as an absolute path) with this option\&. The keyword
+\fI@HOME@\fR
+is replaced with the home directory of the user running ejabberd, and the keyword
+\fI@HOST@\fR
+with the virtual host name\&. The default value is
+\fI"@HOME@/upload"\fR\&.
.RE
.PP
\fBexternal_secret\fR: \fIText\fR
.RS 4
This option makes it possible to offload all HTTP Upload processing to a separate HTTP server\&. Both ejabberd and the HTTP server should share this secret and behave exactly as described at
-Prosody\(cqs mod_http_upload_external
-in the
-\fIImplementation\fR
-section\&. There is no default value\&.
+Prosody\(cqs mod_http_upload_external: Implementation\&. There is no default value\&.
.RE
.PP
\fBfile_mode\fR: \fIPermission\fR
.RS 4
-This option defines the permission bits of uploaded files\&. The bits are specified as an octal number (see the chmod(1) manual page) within double quotes\&. For example: "0644"\&. The default is undefined, which means no explicit permissions will be set\&.
+This option defines the permission bits of uploaded files\&. The bits are specified as an octal number (see the
+\fIchmod(1)\fR
+manual page) within double quotes\&. For example:
+\fI"0644"\fR\&. The default is undefined, which means no explicit permissions will be set\&.
.RE
.PP
\fBget_url\fR: \fIURL\fR
@@ -3078,8 +3755,9 @@ This option defines the permission bits of uploaded files\&. The bits are specif
This option specifies the initial part of the GET URLs used for downloading the files\&. The default value is
\fIundefined\fR\&. When this option is
\fIundefined\fR, this option is set to the same value as
-\fIput_url\fR\&. The keyword @HOST@ is replaced with the virtual host name\&. NOTE: if GET requests are handled by
-\fImod_http_upload\fR, the
+\fIput_url\fR\&. The keyword
+\fI@HOST@\fR
+is replaced with the virtual host name\&. NOTE: if GET requests are handled by this module, the
\fIget_url\fR
must match the
\fIput_url\fR\&. Setting it to a different value only makes sense if an external web server or
@@ -3098,7 +3776,8 @@ instead\&.
.RS 4
This option defines the Jabber IDs of the service\&. If the
\fIhosts\fR
-option is not specified, the only Jabber ID will be the hostname of the virtual host with the prefix "upload\&."\&. The keyword
+option is not specified, the only Jabber ID will be the hostname of the virtual host with the prefix
+\fI"upload\&."\fR\&. The keyword
\fI@HOST@\fR
is replaced with the real virtual host name\&.
.RE
@@ -3121,12 +3800,18 @@ must be specified\&. The default value is
.PP
\fBname\fR: \fIName\fR
.RS 4
-A name of the service in the Service Discovery\&. This will only be displayed by special XMPP clients\&. The default value is "HTTP File Upload"\&.
+A name of the service in the Service Discovery\&. The default value is
+\fI"HTTP File Upload"\fR\&. Please note this will only be displayed by some XMPP clients\&.
.RE
.PP
\fBput_url\fR: \fIURL\fR
.RS 4
-This option specifies the initial part of the PUT URLs used for file uploads\&. The keyword @HOST@ is replaced with the virtual host name\&. NOTE: different virtual hosts cannot use the same PUT URL\&. The default value is "https://@HOST@:5443/upload"\&.
+This option specifies the initial part of the PUT URLs used for file uploads\&. The keyword
+\fI@HOST@\fR
+is replaced with the virtual host name\&. And
+\fI@HOST_URL_ENCODE@\fR
+is replaced with the host name encoded for URL, useful when your virtual hosts contain non\-latin characters\&. NOTE: different virtual hosts cannot use the same PUT URL\&. The default value is
+\fI"https://@HOST@:5443/upload"\fR\&.
.RE
.PP
\fBrm_on_unregister\fR: \fItrue | false\fR
@@ -3138,7 +3823,9 @@ This option specifies whether files uploaded by a user should be removed when th
\fBsecret_length\fR: \fILength\fR
.RS 4
This option defines the length of the random string included in the GET and PUT URLs generated by
-\fImod_http_upload\fR\&. The minimum length is 8 characters, but it is recommended to choose a larger value\&. The default value is
+\fImod_http_upload\fR\&. The minimum length is
+\fI8\fR
+characters, but it is recommended to choose a larger value\&. The default value is
\fI40\fR\&.
.RE
.PP
@@ -3159,30 +3846,22 @@ A custom vCard of the service that will be displayed by some XMPP clients in Ser
\fIvCard\fR
is a YAML map constructed from an XML representation of vCard\&. Since the representation has no attributes, the mapping is straightforward\&.
.sp
-For example, the following XML representation of vCard:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-
- Conferences
-
-
- Elm Street
-
-
-.fi
-.if n \{\
-.RE
-.\}
-.sp
-will be translated to:
+\fBExample\fR:
.sp
.if n \{\
.RS 4
.\}
.nf
+# This XML representation of vCard:
+#
+# Conferences
+#
+#
+# Elm Street
+#
+#
+#
+# is translated to:
vcard:
fn: Conferences
adr:
@@ -3209,23 +3888,17 @@ vcard:
.\}
.nf
listen:
- \&.\&.\&.
\-
port: 5443
module: ejabberd_http
tls: true
request_handlers:
- \&.\&.\&.
/upload: mod_http_upload
- \&.\&.\&.
- \&.\&.\&.
modules:
- \&.\&.\&.
mod_http_upload:
docroot: /ejabberd/upload
put_url: "https://@HOST@:5443/upload"
- \&.\&.\&.
.fi
.if n \{\
.RE
@@ -3247,7 +3920,7 @@ This module depends on \fImod_http_upload\fR\&.
.PP
\fBaccess_hard_quota\fR: \fIAccessName\fR
.RS 4
-This option defines which access rule is used to specify the "hard quota" for the matching JIDs\&. That rule must yield a positive number for any JID that is supposed to have a quota limit\&. This is the number of megabytes a corresponding user may upload\&. When this threshold is exceeded, ejabberd deletes the oldest files uploaded by that user until their disk usage equals or falls below the specified soft quota (see
+This option defines which access rule is used to specify the "hard quota" for the matching JIDs\&. That rule must yield a positive number for any JID that is supposed to have a quota limit\&. This is the number of megabytes a corresponding user may upload\&. When this threshold is exceeded, ejabberd deletes the oldest files uploaded by that user until their disk usage equals or falls below the specified soft quota (see also option
\fIaccess_soft_quota\fR)\&. The default value is
\fIhard_upload_quota\fR\&.
.RE
@@ -3277,26 +3950,22 @@ directory, once per day\&. The default value is
\fBExamples:\fR
.RS 4
.sp
-Please note that it\(cqs not necessary to specify the \fIaccess_hard_quota\fR and \fIaccess_soft_quota\fR options in order to use the quota feature\&. You can stick to the default names and just specify access rules such as those in this example:
+Notice it\(cqs not necessary to specify the \fIaccess_hard_quota\fR and \fIaccess_soft_quota\fR options in order to use the quota feature\&. You can stick to the default names and just specify access rules such as those in this example:
.sp
.if n \{\
.RS 4
.\}
.nf
shaper_rules:
- \&.\&.\&.
soft_upload_quota:
1000: all # MiB
hard_upload_quota:
1100: all # MiB
- \&.\&.\&.
modules:
- \&.\&.\&.
mod_http_upload: {}
mod_http_upload_quota:
max_days: 100
- \&.\&.\&.
.fi
.if n \{\
.RE
@@ -3390,7 +4059,23 @@ This type of authentication was obsoleted in 2008 and you unlikely need this mod
The module has no options\&.
.SS "mod_mam"
.sp
-This module implements XEP\-0313: Message Archive Management\&. Compatible XMPP clients can use it to store their chat history on the server\&.
+This module implements XEP\-0313: Message Archive Management and XEP\-0441: Message Archive Management Preferences\&. Compatible XMPP clients can use it to store their chat history on the server\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+.sp
+Mnesia backend for mod_mam is not recommended: it\(cqs limited to 2GB and often gets corrupted when reaching this limit\&. SQL backend is recommended\&. Namely, for small servers SQLite is a preferred choice because it\(cqs very easy to configure\&.
+.sp .5v
+.RE
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -3485,9 +4170,113 @@ option, but applied to this module only\&.
.PP
\fBuser_mucsub_from_muc_archive\fR: \fItrue | false\fR
.RS 4
-When this option is disabled, for each individual subscriber a separa mucsub message is stored\&. With this option enabled, when a user fetches archive virtual mucsub, messages are generated from muc archives\&. The default value is
+When this option is disabled, for each individual subscriber a separate mucsub message is stored\&. With this option enabled, when a user fetches archive virtual mucsub, messages are generated from muc archives\&. The default value is
\fIfalse\fR\&.
.RE
+.sp
+\fBAPI Tags:\fR \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#mam|mam\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#purge|purge\fR
+.RE
+.SS "mod_matrix_gw 🟤"
+.sp
+\fINote\fR about this option: improved in 25\&.08\&.
+.sp
+Matrix gateway\&. Supports room versions 9, 10 and 11 since ejabberd 25\&.03; room versions 4 and higher since ejabberd 25\&.07; room version 12 (hydra rooms) since ejabberd 25\&.08\&. Erlang/OTP 25 or higher is required to use this module\&. This module is available since ejabberd 24\&.02\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBhost\fR: \fIHost\fR
+.RS 4
+This option defines the Jabber IDs of the service\&. If the
+\fIhost\fR
+option is not specified, the Jabber ID will be the hostname of the virtual host with the prefix
+\fI"matrix\&."\fR\&. The keyword
+\fI@HOST@\fR
+is replaced with the real virtual host name\&.
+.RE
+.PP
+\fBkey\fR: \fIstring()\fR
+.RS 4
+Value of the matrix signing key, in base64\&.
+.RE
+.PP
+\fBkey_name\fR: \fIstring()\fR
+.RS 4
+Name of the matrix signing key\&.
+.RE
+.PP
+\fBleave_timeout\fR: \fIinteger()\fR
+.RS 4
+Delay in seconds between a user leaving a MUC room and sending
+\fIleave\fR
+Matrix event\&.
+.RE
+.PP
+\fBmatrix_domain\fR: \fIDomain\fR
+.RS 4
+Specify a domain in the Matrix federation\&. The keyword
+\fI@HOST@\fR
+is replaced with the hostname\&. The default value is
+\fI@HOST@\fR\&.
+.RE
+.PP
+\fBmatrix_id_as_jid\fR: \fItrue | false\fR
+.RS 4
+If set to
+\fItrue\fR, all packets failing to be delivered via an XMPP server\-to\-server connection will then be routed to the Matrix gateway by translating a Jabber ID
+\fIuser@matrixdomain\&.tld\fR
+to a Matrix user identifier
+\fI@user:matrixdomain\&.tld\fR\&. When set to
+\fIfalse\fR, messages must be explicitly sent to the matrix gateway service Jabber ID to be routed to a remote Matrix server\&. In this case, to send a message to Matrix user
+\fI@user:matrixdomain\&.tld\fR, the client must send a message to the JID
+\fIuser%\fR\fImatrixdomain\&.tld@matrix\&.myxmppdomain\fR\fI\&.tld\fR, where
+\fImatrix\&.myxmppdomain\&.tld\fR
+is the JID of the gateway service as set by the
+\fIhost\fR
+option\&. The default is
+\fIfalse\fR\&.
+.RE
+.PP
+\fBnotary_servers\fR: \fI[Server, \&.\&.\&.]\fR
+.RS 4
+A list of notary servers\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+listen:
+ \-
+ port: 8448
+ module: ejabberd_http
+ tls: true
+ request_handlers:
+ "/_matrix": mod_matrix_gw
+
+modules:
+ mod_matrix_gw:
+ key_name: "key1"
+ key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ matrix_id_as_jid: true
+.fi
+.if n \{\
+.RE
+.\}
.RE
.SS "mod_metrics"
.sp
@@ -3616,9 +4405,11 @@ An internet port number at which the backend is listening for incoming connectio
.RE
.SS "mod_mix"
.sp
-This module is an experimental implementation of XEP\-0369: Mediated Information eXchange (MIX)\&. MIX support was added in ejabberd 16\&.03 as an experimental feature, updated in 19\&.02, and is not yet ready to use in production\&. It\(cqs asserted that the MIX protocol is going to replace the MUC protocol in the future (see \fImod_muc\fR)\&.
+\fINote\fR about this option: added in 16\&.03 and improved in 19\&.02\&.
.sp
-To learn more about how to use that feature, you can refer to our tutorial: Getting started with XEP\-0369: Mediated Information eXchange (MIX) v0\&.1\&.
+This module is an experimental implementation of XEP\-0369: Mediated Information eXchange (MIX)\&. It\(cqs asserted that the MIX protocol is going to replace the MUC protocol in the future (see \fImod_muc\fR)\&.
+.sp
+To learn more about how to use that feature, you can refer to our tutorial: \fI\&.\&./\&.\&./tutorials/mix\-010\&.md|Getting started with MIX\fR
.sp
The module depends on \fImod_mam\fR\&.
.sp
@@ -3654,7 +4445,8 @@ instead\&.
.RS 4
This option defines the Jabber IDs of the service\&. If the
\fIhosts\fR
-option is not specified, the only Jabber ID will be the hostname of the virtual host with the prefix "mix\&."\&. The keyword
+option is not specified, the only Jabber ID will be the hostname of the virtual host with the prefix
+\fI"mix\&."\fR\&. The keyword
\fI@HOST@\fR
is replaced with the real virtual host name\&.
.RE
@@ -3730,7 +4522,7 @@ option, but applied to this module only\&.
.RE
.SS "mod_mqtt"
.sp
-This module adds support for the MQTT protocol version \fI3\&.1\&.1\fR and \fI5\&.0\fR\&. Remember to configure \fImod_mqtt\fR in \fImodules\fR and \fIlisten\fR sections\&.
+This module adds \fI\&.\&./guide/mqtt/index\&.md|support for the MQTT\fR protocol version \fI3\&.1\&.1\fR and \fI5\&.0\fR\&. Remember to configure \fImod_mqtt\fR in \fImodules\fR and \fIlisten\fR sections\&.
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -3832,12 +4624,97 @@ Same as top\-level
option, but applied to this module only\&.
.RE
.RE
+.SS "mod_mqtt_bridge"
+.sp
+This module adds ability to synchronize local MQTT topics with data on remote servers It can update topics on remote servers when local user updates local topic, or can subscribe for changes on remote server, and update local copy when remote data is updated\&. It is available since ejabberd 23\&.01\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBreplication_user\fR: \fIJID\fR
+.RS 4
+Identifier of a user that will be assigned as owner of local changes\&.
+.RE
+.PP
+\fBservers\fR: \fI{ServerUrl: {Key: Value}}\fR
+.RS 4
+Declaration of data to share for each ServerUrl\&. Server URLs can use schemas:
+\fImqtt\fR,
+\fImqtts\fR
+(mqtt with tls),
+\fImqtt5\fR,
+\fImqtt5s\fR
+(both to trigger v5 protocol),
+\fIws\fR,
+\fIwss\fR,
+\fIws5\fR,
+\fIwss5\fR\&. Keys must be:
+.PP
+\fBauthentication\fR: \fI{AuthKey: AuthValue}\fR
+.RS 4
+List of authentication information, where AuthKey can be:
+\fIusername\fR
+and
+\fIpassword\fR
+fields, or
+\fIcertfile\fR
+pointing to client certificate\&. Certificate authentication can be used only with mqtts, mqtt5s, wss, wss5\&.
+.RE
+.PP
+\fBpublish\fR: \fI{LocalTopic: RemoteTopic}\fR
+.RS 4
+Either publish or subscribe must be set, or both\&.
+.RE
+.PP
+\fBsubscribe\fR: \fI{RemoteTopic: LocalTopic}\fR
+.RS 4
+Either publish or subscribe must be set, or both\&.
+.RE
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBExample:\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+modules:
+ mod_mqtt_bridge:
+ replication_user: "mqtt@xmpp\&.server\&.com"
+ servers:
+ "mqtt://server\&.com":
+ authentication:
+ certfile: "/etc/ejabberd/mqtt_server\&.pem"
+ publish:
+ "localA": "remoteA" # local changes to \*(AqlocalA\*(Aq will be replicated on remote server as \*(AqremoteA\*(Aq
+ "topicB": "topicB"
+ subscribe:
+ "remoteB": "localB" # changes to \*(AqremoteB\*(Aq on remote server will be stored as \*(AqlocalB\*(Aq on local server
+.fi
+.if n \{\
+.RE
+.\}
+.RE
.SS "mod_muc"
.sp
This module provides support for XEP\-0045: Multi\-User Chat\&. Users can discover existing rooms, join or create them\&. Occupants of a room can chat in public or have private chats\&.
.sp
The MUC service allows any Jabber ID to register a nickname, so nobody else can use that nickname in any room in the MUC service\&. To register a nickname, open the Service Discovery in your XMPP client and register in the MUC service\&.
.sp
+It is also possible to register a nickname in a room, so nobody else can use that nickname in that room\&. If a nick is registered in the MUC service, that nick cannot be registered in any room, and vice versa: a nick that is registered in a room cannot be registered at the MUC service\&.
+.sp
This module supports clustering and load balancing\&. One module can be started per cluster node\&. Rooms are distributed at creation time on all available MUC module instances\&. The multi\-user chat module is clustered but the rooms themselves are not clustered nor fault\-tolerant: if the node managing a set of rooms goes down, the rooms disappear and they will be recreated on an available node on first connection attempt\&.
.sp
.it 1 an-trap
@@ -3883,16 +4760,16 @@ room option\&. The default value is
.PP
\fBaccess_register\fR: \fIAccessName\fR
.RS 4
-This option specifies who is allowed to register nickname within the Multi\-User Chat service\&. The default is
+\fINote\fR
+about this option: improved in 23\&.10\&. This option specifies who is allowed to register nickname within the Multi\-User Chat service and rooms\&. The default is
\fIall\fR
-for backward compatibility, which means that any user is allowed to register any free nick\&.
+for backward compatibility, which means that any user is allowed to register any free nick in the MUC service and in the rooms\&.
.RE
-.sp
-\fINote\fR about the next option: added in 22\&.05:
.PP
\fBcleanup_affiliations_on_start\fR: \fItrue | false\fR
.RS 4
-Remove affiliations for non\-existing local users on startup\&. The default value is
+\fINote\fR
+about this option: added in 22\&.05\&. Remove affiliations for non\-existing local users on startup\&. The default value is
\fIfalse\fR\&.
.RE
.PP
@@ -3902,12 +4779,10 @@ Same as top\-level
\fIdefault_db\fR
option, but applied to this module only\&.
.RE
-.sp
-\fINote\fR about the next option: improved in 22\&.05:
.PP
\fBdefault_room_options\fR: \fIOptions\fR
.RS 4
-This option allows to define the desired default room options\&. Note that the creator of a room can modify the options of his room at any time using an XMPP client with MUC capability\&. The
+Define the default room options\&. Note that the creator of a room can modify the options of his room at any time using an XMPP client with MUC capability\&. The
\fIOptions\fR
are:
.PP
@@ -3917,12 +4792,6 @@ Allow occupants to change the subject\&. The default value is
\fItrue\fR\&.
.RE
.PP
-\fBallow_private_messages\fR: \fItrue | false\fR
-.RS 4
-Occupants can send private messages to other occupants\&. The default value is
-\fItrue\fR\&.
-.RE
-.PP
\fBallow_private_messages_from_visitors\fR: \fIanyone | moderators | nobody\fR
.RS 4
Visitors can send private messages to other occupants\&. The default value is
@@ -3939,7 +4808,7 @@ Occupants can send IQ queries to other occupants\&. The default value is
\fBallow_subscription\fR: \fItrue | false\fR
.RS 4
Allow users to subscribe to room events as described in
-Multi\-User Chat Subscriptions\&. The default value is
+\fI\&.\&./\&.\&./developer/xmpp\-clients\-bots/extensions/muc\-sub\&.md|Multi\-User Chat Subscriptions\fR\&. The default value is
\fIfalse\fR\&.
.RE
.PP
@@ -3967,6 +4836,12 @@ Allow visitors in a moderated room to request voice\&. The default value is
\fItrue\fR\&.
.RE
.PP
+\fBallowpm\fR: \fIanyone | participants | moderators | none\fR
+.RS 4
+Who can send private messages\&. The default value is
+\fIanyone\fR\&.
+.RE
+.PP
\fBanonymous\fR: \fItrue | false\fR
.RS 4
The room is anonymous: occupants don\(cqt see the real JIDs of other occupants\&. Note that the room moderators can always see the real JIDs of the occupants\&. The default value is
@@ -3976,7 +4851,7 @@ The room is anonymous: occupants don\(cqt see the real JIDs of other occupants\&
\fBcaptcha_protected\fR: \fItrue | false\fR
.RS 4
When a user tries to join a room where they have no affiliation (not owner, admin or member), the room requires them to fill a CAPTCHA challenge (see section
-CAPTCHA
+\fIbasic\&.md#captcha|CAPTCHA\fR
in order to accept their join in the room\&. The default value is
\fIfalse\fR\&.
.RE
@@ -3988,7 +4863,10 @@ Short description of the room\&. The default value is an empty string\&.
.PP
\fBenable_hats\fR: \fItrue | false\fR
.RS 4
-Allow extended roles as defined in XEP\-0317 Hats\&. The default value is
+\fINote\fR
+about this option: improved in 25\&.03\&. Allow extended roles as defined in XEP\-0317 Hats\&. Check the
+\fI\&.\&./\&.\&./tutorials/muc\-hats\&.md|MUC Hats\fR
+tutorial\&. The default value is
\fIfalse\fR\&.
.RE
.PP
@@ -4054,7 +4932,7 @@ The room persists even if the last participant leaves\&. The default value is
\fIfalse\fR\&.
.RE
.PP
-\fBpresence_broadcast\fR: \fI[moderator | participant | visitor, \&.\&.\&.]\fR
+\fBpresence_broadcast\fR: \fI[Role]\fR
.RS 4
List of roles for which presence is broadcasted\&. The list can contain one or several of:
\fImoderator\fR,
@@ -4104,6 +4982,12 @@ A human\-readable title of the room\&. There is no default value
A custom vCard for the room\&. See the equivalent mod_muc option\&.The default value is an empty string\&.
.RE
.PP
+\fBvcard_xupdate\fR: \fIundefined | external | AvatarHash\fR
+.RS 4
+Set the hash of the avatar image\&. The default value is
+\fIundefined\fR\&.
+.RE
+.PP
\fBvoice_request_min_interval\fR: \fINumber\fR
.RS 4
Minimum interval between voice requests, in seconds\&. The default value is
@@ -4119,7 +5003,10 @@ Timeout before hibernating the room process, expressed in seconds\&. The default
.PP
\fBhistory_size\fR: \fISize\fR
.RS 4
-A small history of the current discussion is sent to users when they enter the room\&. With this option you can define the number of history messages to keep and send to users joining the room\&. The value is a non\-negative integer\&. Setting the value to 0 disables the history feature and, as a result, nothing is kept in memory\&. The default value is 20\&. This value affects all rooms on the service\&. NOTE: modern XMPP clients rely on Message Archives (XEP\-0313), so feel free to disable the history feature if you\(cqre only using modern clients and have
+A small history of the current discussion is sent to users when they enter the room\&. With this option you can define the number of history messages to keep and send to users joining the room\&. The value is a non\-negative integer\&. Setting the value to
+\fI0\fR
+disables the history feature and, as a result, nothing is kept in memory\&. The default value is
+\fI20\fR\&. This value affects all rooms on the service\&. NOTE: modern XMPP clients rely on Message Archives (XEP\-0313), so feel free to disable the history feature if you\(cqre only using modern clients and have
\fImod_mam\fR
module loaded\&.
.RE
@@ -4139,20 +5026,18 @@ option is not specified, the only Jabber ID will be the hostname of the virtual
\fI@HOST@\fR
is replaced with the real virtual host name\&.
.RE
-.sp
-\fINote\fR about the next option: added in 21\&.01:
.PP
\fBmax_captcha_whitelist\fR: \fINumber\fR
.RS 4
-This option defines the maximum number of characters that Captcha Whitelist can have when configuring the room\&. The default value is
+\fINote\fR
+about this option: added in 21\&.01\&. This option defines the maximum number of characters that Captcha Whitelist can have when configuring the room\&. The default value is
\fIinfinity\fR\&.
.RE
-.sp
-\fINote\fR about the next option: added in 21\&.01:
.PP
\fBmax_password\fR: \fINumber\fR
.RS 4
-This option defines the maximum number of characters that Password can have when configuring the room\&. The default value is
+\fINote\fR
+about this option: added in 21\&.01\&. This option defines the maximum number of characters that Password can have when configuring the room\&. The default value is
\fIinfinity\fR\&.
.RE
.PP
@@ -4201,18 +5086,22 @@ This option defines the number of service admins or room owners allowed to enter
.PP
\fBmax_users_presence\fR: \fINumber\fR
.RS 4
-This option defines after how many users in the room, it is considered overcrowded\&. When a MUC room is considered overcrowed, presence broadcasts are limited to reduce load, traffic and excessive presence "storm" received by participants\&. The default value is
+This option defines after how many users in the room, it is considered overcrowded\&. When a MUC room is considered overcrowded, presence broadcasts are limited to reduce load, traffic and excessive presence "storm" received by participants\&. The default value is
\fI1000\fR\&.
.RE
.PP
\fBmin_message_interval\fR: \fINumber\fR
.RS 4
-This option defines the minimum interval between two messages send by an occupant in seconds\&. This option is global and valid for all rooms\&. A decimal value can be used\&. When this option is not defined, message rate is not limited\&. This feature can be used to protect a MUC service from occupant abuses and limit number of messages that will be broadcasted by the service\&. A good value for this minimum message interval is 0\&.4 second\&. If an occupant tries to send messages faster, an error is send back explaining that the message has been discarded and describing the reason why the message is not acceptable\&.
+This option defines the minimum interval between two messages send by an occupant in seconds\&. This option is global and valid for all rooms\&. A decimal value can be used\&. When this option is not defined, message rate is not limited\&. This feature can be used to protect a MUC service from occupant abuses and limit number of messages that will be broadcasted by the service\&. A good value for this minimum message interval is
+\fI0\&.4\fR
+second\&. If an occupant tries to send messages faster, an error is send back explaining that the message has been discarded and describing the reason why the message is not acceptable\&.
.RE
.PP
\fBmin_presence_interval\fR: \fINumber\fR
.RS 4
-This option defines the minimum of time between presence changes coming from a given occupant in seconds\&. This option is global and valid for all rooms\&. A decimal value can be used\&. When this option is not defined, no restriction is applied\&. This option can be used to protect a MUC service for occupants abuses\&. If an occupant tries to change its presence more often than the specified interval, the presence is cached by ejabberd and only the last presence is broadcasted to all occupants in the room after expiration of the interval delay\&. Intermediate presence packets are silently discarded\&. A good value for this option is 4 seconds\&.
+This option defines the minimum of time between presence changes coming from a given occupant in seconds\&. This option is global and valid for all rooms\&. A decimal value can be used\&. When this option is not defined, no restriction is applied\&. This option can be used to protect a MUC service for occupants abuses\&. If an occupant tries to change its presence more often than the specified interval, the presence is cached by ejabberd and only the last presence is broadcasted to all occupants in the room after expiration of the interval delay\&. Intermediate presence packets are silently discarded\&. A good value for this option is
+\fI4\fR
+seconds\&.
.RE
.PP
\fBname\fR: \fIstring()\fR
@@ -4271,30 +5160,22 @@ A custom vCard of the service that will be displayed by some XMPP clients in Ser
\fIvCard\fR
is a YAML map constructed from an XML representation of vCard\&. Since the representation has no attributes, the mapping is straightforward\&.
.sp
-For example, the following XML representation of vCard:
-.sp
-.if n \{\
-.RS 4
-.\}
-.nf
-
- Conferences
-
-
- Elm Street
-
-
-.fi
-.if n \{\
-.RE
-.\}
-.sp
-will be translated to:
+\fBExample\fR:
.sp
.if n \{\
.RS 4
.\}
.nf
+# This XML representation of vCard:
+#
+# Conferences
+#
+#
+# Elm Street
+#
+#
+#
+# is translated to:
vcard:
fn: Conferences
adr:
@@ -4320,16 +5201,17 @@ This module depends on \fImod_muc\fR\&.
.ps +1
\fBAvailable options:\fR
.RS 4
-.sp
-\fINote\fR about the next option: added in 22\&.05:
.PP
\fBsubscribe_room_many_max_users\fR: \fINumber\fR
.RS 4
-How many users can be subscribed to a room at once using the
+\fINote\fR
+about this option: added in 22\&.05\&. How many users can be subscribed to a room at once using the
\fIsubscribe_room_many\fR
-command\&. The default value is
+API\&. The default value is
\fI50\fR\&.
.RE
+.sp
+\fBAPI Tags:\fR \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#muc|muc\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#muc_room|muc_room\fR, \fI\&.\&./\&.\&./developer/ejabberd\-api/admin\-tags\&.md#muc_sub|muc_sub\fR
.RE
.SS "mod_muc_log"
.sp
@@ -4489,7 +5371,7 @@ to a remote file\&. By default a predefined CSS will be embedded into the HTML p
.PP
\fBdirname\fR: \fIroom_jid | room_name\fR
.RS 4
-Allows to configure the name of the room directory\&. If set to
+Configure the name of the room directory\&. If set to
\fIroom_jid\fR, the room directory name will be the full room JID\&. Otherwise, the room directory name will be only the room name, not including the MUC service name\&. The default value is
\fIroom_jid\fR\&.
.RE
@@ -4583,6 +5465,43 @@ or a conference JID is appended to the
otherwise\&. There is no default value\&.
.RE
.RE
+.SS "mod_muc_occupantid"
+.sp
+\fINote\fR about this option: added in 23\&.10\&.
+.sp
+This module implements XEP\-0421: Anonymous unique occupant identifiers for MUCs\&.
+.sp
+When the module is enabled, the feature is enabled in all semi\-anonymous rooms\&.
+.sp
+The module has no options\&.
+.SS "mod_muc_rtbl"
+.sp
+\fINote\fR about this option: added in 23\&.04\&.
+.sp
+This module implement Real\-time blocklists for MUC rooms\&.
+.sp
+It works by observing remote pubsub node conforming with specification described in https://xmppbl\&.org/\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBAvailable options:\fR
+.RS 4
+.PP
+\fBrtbl_node\fR: \fIPubsubNodeName\fR
+.RS 4
+Name of pubsub node that should be used to track blocked users\&. The default value is
+\fImuc_bans_sha256\fR\&.
+.RE
+.PP
+\fBrtbl_server\fR: \fIDomain\fR
+.RS 4
+Domain of xmpp server that serves block list\&. The default value is
+\fIxmppbl\&.org\fR
+.RE
+.RE
.SS "mod_multicast"
.sp
This module implements a service for XEP\-0033: Extended Stanza Addressing\&.
@@ -4748,22 +5667,8 @@ modules:
.SS "mod_offline"
.sp
This module implements XEP\-0160: Best Practices for Handling Offline Messages and XEP\-0013: Flexible Offline Message Retrieval\&. This means that all messages sent to an offline user will be stored on the server until that user comes online again\&. Thus it is very similar to how email works\&. A user is considered offline if no session presence priority > 0 are currently open\&.
-.if n \{\
.sp
-.\}
-.RS 4
-.it 1 an-trap
-.nr an-no-space-flag 1
-.nr an-break-flag 1
-.br
-.ps +1
-\fBNote\fR
-.ps -1
-.br
-.sp
-\fIejabberdctl\fR has a command to delete expired messages (see chapter Managing an ejabberd server in online documentation\&.
-.sp .5v
-.RE
+The \fIdelete_expired_messages\fR API allows to delete expired messages, and \fIdelete_old_messages\fR API deletes older ones\&.
.sp
.it 1 an-trap
.nr an-no-space-flag 1
@@ -4775,15 +5680,17 @@ This module implements XEP\-0160: Best Practices for Handling Offline Messages a
.PP
\fBaccess_max_user_messages\fR: \fIAccessName\fR
.RS 4
-This option defines which access rule will be enforced to limit the maximum number of offline messages that a user can have (quota)\&. When a user has too many offline messages, any new messages that they receive are discarded, and a error is returned to the sender\&. The default value is
+This option defines which access rule will be enforced to limit the maximum number of offline messages that a user can have (quota)\&. When a user has too many offline messages, any new messages that they receive are discarded, and a
+\fI\fR
+error is returned to the sender\&. The default value is
\fImax_user_offline_messages\fR\&.
.RE
.PP
\fBbounce_groupchat\fR: \fItrue | false\fR
.RS 4
-This option is use the disable an optimisation that avoids bouncing error messages when groupchat messages could not be stored as offline\&. It will reduce chat room load, without any drawback in standard use cases\&. You may change default value only if you have a custom module which uses offline hook after
+This option is use the disable an optimization that avoids bouncing error messages when groupchat messages could not be stored as offline\&. It will reduce chat room load, without any drawback in standard use cases\&. You may change default value only if you have a custom module which uses offline hook after
\fImod_offline\fR\&. This option can be useful for both standard MUC and MucSub, but the bounce is much more likely to happen in the context of MucSub, so it is even more important to have it on large MucSub services\&. The default value is
-\fIfalse\fR, meaning the optimisation is enabled\&.
+\fIfalse\fR, meaning the optimization is enabled\&.
.RE
.PP
\fBcache_life_time\fR: \fItimeout()\fR
@@ -4809,8 +5716,12 @@ option, but applied to this module only\&.
.PP
\fBstore_empty_body\fR: \fItrue | false | unless_chat_state\fR
.RS 4
-Whether or not to store messages that lack a element\&. The default value is
-\fIunless_chat_state\fR, which tells ejabberd to store messages even if they lack the element, unless they only contain a chat state notification (as defined in
+Whether or not to store messages that lack a
+\fI\fR
+element\&. The default value is
+\fIunless_chat_state\fR, which tells ejabberd to store messages even if they lack the
+\fI