ejabberd
Container Image¶
ejabberd is an open-source, robust, scalable and extensible realtime platform built using Erlang/OTP, that includes XMPP Server, MQTT Broker and SIP Service.
This document explains how to use the ejabberd
container image available in
ghcr.io/processone/ejabberd,
built using the files in .github/container/
.
This image is based in Alpine 3.19, includes Erlang/OTP 26.2 and Elixir 1.16.1.
Alternatively, there is also the ecs
container image available in
docker.io/ejabberd/ecs,
built using the
docker-ejabberd/ecs
repository.
Check the differences between ejabberd
and ecs
images.
If you are using a Windows operating system, check the tutorials mentioned in ejabberd Docs > Docker Image.
Start ejabberd¶
With default configuration¶
Start ejabberd in a new container:
That runs the container as a daemon, using ejabberd default configuration file and XMPP domain "localhost".
Stop the running container:
Restart the stopped ejabberd container:
Start with Erlang console attached¶
Start ejabberd with an Erlang console attached using the live
command:
That uses the default configuration file and XMPP domain "localhost".
Start with your configuration and database¶
Pass a configuration file as a volume and share the local directory to store database:
mkdir database
chown ejabberd database
cp ejabberd.yml.example ejabberd.yml
docker run --name ejabberd -it \
-v $(pwd)/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml \
-v $(pwd)/database:/opt/ejabberd/database \
-p 5222:5222 ghcr.io/processone/ejabberd live
Notice that ejabberd runs in the container with an account named ejabberd
,
and the volumes you mount must grant proper rights to that account.
Next steps¶
Register the administrator account¶
The default ejabberd configuration does not grant admin privileges to any account, you may want to register a new account in ejabberd and grant it admin rights.
Register an account using the ejabberdctl
script:
Then edit conf/ejabberd.yml and add the ACL as explained in ejabberd Docs: Administration Account
Check ejabberd log files¶
Check the content of the log files inside the container, even if you do not put it on a shared persistent drive:
Inspect the container files¶
The container uses Alpine Linux. Start a shell inside the container:
Open ejabberd debug console¶
Open an interactive debug Erlang console attached to a running ejabberd in a running container:
CAPTCHA¶
ejabberd includes two example CAPTCHA scripts. If you want to use any of them, first install some additional required libraries:
Now update your ejabberd configuration file, for example:
and add this option:
Finally, reload the configuration file or restart the container:
If the CAPTCHA image is not visible, there may be a problem generating it (the ejabberd log file may show some error message); or the image URL may not be correctly detected by ejabberd, in that case you can set the correct URL manually, for example:
For more details about CAPTCHA options, please check the CAPTCHA documentation section.
Advanced Container Configuration¶
Ports¶
This container image exposes the ports:
5222
: The default port for XMPP clients.5269
: For XMPP federation. Only needed if you want to communicate with users on other servers.5280
: For admin interface.5443
: With encryption, used for admin interface, API, CAPTCHA, OAuth, Websockets and XMPP BOSH.1883
: Used for MQTT4369-4399
: EPMD and Erlang connectivity, used forejabberdctl
and clustering5210
: Erlang connectivity whenERL_DIST_PORT
is set, alternative to EPMD
Volumes¶
ejabberd produces two types of data: log files and database spool files (Mnesia). This is the kind of data you probably want to store on a persistent or local drive (at least the database).
The volumes you may want to map:
/opt/ejabberd/conf/
: Directory containing configuration and certificates/opt/ejabberd/database/
: Directory containing Mnesia database. You should back up or export the content of the directory to persistent storage (host storage, local storage, any storage plugin)/opt/ejabberd/logs/
: Directory containing log files/opt/ejabberd/upload/
: Directory containing uploaded files. This should also be backed up.
All these files are owned by ejabberd
user inside the container.
It's possible to install additional ejabberd modules using volumes, this comment explains how to install an additional module using docker-compose.
Commands on start¶
The ejabberdctl script reads the CTL_ON_CREATE
environment variable
the first time the container is started,
and reads CTL_ON_START
every time the container is started.
Those variables can contain one ejabberdctl command,
or several commands separated with the blankspace and ;
characters.
By default failure of any of commands executed that way would
abort start, this can be disabled by prefixing commands with !
Example usage (or check the full example):
environment:
- CTL_ON_CREATE=! register admin localhost asd
- CTL_ON_START=stats registeredusers ;
check_password admin localhost asd ;
status
Clustering¶
When setting several containers to form a cluster of ejabberd nodes, each one must have a different Erlang Node Name and the same Erlang Cookie.
For this you can either:
- edit conf/ejabberdctl.cfg
and set variables ERLANG_NODE
and ERLANG_COOKIE
- set the environment variables ERLANG_NODE_ARG
and ERLANG_COOKIE
Example to connect a local ejabberdctl
to a containerized ejabberd:
1. When creating the container, export port 5210, and set ERLANG_COOKIE
:
docker run --name ejabberd -it \
-e ERLANG_COOKIE=`cat $HOME/.erlang.cookie` \
-p 5210:5210 -p 5222:5222 \
ghcr.io/processone/ejabberd
ERL_DIST_PORT=5210
in ejabberdctl.cfg of container and local ejabberd
3. Restart the container
4. Now use ejabberdctl
in your local ejabberd deployment
To connect using a local ejabberd
script:
Example using environment variables (see full example docker-compose.yml):
Build a Container Image¶
This container image includes ejabberd as a standalone OTP release built using Elixir. That OTP release is configured with:
mix.exs
: Customize ejabberd releasevars.config
: ejabberd compilation configuration optionsconfig/runtime.exs
: Customize ejabberd pathsejabberd.yml.template
: ejabberd default config file
Direct build¶
Build ejabberd Community Server container image from ejabberd master git repository:
Podman build¶
It's also possible to use podman instead of docker, just notice:
- EXPOSE 4369-4399
port range is not supported, remove that in Dockerfile
- It mentions that healthcheck
is not supported by the Open Container Initiative image format
- to start with command live
, you may want to add environment variable EJABBERD_BYPASS_WARNINGS=true
podman build \
-t ejabberd \
-f .github/container/Dockerfile \
.
podman run --name eja1 -d -p 5222:5222 localhost/ejabberd
podman exec eja1 ejabberdctl status
podman exec -it eja1 sh
podman stop eja1
podman run --name eja1 -it -e EJABBERD_BYPASS_WARNINGS=true -p 5222:5222 localhost/ejabberd live
Package build for arm64
¶
By default, .github/container/Dockerfile
builds this container by directly compiling ejabberd,
it is a fast and direct method.
However, a problem with QEMU prevents building the container in QEMU using Erlang/OTP 25
for the arm64
architecture.
Providing --build-arg METHOD=package
is an alternate method to build the container
used by the Github Actions workflow that provides amd64
and arm64
container images.
It first builds an ejabberd binary package, and later installs it in the image.
That method avoids using QEMU, so it can build arm64
container images, but is extremely
slow the first time it's used, and consequently not recommended for general use.
In this case, to build the ejabberd container image for arm64 architecture:
docker buildx build \
--build-arg METHOD=package \
--platform linux/arm64 \
-t personal/ejabberd:$VERSION \
-f .github/container/Dockerfile \
.
Composer Examples¶
Minimal Example¶
This is the barely minimal file to get a usable ejabberd.
Store it as docker-compose.yml
:
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
Create and start the container with the command:
Customized Example¶
This example shows the usage of several customizations: it uses a local configuration file, stores the mnesia database in a local path, registers an account when it's created, and checks the number of registered accounts every time it's started.
Download or copy the ejabberd configuration file:
wget https://raw.githubusercontent.com/processone/ejabberd/master/ejabberd.yml.example
mv ejabberd.yml.example ejabberd.yml
Create the database directory and allow the container access to it:
Now write this docker-compose.yml
file:
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
- CTL_ON_CREATE=register admin localhost asd
- CTL_ON_START=registered_users localhost ;
status
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
volumes:
- ./ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro
- ./database:/opt/ejabberd/database
Clustering Example¶
In this example, the main container is created first. Once it is fully started and healthy, a second container is created, and once ejabberd is started in it, it joins the first one.
An account is registered in the first node when created (and we ignore errors that can happen when doing that - for example whenn account already exists), and it should exist in the second node after join.
Notice that in this example the main container does not have access to the exterior; the replica exports the ports and can be accessed.
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
- ERLANG_NODE_ARG=ejabberd@main
- ERLANG_COOKIE=dummycookie123
- CTL_ON_CREATE=! register admin localhost asd
replica:
image: ghcr.io/processone/ejabberd
container_name: replica
depends_on:
main:
condition: service_healthy
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
environment:
- ERLANG_NODE_ARG=ejabberd@replica
- ERLANG_COOKIE=dummycookie123
- CTL_ON_CREATE=join_cluster ejabberd@main
- CTL_ON_START=registered_users localhost ;
status