2022-04-22 20:32:57 +02:00
[![GitHub tag (latest SemVer) ](https://img.shields.io/github/v/tag/processone/ejabberd?sort=semver&logo=embarcadero&label=&color=49c0c4 )](https://github.com/processone/ejabberd/tags)
2024-08-20 12:25:19 +02:00
[![ejabberd Container on GitHub ](https://img.shields.io/github/v/tag/processone/ejabberd?label=ejabberd&sort=semver&logo=docker )](https://github.com/processone/ejabberd/pkgs/container/ejabberd)
[![ecs Container on Docker ](https://img.shields.io/docker/v/ejabberd/ecs?label=ecs&sort=semver&logo=docker )](https://hub.docker.com/r/ejabberd/ecs/)
2022-04-22 20:32:57 +02:00
2023-04-24 11:27:13 +02:00
`ejabberd` Container Image
==========================
2022-04-22 20:32:57 +02:00
[ejabberd][home] 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.
[home]: https://ejabberd.im/
[erlang]: https://www.erlang.org/
[xmpp]: https://xmpp.org/
[mqtt]: https://mqtt.org/
[sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol
2023-04-03 17:06:49 +02:00
This document explains how to use the `ejabberd` container image available in
[ghcr.io/processone/ejabberd ](https://github.com/processone/ejabberd/pkgs/container/ejabberd ),
2022-04-22 20:32:57 +02:00
built using the files in `.github/container/` .
2024-02-23 15:25:39 +01:00
This image is based in Alpine 3.19, includes Erlang/OTP 26.2 and Elixir 1.16.1.
2022-04-22 20:32:57 +02:00
2023-04-03 17:06:49 +02:00
Alternatively, there is also the `ecs` container image available in
[docker.io/ejabberd/ecs ](https://hub.docker.com/r/ejabberd/ecs/ ),
2022-04-22 20:32:57 +02:00
built using the
[docker-ejabberd/ecs ](https://github.com/processone/docker-ejabberd/tree/master/ecs )
repository.
2023-04-03 17:06:49 +02:00
Check the [differences between `ejabberd` and `ecs` images ](https://github.com/processone/docker-ejabberd/blob/master/ecs/HUB-README.md#alternative-image-in-github ).
2022-04-22 20:32:57 +02:00
If you are using a Windows operating system, check the tutorials mentioned in
2024-04-24 17:23:53 +02:00
[ejabberd Docs > Docker Image ](https://docs.ejabberd.im/admin/install/container/#ejabberd-container-image ).
2022-04-22 20:32:57 +02:00
Start ejabberd
2024-02-23 17:01:26 +01:00
--------------
2022-04-22 20:32:57 +02:00
2024-02-23 17:01:26 +01:00
### With default configuration
2022-04-22 20:32:57 +02:00
Start ejabberd in a new container:
```bash
docker run --name ejabberd -d -p 5222:5222 ghcr.io/processone/ejabberd
```
That runs the container as a daemon,
using ejabberd default configuration file and XMPP domain "localhost".
Stop the running container:
```bash
docker stop ejabberd
```
Restart the stopped ejabberd container:
```bash
docker restart ejabberd
```
2024-02-23 17:01:26 +01:00
### Start with Erlang console attached
2022-04-22 20:32:57 +02:00
Start ejabberd with an Erlang console attached using the `live` command:
```bash
docker run --name ejabberd -it -p 5222:5222 ghcr.io/processone/ejabberd live
```
That uses the default configuration file and XMPP domain "localhost".
2024-02-23 17:01:26 +01:00
### Start with your configuration and database
2022-04-22 20:32:57 +02:00
Pass a configuration file as a volume
and share the local directory to store database:
```bash
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
2024-02-23 17:01:26 +01:00
----------
2022-04-22 20:32:57 +02:00
2024-02-23 17:01:26 +01:00
### Register the administrator account
2022-04-22 20:32:57 +02:00
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:
```bash
docker exec -it ejabberd ejabberdctl register admin localhost passw0rd
```
Then edit conf/ejabberd.yml and add the ACL as explained in
2024-04-24 17:23:53 +02:00
[ejabberd Docs: Administration Account ](https://docs.ejabberd.im/admin/install/next-steps/#administration-account )
2022-04-22 20:32:57 +02:00
2024-02-23 17:01:26 +01:00
### Check ejabberd log files
2022-04-22 20:32:57 +02:00
Check the content of the log files inside the container,
even if you do not put it on a shared persistent drive:
```bash
docker exec -it ejabberd tail -f logs/ejabberd.log
```
2024-02-23 17:01:26 +01:00
### Inspect the container files
2022-04-22 20:32:57 +02:00
The container uses Alpine Linux. Start a shell inside the container:
```bash
docker exec -it ejabberd sh
```
2024-02-23 17:01:26 +01:00
### Open ejabberd debug console
2022-04-22 20:32:57 +02:00
Open an interactive debug Erlang console attached to a running ejabberd in a running container:
```bash
docker exec -it ejabberd ejabberdctl debug
```
2024-02-23 17:01:26 +01:00
### CAPTCHA
2022-04-22 20:32:57 +02:00
ejabberd includes two example CAPTCHA scripts.
If you want to use any of them, first install some additional required libraries:
```bash
docker exec --user root ejabberd apk add imagemagick ghostscript-fonts bash
```
Now update your ejabberd configuration file, for example:
```bash
docker exec -it ejabberd vi conf/ejabberd.yml
```
2023-04-17 12:19:37 +02:00
and add this option:
```yaml
2023-01-26 15:53:27 +01:00
captcha_cmd: /opt/ejabberd-22.04/lib/captcha.sh
2022-04-22 20:32:57 +02:00
```
Finally, reload the configuration file or restart the container:
```bash
docker exec ejabberd ejabberdctl reload_config
```
2023-04-17 12:19:37 +02:00
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:
```yaml
captcha_url: https://localhost:5443/captcha
```
For more details about CAPTCHA options, please check the
[CAPTCHA ](https://docs.ejabberd.im/admin/configuration/basic/#captcha )
documentation section.
2022-04-22 20:32:57 +02:00
Advanced Container Configuration
2024-02-23 17:01:26 +01:00
--------------------------------
2022-04-22 20:32:57 +02:00
2024-02-23 17:01:26 +01:00
### Ports
2022-04-22 20:32:57 +02:00
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 MQTT
- `4369-4399` : EPMD and Erlang connectivity, used for `ejabberdctl` and clustering
2022-05-31 13:35:15 +02:00
- `5210` : Erlang connectivity when `ERL_DIST_PORT` is set, alternative to EPMD
2022-04-22 20:32:57 +02:00
2024-02-23 17:01:26 +01:00
### Volumes
2022-04-22 20:32:57 +02:00
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 ](https://github.com/processone/docker-ejabberd/issues/81#issuecomment-1036115146 )
explains how to install an additional module using docker-compose.
2024-02-23 17:01:26 +01:00
### Commands on start
2022-04-22 20:32:57 +02:00
The ejabberdctl script reads the `CTL_ON_CREATE` environment variable
2023-04-03 17:06:49 +02:00
the first time the container is started,
2022-04-22 20:32:57 +02:00
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.
2024-02-13 11:55:12 +01:00
By default failure of any of commands executed that way would
abort start, this can be disabled by prefixing commands with `!`
2022-11-07 22:30:05 +01:00
Example usage (or check the [full example ](#customized-example )):
2022-04-22 20:32:57 +02:00
```yaml
environment:
2024-04-19 16:14:05 +02:00
- CTL_ON_CREATE=! register admin localhost asd
2022-04-22 20:32:57 +02:00
- CTL_ON_START=stats registeredusers ;
check_password admin localhost asd ;
status
```
2024-11-29 11:07:26 +01:00
### Macros in environment
ejabberd reads `EJABBERD_MACRO_*` environment variables
and uses them to define the `*`
[macros ](https://docs.ejabberd.im/admin/configuration/file-format/#macros-in-configuration-file ),
overwriting the corresponding macro definition if it was set in the configuration file.
For example, if you configure this in `ejabberd.yml` :
```yaml
acl:
admin:
user: ADMINJID
```
now you can define the admin account JID using an environment variable:
```yaml
environment:
- EJABBERD_MACRO_ADMINJID=admin@localhost
```
Check the [full example ](#customized-example ) for other example.
2024-02-23 17:01:26 +01:00
### Clustering
2022-04-22 20:32:57 +02:00
When setting several containers to form a
[cluster of ejabberd nodes ](https://docs.ejabberd.im/admin/guide/clustering/ ),
each one must have a different
[Erlang Node Name ](https://docs.ejabberd.im/admin/guide/security/#erlang-node-name )
and the same
[Erlang Cookie ](https://docs.ejabberd.im/admin/guide/security/#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`
2022-05-31 13:35:15 +02:00
Example to connect a local `ejabberdctl` to a containerized ejabberd:
1. When creating the container, export port 5210, and set `ERLANG_COOKIE` :
2024-04-03 22:55:58 +02:00
```sh
2022-05-31 13:35:15 +02:00
docker run --name ejabberd -it \
-e ERLANG_COOKIE=`cat $HOME/.erlang.cookie` \
-p 5210:5210 -p 5222:5222 \
ghcr.io/processone/ejabberd
```
2. Set `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:
2024-04-03 22:55:58 +02:00
```sh
2022-05-31 13:35:15 +02:00
ERL_DIST_PORT=5210 _build/dev/rel/ejabberd/bin/ejabberd ping
```
2022-04-22 20:32:57 +02:00
Example using environment variables (see full example [docker-compose.yml ](https://github.com/processone/docker-ejabberd/issues/64#issuecomment-887741332 )):
```yaml
environment:
- ERLANG_NODE_ARG=ejabberd@node7
- ERLANG_COOKIE=dummycookie123
```
2023-04-11 12:09:37 +02:00
Build a Container Image
2024-02-23 17:01:26 +01:00
-----------------------
2022-11-18 21:55:17 +01:00
2022-04-22 20:32:57 +02:00
This container image includes ejabberd as a standalone OTP release built using Elixir.
That OTP release is configured with:
- `mix.exs` : Customize ejabberd release
- `vars.config` : ejabberd compilation configuration options
- `config/runtime.exs` : Customize ejabberd paths
- `ejabberd.yml.template` : ejabberd default config file
2024-02-23 17:01:26 +01:00
### Direct build
2023-04-11 12:09:37 +02:00
Build ejabberd Community Server container image from ejabberd master git repository:
2022-04-22 20:32:57 +02:00
```bash
2023-04-11 11:11:16 +02:00
docker buildx build \
2022-09-06 12:03:12 +02:00
-t personal/ejabberd \
-f .github/container/Dockerfile \
.
2022-04-22 20:32:57 +02:00
```
2024-02-23 17:01:26 +01:00
### Podman build
2022-04-22 20:32:57 +02:00
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
2024-04-08 13:50:06 +02:00
- to start with command `live` , you may want to add environment variable `EJABBERD_BYPASS_WARNINGS=true`
2022-04-22 20:32:57 +02:00
```bash
podman build \
2022-09-07 13:56:19 +02:00
-t ejabberd \
2022-09-06 12:03:12 +02:00
-f .github/container/Dockerfile \
.
2022-09-07 13:56:19 +02:00
podman run --name eja1 -d -p 5222:5222 localhost/ejabberd
podman exec eja1 ejabberdctl status
podman exec -it eja1 sh
podman stop eja1
2024-04-08 13:50:06 +02:00
podman run --name eja1 -it -e EJABBERD_BYPASS_WARNINGS=true -p 5222:5222 localhost/ejabberd live
2022-04-22 20:32:57 +02:00
```
2022-11-07 22:17:33 +01:00
2024-02-23 17:01:26 +01:00
### Package build for `arm64`
2023-04-11 12:09:37 +02:00
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:
```bash
docker buildx build \
--build-arg METHOD=package \
--platform linux/arm64 \
-t personal/ejabberd:$VERSION \
-f .github/container/Dockerfile \
.
```
2022-11-07 22:17:33 +01:00
Composer Examples
2024-02-23 17:01:26 +01:00
-----------------
2022-11-07 22:17:33 +01:00
2024-02-23 17:01:26 +01:00
### Minimal Example
2022-11-07 22:17:33 +01:00
This is the barely minimal file to get a usable ejabberd.
Store it as `docker-compose.yml` :
```yaml
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:
```bash
docker-compose up
```
2024-02-23 17:01:26 +01:00
### Customized Example
2022-11-07 22:17:33 +01:00
This example shows the usage of several customizations:
it uses a local configuration file,
2024-11-29 11:07:26 +01:00
defines a configuration macro using an environment variable,
2022-11-07 22:17:33 +01:00
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:
```bash
wget https://raw.githubusercontent.com/processone/ejabberd/master/ejabberd.yml.example
mv ejabberd.yml.example ejabberd.yml
```
2024-11-29 11:07:26 +01:00
Use a macro in `ejabberd.yml` to set the served vhost, with `localhost` as default value:
```bash
define_macro:
XMPPHOST: localhost
hosts:
- XMPPHOST
```
2022-11-07 22:17:33 +01:00
Create the database directory and allow the container access to it:
```bash
mkdir database
sudo chown 9000:9000 database
```
Now write this `docker-compose.yml` file:
```yaml
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
2024-11-29 11:07:26 +01:00
- EJABBERD_MACRO_XMPPHOST=example.com
- CTL_ON_CREATE=register admin example.com asd
- CTL_ON_START=registered_users example.com ;
2022-11-07 22:17:33 +01:00
status
ports:
- "5222:5222"
- "5269:5269"
- "5280:5280"
- "5443:5443"
volumes:
- ./ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro
- ./database:/opt/ejabberd/database
```
2024-02-23 17:01:26 +01:00
### Clustering Example
2022-11-07 22:17:33 +01:00
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.
2024-02-13 11:55:12 +01:00
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),
2022-11-07 22:17:33 +01:00
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.
```yaml
version: '3.7'
services:
main:
image: ghcr.io/processone/ejabberd
container_name: ejabberd
environment:
- ERLANG_NODE_ARG=ejabberd@main
- ERLANG_COOKIE=dummycookie123
2024-04-19 16:14:05 +02:00
- CTL_ON_CREATE=! register admin localhost asd
2022-11-07 22:17:33 +01:00
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
```