├── .github └── workflows │ ├── code-server.yml │ ├── devcontainer.yml │ └── tests.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── code-server └── Dockerfile ├── devcontainer └── Dockerfile ├── ecs ├── .gitignore ├── Dockerfile ├── HUB-README.md ├── README.md ├── bin │ ├── ejabberdctl │ └── erl ├── build.sh ├── conf │ ├── dhparams.pem │ ├── ejabberd.yml │ ├── ejabberdctl.cfg │ ├── inetrc │ └── server.pem ├── config.exs ├── ejabberd-docker-install.bat ├── hooks │ └── build ├── rel │ ├── config.exs │ ├── dev.exs │ └── prod.exs └── vars.config └── mix ├── Dockerfile └── README.md /.github/workflows/code-server.yml: -------------------------------------------------------------------------------- 1 | name: code-server 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/code-server.yml' 7 | - 'code-server/**' 8 | 9 | jobs: 10 | 11 | code-server: 12 | 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | 20 | - uses: actions/checkout@v4 21 | 22 | - name: Build image 23 | run: docker build 24 | code-server 25 | --tag code-server 26 | 27 | - name: Login to GitHub Container Registry 28 | uses: docker/login-action@v3 29 | with: 30 | registry: ghcr.io 31 | username: ${{ github.repository_owner }} 32 | password: ${{ secrets.GITHUB_TOKEN }} 33 | 34 | - name: Push image 35 | run: | 36 | IMAGE_ID=ghcr.io/${{ github.repository_owner }}/code-server 37 | # Strip git ref prefix from version 38 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 39 | # Use Docker `latest` tag convention 40 | [ "$VERSION" == "master" ] && VERSION=latest 41 | docker tag code-server $IMAGE_ID:$VERSION 42 | docker push $IMAGE_ID:$VERSION 43 | -------------------------------------------------------------------------------- /.github/workflows/devcontainer.yml: -------------------------------------------------------------------------------- 1 | name: devcontainer 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/devcontainer.yml' 7 | - 'devcontainer/**' 8 | 9 | jobs: 10 | 11 | devcontainer: 12 | 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | 20 | - uses: actions/checkout@v4 21 | 22 | - name: Build image 23 | run: docker build 24 | devcontainer 25 | --tag devcontainer 26 | 27 | - name: Login to GitHub Container Registry 28 | uses: docker/login-action@v3 29 | with: 30 | registry: ghcr.io 31 | username: ${{ github.repository_owner }} 32 | password: ${{ secrets.GITHUB_TOKEN }} 33 | 34 | - name: Push image 35 | run: | 36 | IMAGE_ID=ghcr.io/${{ github.repository_owner }}/devcontainer 37 | # Strip git ref prefix from version 38 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 39 | # Use Docker `latest` tag convention 40 | [ "$VERSION" == "master" ] && VERSION=latest 41 | docker tag devcontainer $IMAGE_ID:$VERSION 42 | docker push $IMAGE_ID:$VERSION 43 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | push: 5 | paths: 6 | - '.github/workflows/tests.yml' 7 | - 'ecs/**' 8 | - 'mix/**' 9 | pull_request: 10 | paths: 11 | - '.github/workflows/tests.yml' 12 | - 'ecs/**' 13 | - 'mix/**' 14 | 15 | env: 16 | REGISTRY_GHCR: ghcr.io 17 | REGISTRY_LOCAL: localhost:5000 18 | REGISTRY_DOCKER: docker.io 19 | MIX_IMAGENAME_GHCR: ${{ github.repository_owner }}/mix 20 | ECS_IMAGENAME_GHCR: ${{ github.repository_owner }}/ecs 21 | MIX_IMAGENAME_DOCKERHUB: ejabberd/mix 22 | ECS_IMAGENAME_DOCKERHUB: ejabberd/ecs 23 | 24 | jobs: 25 | 26 | build: 27 | name: Build 28 | runs-on: ubuntu-24.04 29 | strategy: 30 | fail-fast: true 31 | max-parallel: 1 32 | permissions: 33 | packages: write 34 | services: 35 | registry: 36 | image: registry:2 37 | ports: 38 | - 5000:5000 39 | 40 | steps: 41 | 42 | - name: Checkout code 43 | uses: actions/checkout@v4 44 | with: 45 | fetch-depth: 0 46 | 47 | - name: Login to GHCR 48 | uses: docker/login-action@v3 49 | with: 50 | registry: ${{ env.REGISTRY_GHCR }} 51 | username: ${{ github.actor }} 52 | password: ${{ secrets.GITHUB_TOKEN }} 53 | 54 | - name: Login to Docker Hub 55 | uses: docker/login-action@v3 56 | with: 57 | username: ${{ secrets.DOCKERHUB_USERNAME }} 58 | password: ${{ secrets.DOCKERHUB_TOKEN }} 59 | 60 | - name: Get git describe 61 | id: gitdescribe 62 | run: echo "ver=$(git describe --tags --exact-match 2>/dev/null || echo latest)" >> $GITHUB_OUTPUT 63 | 64 | - name: Extract mix metadata (tags, labels) 65 | id: mixmeta 66 | if: github.ref_type == 'tag' 67 | uses: docker/metadata-action@v5 68 | with: 69 | images: | 70 | ${{ env.REGISTRY_GHCR }}/${{ env.MIX_IMAGENAME_GHCR }} 71 | ${{ env.REGISTRY_DOCKER }}/${{ env.MIX_IMAGENAME_DOCKERHUB }} 72 | labels: | 73 | org.opencontainers.image.revision=${{ steps.gitdescribe.outputs.ver }} 74 | org.opencontainers.image.licenses=GPL-2.0 75 | org.opencontainers.image.vendor=ProcessOne 76 | 77 | - name: Extract ecs metadata (tags, labels) 78 | id: ecsmeta 79 | if: github.ref_type == 'tag' 80 | uses: docker/metadata-action@v5 81 | with: 82 | images: | 83 | ${{ env.REGISTRY_GHCR }}/${{ env.ECS_IMAGENAME_GHCR }} 84 | ${{ env.REGISTRY_DOCKER }}/${{ env.ECS_IMAGENAME_DOCKERHUB }} 85 | labels: | 86 | org.opencontainers.image.revision=${{ steps.gitdescribe.outputs.ver }} 87 | org.opencontainers.image.licenses=GPL-2.0 88 | org.opencontainers.image.vendor=ProcessOne 89 | 90 | - name: Prepare local tags 91 | id: localreg 92 | run: | 93 | tag="$(echo ${{ github.ref_name }} | sed -e 's|[/]\+|-|g')" 94 | echo "mixlocaltag=${{ env.REGISTRY_LOCAL }}/${{ env.MIX_IMAGENAME_GHCR }}:$tag" >> $GITHUB_OUTPUT 95 | echo "ecslocaltag=${{ env.REGISTRY_LOCAL }}/${{ env.ECS_IMAGENAME_GHCR }}:$tag" >> $GITHUB_OUTPUT 96 | 97 | - name: Set up Docker Buildx 98 | uses: docker/setup-buildx-action@v3 99 | with: 100 | driver-opts: network=host 101 | 102 | - name: Build and push local mix image 103 | uses: docker/build-push-action@v5 104 | with: 105 | build-args: | 106 | VERSION=${{ steps.gitdescribe.outputs.ver }} 107 | cache-from: type=gha 108 | cache-to: type=gha,mode=max 109 | context: mix 110 | labels: ${{ steps.mixmeta.outputs.labels }} 111 | platforms: linux/amd64 112 | push: true 113 | tags: | 114 | ${{ steps.localreg.outputs.mixlocaltag }} 115 | 116 | - name: Prepare ecs Dockerfile 117 | run: sed -i 's|docker.io/ejabberd/mix|${{ steps.localreg.outputs.mixlocaltag }}|g' ecs/Dockerfile 118 | 119 | - name: Build and push local ecs image 120 | uses: docker/build-push-action@v5 121 | with: 122 | build-args: | 123 | VERSION=${{ steps.gitdescribe.outputs.ver }} 124 | cache-from: type=gha 125 | cache-to: type=gha,mode=max 126 | context: ecs 127 | labels: ${{ steps.ecsmeta.outputs.labels }} 128 | platforms: linux/amd64 129 | push: true 130 | tags: | 131 | ${{ steps.localreg.outputs.ecslocaltag }} 132 | 133 | - name: Run ecs image 134 | run: | 135 | docker images 136 | docker run --name ejabberd -d -p 5222:5222 ${{ steps.localreg.outputs.ecslocaltag }} 137 | 138 | - name: Wait ejabberd started 139 | run: | 140 | docker exec ejabberd bin/ejabberdctl started 141 | 142 | - name: Check ecs results 143 | if: always() 144 | run: | 145 | docker ps -s 146 | docker logs ejabberd 147 | docker logs ejabberd | grep -q "Start accepting TCP connections" || exit 1 148 | docker logs ejabberd | grep -q "error" && exit 1 || exit 0 149 | docker logs ejabberd | grep -q "Error" && exit 1 || exit 0 150 | 151 | - name: Save image 152 | run: | 153 | docker image save ${{ steps.localreg.outputs.ecslocaltag }} --output ejabberd-latest.tar 154 | 155 | - name: Upload image 156 | uses: actions/upload-artifact@v4 157 | with: 158 | name: ejabberd-image 159 | path: ejabberd-latest.tar 160 | 161 | - run: | 162 | echo "::notice::To get this image, download ejabberd-image.zip, "\ 163 | "uncompress it and run: " \ 164 | "docker image load -i ejabberd-latest.tar" 165 | 166 | - name: Build and push mix image 167 | uses: docker/build-push-action@v5 168 | if: github.ref_type == 'tag' 169 | with: 170 | build-args: | 171 | VERSION=${{ steps.gitdescribe.outputs.ver }} 172 | cache-from: type=gha 173 | cache-to: type=gha,mode=max 174 | context: mix 175 | labels: ${{ steps.mixmeta.outputs.labels }} 176 | platforms: linux/amd64 177 | push: true 178 | tags: | 179 | ${{ steps.mixmeta.outputs.tags }} 180 | 181 | - name: Build and push ecs image 182 | uses: docker/build-push-action@v5 183 | if: github.ref_type == 'tag' 184 | with: 185 | build-args: | 186 | VERSION=${{ steps.gitdescribe.outputs.ver }} 187 | cache-from: type=gha 188 | cache-to: type=gha,mode=max 189 | context: ecs 190 | labels: ${{ steps.ecsmeta.outputs.labels }} 191 | platforms: linux/amd64 192 | push: true 193 | tags: | 194 | ${{ steps.ecsmeta.outputs.tags }} 195 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version 19.08 2 | 3 | - Update default configuration 4 | - Add sqlite libs 5 | - Fix sample Let's Encrypt configuration 6 | - Add badges and links docker README 7 | - Allow mapping of upload dir as volume 8 | - Fix INET_DIST_INTERFACE 9 | - Add travis support 10 | - Add STUN/TURN & SIP support 11 | - Add libgd for image manupilation 12 | - Add Dockerhub build hook 13 | - Keep SQL init scripts in database volume 14 | - Update use of new distillery 15 | 16 | # Version 19.05 17 | 18 | - Update default configuration 19 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at conduct@process-one.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We'd love for you to contribute to our source code and to make our project even better than it is 4 | today! Here are the guidelines we'd like you to follow: 5 | 6 | * [Code of Conduct](#coc) 7 | * [Questions and Problems](#question) 8 | * [Issues and Bugs](#issue) 9 | * [Feature Requests](#feature) 10 | * [Issue Submission Guidelines](#submit) 11 | * [Pull Request Submission Guidelines](#submit-pr) 12 | * [Signing the CLA](#cla) 13 | 14 | ## Code of Conduct 15 | 16 | Help us keep our community open-minded and inclusive. Please read and follow our [Code of Conduct][coc]. 17 | 18 | ## Questions, Bugs, Features 19 | 20 | ### Got a Question or Problem? 21 | 22 | Do not open issues for general support questions as we want to keep GitHub issues for bug reports 23 | and feature requests. You've got much better chances of getting your question answered on dedicated 24 | support platforms, the best being [Stack Overflow][stackoverflow]. 25 | 26 | Stack Overflow is a much better place to ask questions since: 27 | 28 | - there are thousands of people willing to help on Stack Overflow 29 | - questions and answers stay available for public viewing so your question / answer might help 30 | someone else 31 | - Stack Overflow's voting system assures that the best answers are prominently visible. 32 | 33 | To save your and our time, we will systematically close all issues that are requests for general 34 | support and redirect people to the section you are reading right now. 35 | 36 | ### Found an Issue or Bug? 37 | 38 | If you find a bug in the source code, you can help us by submitting an issue to our 39 | [GitHub Repository][github]. Even better, you can submit a Pull Request with a fix. 40 | 41 | ### Missing a Feature? 42 | 43 | You can request a new feature by submitting an issue to our [GitHub Repository][github-issues]. 44 | 45 | If you would like to implement a new feature then consider what kind of change it is: 46 | 47 | * **Major Changes** that you wish to contribute to the project should be discussed first in an 48 | [GitHub issue][github-issues] that clearly outlines the changes and benefits of the feature. 49 | * **Small Changes** can directly be crafted and submitted to the [GitHub Repository][github] 50 | as a Pull Request. See the section about [Pull Request Submission Guidelines](#submit-pr). 51 | 52 | ## Issue Submission Guidelines 53 | 54 | Before you submit your issue search the archive, maybe your question was already answered. 55 | 56 | If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize 57 | the effort we can spend fixing issues and adding new features, by not reporting duplicate issues. 58 | 59 | The "[new issue][github-new-issue]" form contains a number of prompts that you should fill out to 60 | make it easier to understand and categorize the issue. 61 | 62 | ## Pull Request Submission Guidelines 63 | 64 | By submitting a pull request for a code or doc contribution, you need to have the right 65 | to grant your contribution's copyright license to ProcessOne. Please check [ProcessOne CLA][cla] 66 | for details. 67 | 68 | Before you submit your pull request consider the following guidelines: 69 | 70 | * Search [GitHub][github-pr] for an open or closed Pull Request 71 | that relates to your submission. You don't want to duplicate effort. 72 | * Make your changes in a new git branch: 73 | 74 | ```shell 75 | git checkout -b my-fix-branch master 76 | ``` 77 | * Test your changes and, if relevant, expand the automated test suite. 78 | * Create your patch commit, including appropriate test cases. 79 | * If the changes affect public APIs, change or add relevant documentation. 80 | * Commit your changes using a descriptive commit message. 81 | 82 | ```shell 83 | git commit -a 84 | ``` 85 | Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. 86 | 87 | * Push your branch to GitHub: 88 | 89 | ```shell 90 | git push origin my-fix-branch 91 | ``` 92 | 93 | * In GitHub, send a pull request to `master` branch. This will trigger the continuous integration and run the test. 94 | We will also notify you if you have not yet signed the [contribution agreement][cla]. 95 | 96 | * If you find that the continunous integration has failed, look into the logs to find out 97 | if your changes caused test failures, the commit message was malformed etc. If you find that the 98 | tests failed or times out for unrelated reasons, you can ping a team member so that the build can be 99 | restarted. 100 | 101 | * If we suggest changes, then: 102 | 103 | * Make the required updates. 104 | * Test your changes and test cases. 105 | * Commit your changes to your branch (e.g. `my-fix-branch`). 106 | * Push the changes to your GitHub repository (this will update your Pull Request). 107 | 108 | You can also amend the initial commits and force push them to the branch. 109 | 110 | ```shell 111 | git rebase master -i 112 | git push origin my-fix-branch -f 113 | ``` 114 | 115 | This is generally easier to follow, but separate commits are useful if the Pull Request contains 116 | iterations that might be interesting to see side-by-side. 117 | 118 | That's it! Thank you for your contribution! 119 | 120 | ## Signing the Contributor License Agreement (CLA) 121 | 122 | Upon submitting a Pull Request, we will ask you to sign our CLA if you haven't done 123 | so before. It's a quick process, we promise, and you will be able to do it all online 124 | 125 | You can read [ProcessOne Contribution License Agreement][cla] in PDF. 126 | 127 | This is part of the legal framework of the open-source ecosystem that adds some red tape, 128 | but protects both the contributor and the company / foundation behind the project. It also 129 | gives us the option to relicense the code with a more permissive license in the future. 130 | 131 | 132 | [coc]: https://github.com/processone/docker-ejabberd/blob/master/CODE_OF_CONDUCT.md 133 | [stackoverflow]: https://stackoverflow.com/ 134 | [github]: https://github.com/processone/docker-ejabberd 135 | [github-issues]: https://github.com/processone/docker-ejabberd/issues 136 | [github-new-issue]: https://github.com/processone/docker-ejabberd/issues/new 137 | [github-pr]: https://github.com/processone/docker-ejabberd/pulls 138 | [cla]: https://www.process-one.net/resources/ejabberd-cla.pdf 139 | [license]: https://github.com/processone/docker-ejabberd/blob/master/LICENSE.txt 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build Status](https://github.com/processone/docker-ejabberd/actions/workflows/tests.yml/badge.svg)](https://github.com/processone/docker-ejabberd/actions/workflows/tests.yml) 3 | 4 | # docker-ejabberd 5 | 6 | This repository contains a set of container images to run or develop ejabberd: 7 | 8 | - [mix](mix/) (published in [docker.io/ejabberd/mix](https://hub.docker.com/r/ejabberd/mix/) 9 | and [ghcr.io/processone/mix](https://github.com/processone/docker-ejabberd/pkgs/container/mix)): 10 | 11 | Build a development environment for ejabberd. See [mix README](mix/README.md) file for details. 12 | 13 | - [ecs](ecs/) (published in [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/) 14 | and [ghcr.io/processone/ecs](https://github.com/processone/docker-ejabberd/pkgs/container/ecs)): 15 | 16 | Run ejabberd in a container with simple setup. 17 | See [ecs README](ecs/README.md) file for details. 18 | 19 | - [code-server](code-server/) (published in [ghcr.io/processone/code-server](https://github.com/orgs/processone/packages/container/package/code-server)): 20 | 21 | Run Coder's code-server with a local ejabberd git clone. 22 | See [VSCode section](https://docs.ejabberd.im/developer/vscode/) in ejabberds Docs. 23 | 24 | - [devcontainer](devcontainer/) (published in [ghcr.io/processone/devcontainer](https://github.com/orgs/processone/packages/container/package/devcontainer)): 25 | 26 | Use as a Dev Container for ejabberd in Visual Studio Code. 27 | See [VSCode section](https://docs.ejabberd.im/developer/vscode/) in ejabberds Docs. 28 | 29 | The [ejabberd source code repository](https://github.com/processone/ejabberd) also provides: 30 | 31 | - [ejabberd](https://github.com/processone/ejabberd/tree/master/.github/container) (published in [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd)): 32 | 33 | Run ejabberd in a container with simple setup. 34 | See [ejabberd's CONTAINER](https://github.com/processone/ejabberd/blob/master/CONTAINER.md) file for details. 35 | Check the [differences between this image and `ecs`](https://github.com/processone/docker-ejabberd/blob/master/ecs/HUB-README.md#alternative-image-in-github). 36 | -------------------------------------------------------------------------------- /code-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:sid-slim 2 | 3 | RUN apt-get update \ 4 | && apt-get -y --no-install-recommends install \ 5 | curl ca-certificates \ 6 | autoconf automake git make gcc g++ \ 7 | erlang erlang-dev elixir rebar3 \ 8 | libexpat1-dev libgd-dev libpam0g-dev \ 9 | libsqlite3-dev libwebp-dev libyaml-dev \ 10 | libssl-dev 11 | 12 | RUN curl -fsSL https://code-server.dev/install.sh | sh 13 | 14 | RUN addgroup vscode --gid 1000 \ 15 | && adduser --shell /bin/bash --ingroup vscode vscode -u 1000 16 | 17 | USER vscode 18 | 19 | RUN /usr/bin/code-server --install-extension erlang-ls.erlang-ls 20 | 21 | WORKDIR /home/vscode 22 | RUN echo "export PATH=/workspaces/ejabberd/_build/relive:$PATH" >>.bashrc \ 23 | && echo "COOKIE" >.erlang.cookie \ 24 | && chmod 400 .erlang.cookie 25 | 26 | WORKDIR /workspaces/ejabberd 27 | VOLUME ["workspaces/ejabberd"] 28 | EXPOSE 1870 1883 4369-4399 5210 5222 5269 5280 5443 29 | 30 | ENTRYPOINT ["code-server", "--bind-addr", "0.0.0.0:1870", "--auth", "none", "/workspaces/ejabberd"] 31 | -------------------------------------------------------------------------------- /devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # [Choice] Alpine version: 3.16, 3.15, 3.14, 3.13 2 | ARG VARIANT=latest 3 | FROM alpine:${VARIANT} 4 | 5 | RUN apk upgrade --update musl \ 6 | && apk add \ 7 | autoconf \ 8 | automake \ 9 | bash \ 10 | build-base \ 11 | curl \ 12 | elixir \ 13 | erlang-debugger \ 14 | erlang-observer \ 15 | erlang-odbc \ 16 | erlang-reltool \ 17 | expat-dev \ 18 | file \ 19 | gd-dev \ 20 | git \ 21 | jpeg-dev \ 22 | libpng-dev \ 23 | libwebp-dev \ 24 | linux-pam-dev \ 25 | openssl \ 26 | openssl-dev \ 27 | sqlite-dev \ 28 | yaml-dev \ 29 | zlib-dev 30 | 31 | # [Option] Install zsh 32 | ARG INSTALL_ZSH="true" 33 | 34 | # Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies. 35 | ARG USERNAME=vscode 36 | ARG USER_UID=1000 37 | ARG USER_GID=$USER_UID 38 | ARG COMMON_SCRIPT_SOURCE="https://raw.githubusercontent.com/devcontainers/images/v0.2.31/src/base-alpine/.devcontainer/library-scripts/common-alpine.sh" 39 | RUN apk update \ 40 | && curl -sSL ${COMMON_SCRIPT_SOURCE} -o /tmp/common-alpine.sh \ 41 | && ash /tmp/common-alpine.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" \ 42 | && rm -rf /tmp/common-alpine.sh 43 | 44 | RUN mix local.hex --force \ 45 | && mix local.rebar --force 46 | 47 | RUN apk add \ 48 | expat \ 49 | freetds \ 50 | gd \ 51 | jpeg \ 52 | libgd \ 53 | libpng \ 54 | libstdc++ \ 55 | libwebp \ 56 | linux-pam \ 57 | ncurses-libs \ 58 | openssl \ 59 | sqlite \ 60 | sqlite-libs \ 61 | unixodbc \ 62 | yaml \ 63 | zlib \ 64 | && ln -fs /usr/lib/libtdsodbc.so.0 /usr/lib/libtdsodbc.so \ 65 | && rm -rf /var/cache/apk/* 66 | -------------------------------------------------------------------------------- /ecs/.gitignore: -------------------------------------------------------------------------------- 1 | db/ 2 | ejbuild/ 3 | log/ 4 | *.tar.gz 5 | 6 | -------------------------------------------------------------------------------- /ecs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/golang:1.22-alpine AS api 2 | RUN go install -v \ 3 | github.com/processone/ejabberd-api/cmd/ejabberd@latest \ 4 | && mv bin/ejabberd bin/ejabberdapi 5 | 6 | FROM docker.io/ejabberd/mix AS builder 7 | ARG VERSION 8 | ENV VERSION=${VERSION:-latest} \ 9 | MIX_ENV=prod 10 | LABEL maintainer="ProcessOne " \ 11 | product="Ejabberd Community Server builder" 12 | 13 | # Get ejabberd sources, dependencies, configuration 14 | RUN git clone https://github.com/processone/ejabberd.git 15 | WORKDIR /ejabberd 16 | COPY vars.config . 17 | COPY config.exs config/ 18 | COPY rel/*exs rel/ 19 | RUN git checkout ${VERSION/latest/HEAD} \ 20 | \ 21 | && if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then \ 22 | echo '{vsn, "'"$VERSION.0"'"}.' >> vars.config; \ 23 | else \ 24 | echo '{vsn, "0.0.0"}.' >> vars.config; \ 25 | fi \ 26 | \ 27 | && mix deps.get \ 28 | && (cd deps/eimp; ./configure) 29 | 30 | # Compile 31 | RUN MIX_ENV=prod mix release 32 | 33 | # Prepare runtime environment 34 | RUN mkdir runtime \ 35 | && tar -C runtime -zxf _build/prod/ejabberd-*.tar.gz \ 36 | && cd runtime \ 37 | && cp releases/*/start.boot bin \ 38 | && cp releases/*/start_clean.boot bin \ 39 | && echo 'beam_lib:strip_files(filelib:wildcard("lib/*/ebin/*beam")), init:stop().' | erl >/dev/null \ 40 | && mv erts*/bin/* bin \ 41 | && EJABBERD_VERSION=`(cd releases; ls -1 -d *.*.*)` \ 42 | && rm -rf releases erts* bin/*src bin/dialyzer bin/typer etc \ 43 | && rm bin/ejabberd \ 44 | && mkdir lib/ejabberd-$EJABBERD_VERSION/priv/bin \ 45 | && cp /usr/lib/elixir/bin/* bin/ \ 46 | && sed -i 's|ERL_EXEC="erl"|ERL_EXEC="/home/ejabberd/bin/erl"|' bin/elixir \ 47 | && cp /ejabberd/tools/captcha*sh bin/ \ 48 | && cp -r /ejabberd/sql lib/ejabberd-*/priv 49 | 50 | # Runtime container 51 | FROM docker.io/alpine:3.19 52 | ARG VERSION 53 | ARG VCS_REF 54 | ARG BUILD_DATE 55 | ENV TERM=xterm \ 56 | LC_ALL=C.UTF-8 \ 57 | LANG=en_US.UTF-8 \ 58 | LANGUAGE=en_US.UTF-8 \ 59 | REPLACE_OS_VARS=true \ 60 | HOME=/home/ejabberd \ 61 | PATH="$PATH:/home/ejabberd/bin" \ 62 | VERSION=${VERSION:-latest} 63 | LABEL maintainer="ProcessOne " \ 64 | product="Ejabberd Community Server Official Docker Image" \ 65 | version=$VERSION \ 66 | org.label-schema.vcs-ref=$VCS_REF \ 67 | org.label-schema.vcs-url="https://github.com/processone/docker-ejabberd" \ 68 | org.label-schema.build-date=$BUILD_DATE \ 69 | org.label-schema.name="Ejabberd Community Server Official Docker Image" \ 70 | org.label-schema.description="Robust, Scalable and Extensible Realtime Server using XMPP, MQTT and SIP" \ 71 | org.label-schema.url="https://www.ejabberd.im/" \ 72 | org.label-schema.vendor="ProcessOne" \ 73 | org.label-schema.version=$VERSION \ 74 | org.label-schema.schema-version="1.0" 75 | 76 | # Create directory structure and user for ejabberd 77 | RUN addgroup ejabberd -g 9000 \ 78 | && adduser -s /bin/sh -D -G ejabberd ejabberd -u 9000 \ 79 | && mkdir -p /home/ejabberd/conf /home/ejabberd/database /home/ejabberd/logs /home/ejabberd/upload \ 80 | && chown -R ejabberd:ejabberd /home/ejabberd \ 81 | && ln -fs /home/ejabberd /opt/ejabberd \ 82 | && ln -fs /home/ejabberd /opt/ejabberd-$VERSION 83 | 84 | # Install required dependencies 85 | RUN apk upgrade --update-cache --no-progress \ 86 | && apk add \ 87 | expat \ 88 | freetds \ 89 | gd \ 90 | jpeg \ 91 | libgd \ 92 | libpng \ 93 | libstdc++ \ 94 | libwebp \ 95 | ncurses-libs \ 96 | openssl \ 97 | sqlite \ 98 | sqlite-libs \ 99 | tini \ 100 | unixodbc \ 101 | yaml \ 102 | zlib \ 103 | && ln -fs /usr/lib/libtdsodbc.so.0 /usr/lib/libtdsodbc.so \ 104 | && rm -rf /var/cache/apk/* 105 | 106 | # Install ejabberd 107 | WORKDIR $HOME 108 | COPY --from=builder /ejabberd/runtime . 109 | COPY bin/* bin/ 110 | COPY --from=api /go/bin/ejabberdapi bin/ejabberdapi 111 | RUN chmod 755 bin/ejabberdctl bin/ejabberdapi bin/erl bin/captcha*.sh \ 112 | && mkdir -p /home/ejabberd/sql \ 113 | && cp /home/ejabberd/lib/ejabberd-*/priv/sql/* /home/ejabberd/database/ \ 114 | && cp /home/ejabberd/lib/ejabberd-*/priv/sql/* /home/ejabberd/sql/ 115 | COPY --chown=ejabberd:ejabberd conf conf/ 116 | ADD --chown=ejabberd:ejabberd https://download.process-one.net/cacert.pem conf/cacert.pem 117 | 118 | # Setup runtime environment 119 | USER ejabberd 120 | VOLUME ["$HOME/database","$HOME/conf","$HOME/logs","$HOME/upload"] 121 | EXPOSE 1880 1883 4369-4399 5210 5222 5269 5280 5443 122 | 123 | ENTRYPOINT ["/sbin/tini","--","/home/ejabberd/bin/ejabberdctl"] 124 | CMD ["foreground"] 125 | -------------------------------------------------------------------------------- /ecs/HUB-README.md: -------------------------------------------------------------------------------- 1 | # ejabberd Community Server Docker Image 2 | 3 | ## What is ejabberd 4 | 5 | [ejabberd][im] is an open-source, 6 | robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang], 7 | that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service. 8 | 9 | Check the features in [ejabberd.im][im], [ejabberd Docs][features], 10 | [ejabberd at ProcessOne][p1home], and a list of [supported protocols and XEPs][xeps]. 11 | 12 | [im]: https://ejabberd.im/ 13 | [erlang]: https://www.erlang.org/ 14 | [xmpp]: https://xmpp.org/ 15 | [mqtt]: https://mqtt.org/ 16 | [sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol 17 | [features]: https://docs.ejabberd.im/admin/introduction/ 18 | [p1home]: https://www.process-one.net/en/ejabberd/ 19 | [xeps]: https://www.process-one.net/en/ejabberd/protocols/ 20 | 21 | 22 | ## What is `ejabberd/ecs` 23 | 24 | This `ejabberd/ecs` Docker image is built for stable ejabberd releases using 25 | [docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs). 26 | It's based in Alpine Linux, and is aimed at providing a simple image to setup and configure. 27 | 28 | Please report problems related to this `ejabberd/ecs` image packaging in 29 | [docker-ejabberd Issues](https://github.com/processone/docker-ejabberd/issues), 30 | and general ejabberd problems in 31 | [ejabberd Issues](https://github.com/processone/ejabberd/issues). 32 | 33 | 34 | ## How to use the ejabberd/ecs image 35 | 36 | Please check [ejabberd/ecs README](https://github.com/processone/docker-ejabberd/tree/master/ecs#readme) 37 | 38 | 39 | ## Supported Architectures 40 | 41 | This `ejabberd/ecs` docker image is built for the `linux/amd64` architecture. 42 | 43 | 44 | ## Alternative Image in GitHub 45 | 46 | There is another container image published in 47 | [ejabberd GitHub Packages](https://github.com/processone/ejabberd/pkgs/container/ejabberd), 48 | that you can download from the GitHub Container Registry. 49 | 50 | Its usage is similar to this `ejabberd/ecs` image, with some benefits and changes worth noting: 51 | 52 | - it's available for `linux/amd64` and `linux/arm64` architectures 53 | - it's built also for `master` branch, in addition to the stable ejabberd releases 54 | - it includes less customizations to the base ejabberd compared to `ejabberd/ecs` 55 | - it stores data in `/opt/ejabberd/` instead of `/home/ejabberd/` 56 | 57 | See its documentation in [CONTAINER](https://github.com/processone/ejabberd/blob/master/CONTAINER.md). 58 | 59 | -------------------------------------------------------------------------------- /ecs/README.md: -------------------------------------------------------------------------------- 1 | 2 | [![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) 3 | [![ejabberd Container on GitHub](https://img.shields.io/github/v/tag/processone/ejabberd?label=ejabberd&sort=semver&logo=opencontainersinitiative&logoColor=2094f3)](https://github.com/processone/ejabberd/pkgs/container/ejabberd) 4 | [![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/) 5 | 6 | ejabberd Container Images 7 | ========================= 8 | 9 | [ejabberd][home] is an open-source, 10 | robust, scalable and extensible realtime platform built using [Erlang/OTP][erlang], 11 | that includes [XMPP][xmpp] Server, [MQTT][mqtt] Broker and [SIP][sip] Service. 12 | 13 | [home]: https://www.ejabberd.im/ 14 | [erlang]: https://www.erlang.org/ 15 | [xmpp]: https://xmpp.org/ 16 | [mqtt]: https://mqtt.org/ 17 | [sip]: https://en.wikipedia.org/wiki/Session_Initiation_Protocol 18 | 19 | This page documents those container images ([images comparison](#images-comparison)): 20 | 21 | - [![ejabberd Container](https://img.shields.io/badge/ejabberd-grey?logo=opencontainersinitiative&logoColor=2094f3)](https://github.com/processone/ejabberd/pkgs/container/ejabberd) 22 | published in [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd), 23 | built using [ejabberd](https://github.com/processone/ejabberd/tree/master/.github/container) repository, 24 | both for stable ejabberd releases and the `master` branch, in x64 and arm64 architectures. 25 | 26 | - [![ecs Container](https://img.shields.io/badge/ecs-grey?logo=docker&logoColor=2094f3)](https://hub.docker.com/r/ejabberd/ecs/) 27 | published in [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/), 28 | built using [docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs) repository 29 | for ejabberd stable releases in x64 architectures. 30 | 31 | For Microsoft Windows, see 32 | [Docker Desktop for Windows 10](https://www.process-one.net/blog/install-ejabberd-on-windows-10-using-docker-desktop/), 33 | and [Docker Toolbox for Windows 7](https://www.process-one.net/blog/install-ejabberd-on-windows-7-using-docker-toolbox/). 34 | 35 | For Kubernetes Helm, see [help-ejabberd](https://github.com/sando38/helm-ejabberd). 36 | 37 | 38 | Start ejabberd 39 | -------------- 40 | 41 | ### daemon 42 | 43 | Start ejabberd in a new container: 44 | 45 | ```bash 46 | docker run --name ejabberd -d -p 5222:5222 docker.io/ejabberd/ecs 47 | ``` 48 | 49 | That runs the container as a daemon, 50 | using ejabberd default configuration file and XMPP domain `localhost`. 51 | 52 | Restart the stopped ejabberd container: 53 | 54 | ```bash 55 | docker restart ejabberd 56 | ``` 57 | 58 | Stop the running container: 59 | 60 | ```bash 61 | docker stop ejabberd 62 | ``` 63 | 64 | Remove the ejabberd container: 65 | 66 | ```bash 67 | docker rm ejabberd 68 | ``` 69 | 70 | 71 | ### with Erlang console 72 | 73 | Start ejabberd with an interactive Erlang console attached using the `live` command: 74 | 75 | ```bash 76 | docker run --name ejabberd -it -p 5222:5222 docker.io/ejabberd/ecs live 77 | ``` 78 | 79 | That uses the default configuration file and XMPP domain `localhost`. 80 | 81 | 82 | ### with your data 83 | 84 | Pass a configuration file as a volume 85 | and share the local directory to store database: 86 | 87 | ```bash 88 | mkdir conf && cp ejabberd.yml.example conf/ejabberd.yml 89 | 90 | mkdir database && chown ejabberd database 91 | 92 | docker run --name ejabberd -it \ 93 | -v $(pwd)/conf/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml \ 94 | -v $(pwd)/database:/opt/ejabberd/database \ 95 | -p 5222:5222 docker.io/ejabberd/ecs live 96 | ``` 97 | 98 | Notice that ejabberd runs in the container with an account named `ejabberd` 99 | with UID 9000 and group `ejabberd` with GID 9000, 100 | and the volumes you mount must grant proper rights to that account. 101 | 102 | 103 | Next steps 104 | ---------- 105 | 106 | ### Register admin account 107 | 108 | #### [![ejabberd Container](https://img.shields.io/badge/ejabberd-grey?logo=opencontainersinitiative&logoColor=2094f3)](https://github.com/processone/ejabberd/pkgs/container/ejabberd) [:orange_circle:](#images-comparison) 109 | 110 | If you set the `REGISTER_ADMIN_PASSWORD` environment variable, 111 | an account is automatically registered with that password, 112 | and admin privileges are granted to it. 113 | The account created depends on what variables you have set: 114 | 115 | - `EJABBERD_MACRO_ADMIN=juliet@example.org` -> `juliet@example.org` 116 | - `EJABBERD_MACRO_HOST=example.org` -> `admin@example.org` 117 | - None of those variables are set -> `admin@localhost` 118 | 119 | The account registration is shown in the container log: 120 | 121 | ``` 122 | :> ejabberdctl register admin example.org somePassw0rd 123 | User admin@example.org successfully registered 124 | ``` 125 | 126 | Alternatively, you can register the account manually yourself 127 | and edit `conf/ejabberd.yml` and add the ACL as explained in 128 | [ejabberd Docs: Administration Account](https://docs.ejabberd.im/admin/install/next-steps/#administration-account). 129 | 130 | --- 131 | 132 | #### [![ecs Container](https://img.shields.io/badge/ecs-grey?logo=docker&logoColor=2094f3)](https://hub.docker.com/r/ejabberd/ecs/) 133 | 134 | The default ejabberd configuration has already granted admin privilege 135 | to an account that would be called `admin@localhost`, 136 | so you just need to register it, for example: 137 | 138 | ```bash 139 | docker exec -it ejabberd ejabberdctl register admin localhost passw0rd 140 | ``` 141 | 142 | ### Check ejabberd log 143 | 144 | Check the content of the log files inside the container, 145 | even if you do not put it on a shared persistent drive: 146 | 147 | ```bash 148 | docker exec -it ejabberd tail -f logs/ejabberd.log 149 | ``` 150 | 151 | 152 | ### Inspect container files 153 | 154 | The container uses Alpine Linux. Start a shell inside the container: 155 | 156 | ```bash 157 | docker exec -it ejabberd sh 158 | ``` 159 | 160 | 161 | ### Open debug console 162 | 163 | Open an interactive debug Erlang console attached to a running ejabberd in a running container: 164 | 165 | ```bash 166 | docker exec -it ejabberd ejabberdctl debug 167 | ``` 168 | 169 | 170 | ### CAPTCHA 171 | 172 | ejabberd includes two example CAPTCHA scripts. 173 | If you want to use any of them, first install some additional required libraries: 174 | 175 | ```bash 176 | docker exec --user root ejabberd apk add imagemagick ghostscript-fonts bash 177 | ``` 178 | 179 | Now update your ejabberd configuration file, for example: 180 | ```bash 181 | docker exec -it ejabberd vi conf/ejabberd.yml 182 | ``` 183 | 184 | and add this option: 185 | ```yaml 186 | captcha_cmd: "$HOME/bin/captcha.sh" 187 | ``` 188 | 189 | Finally, reload the configuration file or restart the container: 190 | ```bash 191 | docker exec ejabberd ejabberdctl reload_config 192 | ``` 193 | 194 | If the CAPTCHA image is not visible, there may be a problem generating it 195 | (the ejabberd log file may show some error message); 196 | or the image URL may not be correctly detected by ejabberd, 197 | in that case you can set the correct URL manually, for example: 198 | ```yaml 199 | captcha_url: https://localhost:5443/captcha 200 | ``` 201 | 202 | For more details about CAPTCHA options, please check the 203 | [CAPTCHA](https://docs.ejabberd.im/admin/configuration/basic/#captcha) 204 | documentation section. 205 | 206 | 207 | Advanced 208 | -------- 209 | 210 | ### Ports 211 | 212 | The container image exposes several ports 213 | (check also [Docs: Firewall Settings](https://docs.ejabberd.im/admin/guide/security/#firewall-settings)): 214 | 215 | - `5222`: The default port for XMPP clients. 216 | - `5269`: For XMPP federation. Only needed if you want to communicate with users on other servers. 217 | - `5280`: For admin interface (URL is `admin/`). 218 | - `1880`: For admin interface (URL is `/`, useful for [podman-desktop](https://podman-desktop.io/) and [docker-desktop](https://www.docker.com/products/docker-desktop/)) [:orange_circle:](#images-comparison) 219 | - `5443`: With encryption, used for admin interface, API, CAPTCHA, OAuth, Websockets and XMPP BOSH. 220 | - `1883`: Used for MQTT 221 | - `4369-4399`: EPMD and Erlang connectivity, used for `ejabberdctl` and clustering 222 | - `5210`: Erlang connectivity when `ERL_DIST_PORT` is set, alternative to EPMD [:orange_circle:](#images-comparison) 223 | 224 | 225 | ### Volumes 226 | 227 | ejabberd produces two types of data: log files and database spool files (Mnesia). 228 | This is the kind of data you probably want to store on a persistent or local drive (at least the database). 229 | 230 | The volumes you may want to map: 231 | 232 | - `/opt/ejabberd/conf/`: Directory containing configuration and certificates 233 | - `/opt/ejabberd/database/`: Directory containing Mnesia database. 234 | You should back up or export the content of the directory to persistent storage 235 | (host storage, local storage, any storage plugin) 236 | - `/opt/ejabberd/logs/`: Directory containing log files 237 | - `/opt/ejabberd/upload/`: Directory containing uploaded files. This should also be backed up. 238 | 239 | All these files are owned by an account named `ejabberd` with group `ejabberd` in the container. 240 | Its corresponding `UID:GID` is `9000:9000`. 241 | If you prefer bind mounts instead of volumes, then 242 | you need to map this to valid `UID:GID` on your host to get read/write access on 243 | mounted directories. 244 | 245 | If using Docker, try: 246 | ```bash 247 | mkdir database 248 | sudo chown 9000:9000 database 249 | ``` 250 | 251 | If using Podman, try: 252 | ```bash 253 | mkdir database 254 | podman unshare chown 9000:9000 database 255 | ``` 256 | 257 | It's possible to install additional ejabberd modules using volumes, check 258 | [this Docs tutorial](https://docs.ejabberd.im/developer/extending-ejabberd/modules/#your-module-in-ejabberd-modules-with-ejabberd-container). 259 | 260 | 261 | ### Commands on start 262 | 263 | The ejabberdctl script reads the `CTL_ON_CREATE` environment variable 264 | the first time the container is started, 265 | and reads `CTL_ON_START` every time the container is started. 266 | Those variables can contain one ejabberdctl command, 267 | or several commands separated with the blankspace and `;` characters. 268 | 269 | If any of those commands returns a failure, the container starting gets aborted. 270 | If there is a command with a result that can be ignored, 271 | prefix that command with `!` 272 | 273 | This example, registers an `admin@localhost` account when the container is first created. 274 | Everytime the container starts, it shows the list of registered accounts, 275 | checks that the admin account exists and password is valid, 276 | changes the password of an account if it exists (ignoring any failure), 277 | and shows the ejabberd starts (check also the [full example](#customized-example)): 278 | ```yaml 279 | environment: 280 | - CTL_ON_CREATE=register admin localhost asd 281 | - CTL_ON_START=stats registeredusers ; 282 | check_password admin localhost asd ; 283 | ! change_password bot123 localhost qqq ; 284 | status 285 | ``` 286 | 287 | 288 | ### Macros in environment [:high_brightness:](#images-comparison) 289 | 290 | ejabberd reads `EJABBERD_MACRO_*` environment variables 291 | and uses them to define the corresponding 292 | [macros](https://docs.ejabberd.im/admin/configuration/file-format/#macros-in-configuration-file), 293 | overwriting the corresponding macro definition if it was set in the configuration file. 294 | This is supported since ejabberd 24.12. 295 | 296 | For example, if you configure this in `ejabberd.yml`: 297 | 298 | ```yaml 299 | acl: 300 | admin: 301 | user: ADMIN 302 | ``` 303 | 304 | now you can define the admin account JID using an environment variable: 305 | ```yaml 306 | environment: 307 | - EJABBERD_MACRO_ADMIN=admin@localhost 308 | ``` 309 | 310 | Check the [full example](#customized-example) for other example. 311 | 312 | 313 | ### ejabberdapi 314 | 315 | When the container is running (and thus ejabberd), you can exec commands inside the container 316 | using `ejabberdctl` or any other of the available interfaces, see 317 | [Understanding ejabberd "commands"](https://docs.ejabberd.im/developer/ejabberd-api/#understanding-ejabberd-commands) 318 | 319 | Additionally, the container image includes the `ejabberdapi` executable. 320 | Please check the [ejabberd-api homepage](https://github.com/processone/ejabberd-api) 321 | for configuration and usage details. 322 | 323 | For example, if you configure ejabberd like this: 324 | ```yaml 325 | listen: 326 | - 327 | port: 5282 328 | module: ejabberd_http 329 | request_handlers: 330 | "/api": mod_http_api 331 | 332 | acl: 333 | loopback: 334 | ip: 335 | - 127.0.0.0/8 336 | - ::1/128 337 | - ::FFFF:127.0.0.1/128 338 | 339 | api_permissions: 340 | "admin access": 341 | who: 342 | access: 343 | allow: 344 | acl: loopback 345 | what: 346 | - "register" 347 | ``` 348 | 349 | Then you could register new accounts with this query: 350 | 351 | ```bash 352 | docker exec -it ejabberd ejabberdapi register --endpoint=http://127.0.0.1:5282/ --jid=admin@localhost --password=passw0rd 353 | ``` 354 | 355 | 356 | ### Clustering 357 | 358 | When setting several containers to form a 359 | [cluster of ejabberd nodes](https://docs.ejabberd.im/admin/guide/clustering/), 360 | each one must have a different 361 | [Erlang Node Name](https://docs.ejabberd.im/admin/guide/security/#erlang-node-name) 362 | and the same 363 | [Erlang Cookie](https://docs.ejabberd.im/admin/guide/security/#erlang-cookie). 364 | 365 | For this you can either: 366 | 367 | - edit `conf/ejabberdctl.cfg` and set variables `ERLANG_NODE` and `ERLANG_COOKIE` 368 | - set the environment variables `ERLANG_NODE_ARG` and `ERLANG_COOKIE` 369 | 370 | --- 371 | 372 | Example to connect a local `ejabberdctl` to a containerized ejabberd: 373 | 374 | 1. When creating the container, export port 5210, and set `ERLANG_COOKIE`: 375 | ```sh 376 | docker run --name ejabberd -it \ 377 | -e ERLANG_COOKIE=`cat $HOME/.erlang.cookie` \ 378 | -p 5210:5210 -p 5222:5222 \ 379 | docker.io/ejabberd/ecs 380 | ``` 381 | 2. Set `ERL_DIST_PORT=5210` in `ejabberdctl.cfg` of container and local ejabberd 382 | 3. Restart the container 383 | 4. Now use `ejabberdctl` in your local ejabberd deployment 384 | 385 | To connect using a local `ejabberd` script: 386 | ```sh 387 | ERL_DIST_PORT=5210 _build/dev/rel/ejabberd/bin/ejabberd ping 388 | ``` 389 | 390 | Example using environment variables (see full example [docker-compose.yml](https://github.com/processone/docker-ejabberd/issues/64#issuecomment-887741332)): 391 | ```yaml 392 | environment: 393 | - ERLANG_NODE_ARG=ejabberd@node7 394 | - ERLANG_COOKIE=dummycookie123 395 | ``` 396 | 397 | --- 398 | 399 | Once you have the ejabberd nodes properly set and running, 400 | you can tell the secondary nodes to join the master node using the 401 | [`join_cluster`](https://docs.ejabberd.im/developer/ejabberd-api/admin-api/#join-cluster) 402 | API call. 403 | 404 | Example using environment variables (see the full 405 | [`docker-compose.yml` clustering example](#clustering-example)): 406 | ```yaml 407 | environment: 408 | - ERLANG_NODE_ARG=ejabberd@replica 409 | - ERLANG_COOKIE=dummycookie123 410 | - CTL_ON_CREATE=join_cluster ejabberd@main 411 | ``` 412 | 413 | ### Change Mnesia Node Name 414 | 415 | To use the same Mnesia database in a container with a different hostname, 416 | it is necessary to change the old hostname stored in Mnesia. 417 | 418 | This section is equivalent to the ejabberd Documentation 419 | [Change Computer Hostname](https://docs.ejabberd.im/admin/guide/managing/#change-computer-hostname), 420 | but particularized to containers that use this 421 | ecs container image from ejabberd 23.01 or older. 422 | 423 | #### Setup Old Container 424 | 425 | Let's assume a container running ejabberd 23.01 (or older) from 426 | this ecs container image, with the database directory binded 427 | and one registered account. 428 | This can be produced with: 429 | ```bash 430 | OLDCONTAINER=ejaold 431 | NEWCONTAINER=ejanew 432 | 433 | mkdir database 434 | sudo chown 9000:9000 database 435 | docker run -d --name $OLDCONTAINER -p 5222:5222 \ 436 | -v $(pwd)/database:/opt/ejabberd/database \ 437 | docker.io/ejabberd/ecs:23.01 438 | docker exec -it $OLDCONTAINER ejabberdctl started 439 | docker exec -it $OLDCONTAINER ejabberdctl register user1 localhost somepass 440 | docker exec -it $OLDCONTAINER ejabberdctl registered_users localhost 441 | ``` 442 | 443 | Methods to know the Erlang node name: 444 | ```bash 445 | ls database/ | grep ejabberd@ 446 | docker exec -it $OLDCONTAINER ejabberdctl status 447 | docker exec -it $OLDCONTAINER grep "started in the node" logs/ejabberd.log 448 | ``` 449 | 450 | #### Change Mnesia Node 451 | 452 | First of all let's store the Erlang node names and paths in variables. 453 | In this example they would be: 454 | ```bash 455 | OLDCONTAINER=ejaold 456 | NEWCONTAINER=ejanew 457 | OLDNODE=ejabberd@95145ddee27c 458 | NEWNODE=ejabberd@localhost 459 | OLDFILE=/opt/ejabberd/database/old.backup 460 | NEWFILE=/opt/ejabberd/database/new.backup 461 | ``` 462 | 463 | 1. Start your old container that can still read the Mnesia database correctly. 464 | If you have the Mnesia spool files, 465 | but don't have access to the old container anymore, go to 466 | [Create Temporary Container](#create-temporary-container) 467 | and later come back here. 468 | 469 | 2. Generate a backup file and check it was created: 470 | ```bash 471 | docker exec -it $OLDCONTAINER ejabberdctl backup $OLDFILE 472 | ls -l database/*.backup 473 | ``` 474 | 475 | 3. Stop ejabberd: 476 | ```bash 477 | docker stop $OLDCONTAINER 478 | ``` 479 | 480 | 4. Create the new container. For example: 481 | ```bash 482 | docker run \ 483 | --name $NEWCONTAINER \ 484 | -d \ 485 | -p 5222:5222 \ 486 | -v $(pwd)/database:/opt/ejabberd/database \ 487 | docker.io/ejabberd/ecs:latest 488 | ``` 489 | 490 | 5. Convert the backup file to new node name: 491 | ```bash 492 | docker exec -it $NEWCONTAINER ejabberdctl mnesia_change_nodename $OLDNODE $NEWNODE $OLDFILE $NEWFILE 493 | ``` 494 | 495 | 6. Install the backup file as a fallback: 496 | ```bash 497 | docker exec -it $NEWCONTAINER ejabberdctl install_fallback $NEWFILE 498 | ``` 499 | 500 | 7. Restart the container: 501 | ```bash 502 | docker restart $NEWCONTAINER 503 | ``` 504 | 505 | 8. Check that the information of the old database is available. 506 | In this example, it should show that the account `user1` is registered: 507 | ```bash 508 | docker exec -it $NEWCONTAINER ejabberdctl registered_users localhost 509 | ``` 510 | 511 | 9. When the new container is working perfectly with the converted Mnesia database, 512 | you may want to remove the unneeded files: 513 | the old container, the old Mnesia spool files, and the backup files. 514 | 515 | #### Create Temporary Container 516 | 517 | In case the old container that used the Mnesia database is not available anymore, 518 | a temporary container can be created just to read the Mnesia database 519 | and make a backup of it, as explained in the previous section. 520 | 521 | This method uses `--hostname` command line argument for docker, 522 | and `ERLANG_NODE_ARG` environment variable for ejabberd. 523 | Their values must be the hostname of your old container 524 | and the Erlang node name of your old ejabberd node. 525 | To know the Erlang node name please check 526 | [Setup Old Container](#setup-old-container). 527 | 528 | Command line example: 529 | ```bash 530 | OLDHOST=${OLDNODE#*@} 531 | docker run \ 532 | -d \ 533 | --name $OLDCONTAINER \ 534 | --hostname $OLDHOST \ 535 | -p 5222:5222 \ 536 | -v $(pwd)/database:/opt/ejabberd/database \ 537 | -e ERLANG_NODE_ARG=$OLDNODE \ 538 | docker.io/ejabberd/ecs:latest 539 | ``` 540 | 541 | Check the old database content is available: 542 | ```bash 543 | docker exec -it $OLDCONTAINER ejabberdctl registered_users localhost 544 | ``` 545 | 546 | Now that you have ejabberd running with access to the Mnesia database, 547 | you can continue with step 2 of previous section 548 | [Change Mnesia Node](#change-mnesia-node). 549 | 550 | 551 | Build Container Image 552 | ---------------- 553 | 554 | The container image includes ejabberd as a standalone OTP release built using Elixir. 555 | 556 | ### Build `ejabberd` [![ejabberd Container](https://img.shields.io/badge/ejabberd-grey?logo=opencontainersinitiative&logoColor=2094f3)](https://github.com/processone/ejabberd/pkgs/container/ejabberd) 557 | 558 | The ejabberd Erlang/OTP release is configured with: 559 | 560 | - `mix.exs`: Customize ejabberd release 561 | - `vars.config`: ejabberd compilation configuration options 562 | - `config/runtime.exs`: Customize ejabberd paths 563 | - `ejabberd.yml.template`: ejabberd default config file 564 | 565 | #### Direct build 566 | 567 | Build ejabberd Community Server container image from ejabberd master git repository: 568 | 569 | ```bash 570 | docker buildx build \ 571 | -t personal/ejabberd \ 572 | -f .github/container/Dockerfile \ 573 | . 574 | ``` 575 | 576 | #### Podman build 577 | 578 | To build the image using Podman, please notice: 579 | 580 | - `EXPOSE 4369-4399` port range is not supported, remove that in Dockerfile 581 | - It mentions that `healthcheck` is not supported by the Open Container Initiative image format 582 | - to start with command `live`, you may want to add environment variable `EJABBERD_BYPASS_WARNINGS=true` 583 | 584 | ```bash 585 | podman build \ 586 | -t ejabberd \ 587 | -f .github/container/Dockerfile \ 588 | . 589 | 590 | podman run --name eja1 -d -p 5222:5222 localhost/ejabberd 591 | 592 | podman exec eja1 ejabberdctl status 593 | 594 | podman exec -it eja1 sh 595 | 596 | podman stop eja1 597 | 598 | podman run --name eja1 -it -e EJABBERD_BYPASS_WARNINGS=true -p 5222:5222 localhost/ejabberd live 599 | ``` 600 | 601 | ### Build `ecs` [![ecs Container](https://img.shields.io/badge/ecs-grey?logo=docker&logoColor=2094f3)](https://hub.docker.com/r/ejabberd/ecs/) 602 | 603 | The ejabberd Erlang/OTP release is configured with: 604 | 605 | - `rel/config.exs`: Customize ejabberd release 606 | - `rel/dev.exs`: ejabberd environment configuration for development release 607 | - `rel/prod.exs`: ejabberd environment configuration for production release 608 | - `vars.config`: ejabberd compilation configuration options 609 | - `conf/ejabberd.yml`: ejabberd default config file 610 | 611 | Build ejabberd Community Server base image from ejabberd master on Github: 612 | 613 | ```bash 614 | docker build -t personal/ejabberd . 615 | ``` 616 | 617 | Build ejabberd Community Server base image for a given ejabberd version: 618 | 619 | ```bash 620 | ./build.sh 18.03 621 | ``` 622 | 623 | Composer Examples 624 | ----------------- 625 | 626 | ### Minimal Example 627 | 628 | This is the barely minimal file to get a usable ejabberd. 629 | 630 | If using Docker, write this `docker-compose.yml` file 631 | and start it with `docker-compose up`: 632 | 633 | ```yaml 634 | services: 635 | main: 636 | image: docker.io/ejabberd/ecs 637 | container_name: ejabberd 638 | ports: 639 | - "5222:5222" 640 | - "5269:5269" 641 | - "5280:5280" 642 | - "5443:5443" 643 | ``` 644 | 645 | If using Podman, write this `minimal.yml` file 646 | and start it with `podman kube play minimal.yml`: 647 | 648 | ```yaml 649 | apiVersion: v1 650 | 651 | kind: Pod 652 | 653 | metadata: 654 | name: ejabberd 655 | 656 | spec: 657 | containers: 658 | 659 | - name: ejabberd 660 | image: docker.io/ejabberd/ecs 661 | ports: 662 | - containerPort: 5222 663 | hostPort: 5222 664 | - containerPort: 5269 665 | hostPort: 5269 666 | - containerPort: 5280 667 | hostPort: 5280 668 | - containerPort: 5443 669 | hostPort: 5443 670 | ``` 671 | 672 | 673 | ### Customized Example 674 | 675 | This example shows the usage of several customizations: 676 | it uses a local configuration file, 677 | defines a configuration macro using an environment variable, 678 | stores the mnesia database in a local path, 679 | registers an account when it's created, 680 | and checks the number of registered accounts every time it's started. 681 | 682 | Prepare an ejabberd configuration file: 683 | ```bash 684 | mkdir conf && cp ejabberd.yml.example conf/ejabberd.yml 685 | ``` 686 | 687 | Create the database directory and allow the container access to it: 688 | 689 | - Docker: 690 | ```bash 691 | mkdir database && sudo chown 9000:9000 database 692 | ``` 693 | - Podman: 694 | ```bash 695 | mkdir database && podman unshare chown 9000:9000 database 696 | ``` 697 | 698 | If using Docker, write this `docker-compose.yml` file 699 | and start it with `docker-compose up`: 700 | 701 | ```yaml 702 | version: '3.7' 703 | 704 | services: 705 | 706 | main: 707 | image: docker.io/ejabberd/ecs 708 | container_name: ejabberd 709 | environment: 710 | - EJABBERD_MACRO_HOST=example.com 711 | - EJABBERD_MACRO_ADMIN=admin@example.com 712 | - REGISTER_ADMIN_PASSWORD=somePassw0rd 713 | - CTL_ON_START=registered_users example.com ; 714 | status 715 | ports: 716 | - "5222:5222" 717 | - "5269:5269" 718 | - "5280:5280" 719 | - "5443:5443" 720 | volumes: 721 | - ./conf/ejabberd.yml:/opt/ejabberd/conf/ejabberd.yml:ro 722 | - ./database:/opt/ejabberd/database 723 | ``` 724 | 725 | If using Podman, write this `custom.yml` file 726 | and start it with `podman kube play custom.yml`: 727 | 728 | ```yaml 729 | apiVersion: v1 730 | 731 | kind: Pod 732 | 733 | metadata: 734 | name: ejabberd 735 | 736 | spec: 737 | containers: 738 | 739 | - name: ejabberd 740 | image: docker.io/ejabberd/ecs 741 | env: 742 | - name: EJABBERD_MACRO_HOST 743 | value: example.com 744 | - name: EJABBERD_MACRO_ADMIN 745 | value: admin@example.com 746 | - name: REGISTER_ADMIN_PASSWORD 747 | value: somePassw0rd 748 | - name: CTL_ON_START 749 | value: registered_users example.com ; 750 | status 751 | ports: 752 | - containerPort: 5222 753 | hostPort: 5222 754 | - containerPort: 5269 755 | hostPort: 5269 756 | - containerPort: 5280 757 | hostPort: 5280 758 | - containerPort: 5443 759 | hostPort: 5443 760 | volumeMounts: 761 | - mountPath: /opt/ejabberd/conf/ejabberd.yml 762 | name: config 763 | readOnly: true 764 | - mountPath: /opt/ejabberd/database 765 | name: db 766 | 767 | volumes: 768 | - name: config 769 | hostPath: 770 | path: ./conf/ejabberd.yml 771 | type: File 772 | - name: db 773 | hostPath: 774 | path: ./database 775 | type: DirectoryOrCreate 776 | ``` 777 | 778 | 779 | ### Clustering Example 780 | 781 | In this example, the main container is created first. 782 | Once it is fully started and healthy, a second container is created, 783 | and once ejabberd is started in it, it joins the first one. 784 | 785 | An account is registered in the first node when created (and 786 | we ignore errors that can happen when doing that - for example 787 | when account already exists), 788 | and it should exist in the second node after join. 789 | 790 | Notice that in this example the main container does not have access 791 | to the exterior; the replica exports the ports and can be accessed. 792 | 793 | If using Docker, write this `docker-compose.yml` file 794 | and start it with `docker-compose up`: 795 | 796 | ```yaml 797 | version: '3.7' 798 | 799 | services: 800 | 801 | main: 802 | image: docker.io/ejabberd/ecs 803 | container_name: main 804 | environment: 805 | - ERLANG_NODE_ARG=ejabberd@main 806 | - ERLANG_COOKIE=dummycookie123 807 | - CTL_ON_CREATE=! register admin localhost asd 808 | healthcheck: 809 | test: netstat -nl | grep -q 5222 810 | start_period: 5s 811 | interval: 5s 812 | timeout: 5s 813 | retries: 120 814 | 815 | replica: 816 | image: docker.io/ejabberd/ecs 817 | container_name: replica 818 | depends_on: 819 | main: 820 | condition: service_healthy 821 | environment: 822 | - ERLANG_NODE_ARG=ejabberd@replica 823 | - ERLANG_COOKIE=dummycookie123 824 | - CTL_ON_CREATE=join_cluster ejabberd@main 825 | - CTL_ON_START=registered_users localhost ; 826 | status 827 | ports: 828 | - "5222:5222" 829 | - "5269:5269" 830 | - "5280:5280" 831 | - "5443:5443" 832 | ``` 833 | 834 | If using Podman, write this `cluster.yml` file 835 | and start it with `podman kube play cluster.yml`: 836 | 837 | ```yaml 838 | apiVersion: v1 839 | 840 | kind: Pod 841 | 842 | metadata: 843 | name: cluster 844 | 845 | spec: 846 | containers: 847 | 848 | - name: first 849 | image: docker.io/ejabberd/ecs 850 | env: 851 | - name: ERLANG_NODE_ARG 852 | value: main@cluster 853 | - name: ERLANG_COOKIE 854 | value: dummycookie123 855 | - name: CTL_ON_CREATE 856 | value: register admin localhost asd 857 | - name: CTL_ON_START 858 | value: stats registeredusers ; 859 | status 860 | - name: EJABBERD_MACRO_PORT_C2S 861 | value: 6222 862 | - name: EJABBERD_MACRO_PORT_C2S_TLS 863 | value: 6223 864 | - name: EJABBERD_MACRO_PORT_S2S 865 | value: 6269 866 | - name: EJABBERD_MACRO_PORT_HTTP_TLS 867 | value: 6443 868 | - name: EJABBERD_MACRO_PORT_HTTP 869 | value: 6280 870 | - name: EJABBERD_MACRO_PORT_MQTT 871 | value: 6883 872 | - name: EJABBERD_MACRO_PORT_PROXY65 873 | value: 6777 874 | volumeMounts: 875 | - mountPath: /opt/ejabberd/conf/ejabberd.yml 876 | name: config 877 | readOnly: true 878 | 879 | - name: second 880 | image: docker.io/ejabberd/ecs 881 | env: 882 | - name: ERLANG_NODE_ARG 883 | value: replica@cluster 884 | - name: ERLANG_COOKIE 885 | value: dummycookie123 886 | - name: CTL_ON_CREATE 887 | value: join_cluster main@cluster ; 888 | started ; 889 | list_cluster 890 | - name: CTL_ON_START 891 | value: stats registeredusers ; 892 | check_password admin localhost asd ; 893 | status 894 | ports: 895 | - containerPort: 5222 896 | hostPort: 5222 897 | - containerPort: 5280 898 | hostPort: 5280 899 | volumeMounts: 900 | - mountPath: /opt/ejabberd/conf/ejabberd.yml 901 | name: config 902 | readOnly: true 903 | 904 | volumes: 905 | - name: config 906 | hostPath: 907 | path: ./conf/ejabberd.yml 908 | type: File 909 | 910 | ``` 911 | 912 | 913 | Images Comparison 914 | ----------------- 915 | 916 | Let's summarize the differences between both container images. Legend: 917 | 918 | - :sparkle: is the recommended alternative 919 | - :orange_circle: added in the latest release (ejabberd 25.03) 920 | - :high_brightness: added in the previous release (ejabberd 24.12) 921 | - :low_brightness: added in the pre-previous release (ejabberd 24.10) 922 | 923 | | | [![ejabberd Container](https://img.shields.io/badge/ejabberd-grey?logo=opencontainersinitiative&logoColor=2094f3)](https://github.com/processone/ejabberd/pkgs/container/ejabberd) | [![ecs Container](https://img.shields.io/badge/ecs-grey?logo=docker&logoColor=2094f3)](https://hub.docker.com/r/ejabberd/ecs/) | 924 | |:----------------------|:------------------|:-----------------------| 925 | | Source code | [ejabberd/.github/container](https://github.com/processone/ejabberd/tree/master/.github/container) | [docker-ejabberd/ecs](https://github.com/processone/docker-ejabberd/tree/master/ecs) | 926 | | Generated by | [container.yml](https://github.com/processone/ejabberd/blob/master/.github/workflows/container.yml) | [tests.yml](https://github.com/processone/docker-ejabberd/blob/master/.github/workflows/tests.yml) | 927 | | Built for | stable releases
`master` branch | stable releases
[`master` branch zip](https://github.com/processone/docker-ejabberd/actions/workflows/tests.yml) | 928 | | Architectures | `linux/amd64`
`linux/arm64` | `linux/amd64` | 929 | | Software | Erlang/OTP 27.3.2-alpine
Elixir 1.18.3 | Alpine 3.19
Erlang/OTP 26.2
Elixir 1.15.7 | 930 | | Published in | [ghcr.io/processone/ejabberd](https://github.com/processone/ejabberd/pkgs/container/ejabberd) | [docker.io/ejabberd/ecs](https://hub.docker.com/r/ejabberd/ecs/)
[ghcr.io/processone/ecs](https://github.com/processone/docker-ejabberd/pkgs/container/ecs) | 931 | | :black_square_button: **Additional content** | 932 | | [ejabberd-contrib](https://docs.ejabberd.im/admin/guide/modules/#ejabberd-contrib) | included | not included | 933 | | [ejabberdapi](#ejabberdapi) | included :orange_circle: | included | 934 | | :black_square_button: **Ports** | 935 | | [1880](#ports) for WebAdmin | yes :orange_circle: | yes :orange_circle: | 936 | | [5210](#ports) for `ERL_DIST_PORT` | supported | supported :orange_circle: | 937 | | :black_square_button: **Paths** | 938 | | `$HOME` | `/opt/ejabberd/` | `/home/ejabberd/` | 939 | | User data | `$HOME` :sparkle:
`/home/ejabberd/` :orange_circle: | `$HOME`
`/opt/ejabberd/` :sparkle: :low_brightness: | 940 | | `ejabberdctl` | `ejabberdctl` :sparkle:
`bin/ejabberdctl` :orange_circle: | `bin/ejabberdctl`
`ejabberdctl` :sparkle: :low_brightness: | 941 | | [`captcha.sh`](#captcha) | `$HOME/bin/captcha.sh` :orange_circle: | `$HOME/bin/captcha.sh` :orange_circle: | 942 | | `*.sql` files | `$HOME/sql/*.sql` :sparkle: :orange_circle:
`$HOME/database/*.sql` :orange_circle: | `$HOME/database/*.sql`
`$HOME/sql/*.sql` :sparkle: :orange_circle: | 943 | | Mnesia spool files | `$HOME/database/` :sparkle:
`$HOME/database/NODENAME/` :orange_circle: | `$HOME/database/NODENAME/`
`$HOME/database/` :sparkle: :orange_circle: | 944 | | :black_square_button: **Variables** | 945 | | [`EJABBERD_MACRO_*`](#macros-in-environment) | supported :high_brightness: | supported :high_brightness: | 946 | | Macros used in `ejabberd.yml` | yes :orange_circle: | yes :orange_circle: | 947 | | [`EJABBERD_MACRO_ADMIN`](#register-admin-account) | Grant admin rights :orange_circle:
(default `admin@localhost`)
| Hardcoded `admin@localhost` | 948 | | [`REGISTER_ADMIN_PASSWORD`](#register-admin-account) | Register admin account :orange_circle: | unsupported | 949 | | `CTL_OVER_HTTP` | enabled :orange_circle: | unsupported | 950 | -------------------------------------------------------------------------------- /ecs/bin/ejabberdctl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # define default configuration 4 | POLL=true 5 | ERL_MAX_PORTS=32000 6 | ERL_PROCESSES=250000 7 | ERL_MAX_ETS_TABLES=1400 8 | FIREWALL_WINDOW="4370-4379" 9 | INET_DIST_INTERFACE="" 10 | ERLANG_NODE=ejabberd@localhost 11 | EJABBERD_BYPASS_WARNINGS=true 12 | 13 | # define default environment variables 14 | ROOT_DIR="/home/ejabberd" 15 | HOME_DIR="$ROOT_DIR" 16 | ERL="$ROOT_DIR"/bin/erl 17 | IEX="$ROOT_DIR"/bin/iex 18 | EPMD="$ROOT_DIR"/bin/epmd 19 | INSTALLUSER=ejabberd 20 | 21 | # check the proper system user is used 22 | case $(id -un) in 23 | "$INSTALLUSER") 24 | EXEC_CMD="as_current_user" 25 | [ -e "$HOME"/conf/ejabberd.yml ] && HOME_DIR="$HOME" 26 | ;; 27 | root) 28 | if [ -n "$INSTALLUSER" ] ; then 29 | EXEC_CMD="as_install_user" 30 | HOME=$(su - ejabberd -c pwd) 31 | [ -e "$HOME"/conf/ejabberd.yml ] && HOME_DIR="$HOME" 32 | else 33 | EXEC_CMD="as_current_user" 34 | echo "WARNING: It is not recommended to run ejabberd as root" >&2 35 | fi 36 | ;; 37 | *) 38 | if [ -n "$INSTALLUSER" ] ; then 39 | echo "ERROR: This command can only be run by root or the user $INSTALLUSER" >&2 40 | exit 7 41 | else 42 | EXEC_CMD="as_current_user" 43 | fi 44 | ;; 45 | esac 46 | 47 | # parse command line parameters 48 | while [ $# -gt 0 ]; do 49 | case $1 in 50 | -n|--node) ERLANG_NODE_ARG=$2; shift 2;; 51 | -s|--spool) SPOOL_DIR=$2; shift 2;; 52 | -l|--logs) LOGS_DIR=$2; shift 2;; 53 | -f|--config) EJABBERD_CONFIG_PATH=$2; shift 2;; 54 | -c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift 2;; 55 | -d|--config-dir) ETC_DIR=$2; shift 2;; 56 | -t|--no-timeout) NO_TIMEOUT="--no-timeout"; shift;; 57 | *) break;; 58 | esac 59 | done 60 | 61 | # define ejabberd variables if not already defined from the command line 62 | : "${ETC_DIR:="$HOME_DIR/conf"}" 63 | : "${LOGS_DIR:="$HOME_DIR/logs"}" 64 | : "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}" 65 | : "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}" 66 | # Allows passing extra Erlang command-line arguments in vm.args file 67 | : "${VMARGS:="$ETC_DIR/vm.args"}" 68 | [ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" 69 | [ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG" 70 | [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s" 71 | : "${SPOOL_DIR:="$HOME_DIR/database"}" 72 | : "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}" 73 | 74 | # backward support for old mnesia spool dir path 75 | : "${SPOOL_DIR_OLD:="$SPOOL_DIR/$ERLANG_NODE"}" 76 | [ -r "$SPOOL_DIR_OLD/schema.DAT" ] && [ ! -r "$SPOOL_DIR/schema.DAT" ] && SPOOL_DIR="$SPOOL_DIR_OLD" 77 | 78 | [ -n "$ERLANG_COOKIE" ] && [ ! -f "$HOME"/.erlang.cookie ] && { 79 | echo "$ERLANG_COOKIE" > "$HOME"/.erlang.cookie 80 | chmod 400 "$HOME"/.erlang.cookie 81 | } 82 | 83 | # define erl parameters 84 | ERLANG_OPTS="-boot_var RELEASE_LIB ../lib +K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" 85 | if [ -n "$FIREWALL_WINDOW" ] ; then 86 | ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" 87 | fi 88 | if [ -n "$INET_DIST_INTERFACE" ] ; then 89 | INET_DIST_INTERFACE2=$("$ERL" -boot start_clean -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt) 90 | if [ -n "$INET_DIST_INTERFACE2" ] ; then 91 | ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2" 92 | fi 93 | fi 94 | [ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -erl_epmd_port $ERL_DIST_PORT -start_epmd false" 95 | ERL_LIBS="$ROOT_DIR/lib" 96 | # if vm.args file exists in config directory, pass it to Erlang VM 97 | [ -f "$VMARGS" ] && ERLANG_OPTS="$ERLANG_OPTS -args_file $VMARGS" 98 | ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump 99 | ERL_INETRC="$ETC_DIR"/inetrc 100 | 101 | # define ejabberd parameters 102 | EJABBERD_OPTS="\ 103 | $(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]\{1,\}\).*/ \1/;s/:[ \t]*\(infinity\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\ 104 | $(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\ 105 | $(sed '/^log_burst_limit_count/!d;s/:[ \t]*\([0-9]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\ 106 | $(sed '/^log_burst_limit_window_time/!d;s/:[ \t]*\([0-9]*[a-z]*\).*/ \1 /;s/^/ /' "$EJABBERD_CONFIG_PATH")\ 107 | $EJABBERD_OPTS" 108 | [ -n "$EJABBERD_OPTS" ] && EJABBERD_OPTS="-ejabberd $EJABBERD_OPTS" 109 | EJABBERD_OPTS="-mnesia dir \"$SPOOL_DIR\" $MNESIA_OPTIONS $EJABBERD_OPTS -s ejabberd" 110 | 111 | # export global variables 112 | export EJABBERD_CONFIG_PATH 113 | export EJABBERD_LOG_PATH 114 | export EJABBERD_PID_PATH 115 | export ERL_CRASH_DUMP 116 | export ERL_EPMD_ADDRESS 117 | export ERL_DIST_PORT 118 | export ERL_INETRC 119 | export ERL_MAX_PORTS 120 | export ERL_MAX_ETS_TABLES 121 | export CONTRIB_MODULES_PATH 122 | export CONTRIB_MODULES_CONF_DIR 123 | export ERL_LIBS 124 | 125 | set_dist_client() 126 | { 127 | [ -n "$ERL_DIST_PORT" ] && ERLANG_OPTS="$ERLANG_OPTS -dist_listen false" 128 | } 129 | 130 | # run command either directly or via su $INSTALLUSER 131 | run_cmd() 132 | { 133 | case $EXEC_CMD in 134 | as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;; 135 | as_current_user) "$@" ;; 136 | esac 137 | } 138 | exec_cmd() 139 | { 140 | case $EXEC_CMD in 141 | as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;; 142 | as_current_user) exec "$@" ;; 143 | esac 144 | } 145 | run_erl() 146 | { 147 | NODE=$1; shift 148 | run_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@" 149 | } 150 | exec_erl() 151 | { 152 | NODE=$1; shift 153 | exec_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@" 154 | } 155 | exec_iex() 156 | { 157 | NODE=$1; shift 158 | exec_cmd "$IEX" -${S:--}name "$NODE" --erl "$ERLANG_OPTS" "$@" 159 | } 160 | 161 | # usage 162 | debugwarning() 163 | { 164 | if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then 165 | echo "--------------------------------------------------------------------" 166 | echo "" 167 | echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell" 168 | echo "to an already running ejabberd node." 169 | echo "If an ERROR is printed, it means the connection was not successful." 170 | echo "You can interact with the ejabberd node if you know how to use it." 171 | echo "Please be extremely cautious with your actions," 172 | echo "and exit immediately if you are not completely sure." 173 | echo "" 174 | echo "To exit and detach this shell from ejabberd, press:" 175 | echo " control+g and then q" 176 | echo "" 177 | #vt100 echo "Please do NOT use control+c in this debug shell !" 178 | #vt100 echo "" 179 | echo "--------------------------------------------------------------------" 180 | echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" 181 | echo " EJABBERD_BYPASS_WARNINGS=true" 182 | echo "Press return to continue" 183 | read -r _ 184 | echo "" 185 | fi 186 | } 187 | 188 | livewarning() 189 | { 190 | if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then 191 | echo "--------------------------------------------------------------------" 192 | echo "" 193 | echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode." 194 | echo "All log messages will be shown in the command shell." 195 | echo "You can interact with the ejabberd node if you know how to use it." 196 | echo "Please be extremely cautious with your actions," 197 | echo "and exit immediately if you are not completely sure." 198 | echo "" 199 | echo "To exit and detach this shell from ejabberd, press:" 200 | echo " control+g and then q" 201 | echo "" 202 | echo "--------------------------------------------------------------------" 203 | echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" 204 | echo " EJABBERD_BYPASS_WARNINGS=true" 205 | echo "Press return to continue" 206 | read -r _ 207 | echo "" 208 | fi 209 | } 210 | 211 | check_etop_result() 212 | { 213 | result=$? 214 | if [ $result -eq 1 ] ; then 215 | echo "" 216 | echo "It seems there was some problem running 'ejabberdctl etop'." 217 | echo "Is the error message something like this?" 218 | echo " Failed to load module 'etop' because it cannot be found..." 219 | echo "Then probably ejabberd was compiled with development tools disabled." 220 | echo "To use 'etop', recompile ejabberd with: ./configure --enable-tools" 221 | echo "" 222 | exit $result 223 | fi 224 | } 225 | 226 | check_iex_result() 227 | { 228 | result=$? 229 | if [ $result -eq 127 ] ; then 230 | echo "" 231 | echo "It seems there was some problem finding 'iex' binary from Elixir." 232 | echo "Probably ejabberd was compiled with Rebar3 and Elixir disabled, like:" 233 | echo " ./configure" 234 | echo "which is equivalent to:" 235 | echo " ./configure --with-rebar=rebar3 --disable-elixir" 236 | echo "To use 'iex', recompile ejabberd enabling Elixir or using Mix:" 237 | echo " ./configure --enable-elixir" 238 | echo " ./configure --with-rebar=mix" 239 | echo "" 240 | exit $result 241 | fi 242 | } 243 | 244 | help() 245 | { 246 | echo "" 247 | echo "Commands to start an ejabberd node:" 248 | echo " start Start in server mode" 249 | echo " foreground Start in server mode (attached)" 250 | echo " foreground-quiet Start in server mode (attached), show only critical messages" 251 | echo " live Start in interactive mode, with Erlang shell" 252 | echo " iexlive Start in interactive mode, with Elixir shell" 253 | echo "" 254 | echo "Commands to interact with a running ejabberd node:" 255 | echo " debug Attach an interactive Erlang shell to a running node" 256 | echo " iexdebug Attach an interactive Elixir shell to a running node" 257 | echo " etop Attach to a running node and start Erlang Top" 258 | echo " ping Send ping to the node, returns pong or pang" 259 | echo " started|stopped Wait for the node to fully start|stop" 260 | echo "" 261 | echo "Optional parameters when starting an ejabberd node:" 262 | echo " --config-dir dir Config ejabberd: $ETC_DIR" 263 | echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH" 264 | echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH" 265 | echo " --logs dir Directory for logs: $LOGS_DIR" 266 | echo " --spool dir Database spool dir: $SPOOL_DIR" 267 | echo " --node nodename ejabberd node name: $ERLANG_NODE" 268 | echo "" 269 | } 270 | 271 | # dynamic node name helper 272 | uid() 273 | { 274 | uuid=$(uuidgen 2>/dev/null) 275 | [ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid) 276 | [ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)") 277 | uuid=$(printf '%s' $uuid | sed 's/^\(...\).*$/\1/') 278 | [ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}" 279 | [ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}" 280 | [ $# -eq 2 ] && echo "${uuid}-${1}@${2}" 281 | } 282 | 283 | # stop epmd if there is no other running node 284 | stop_epmd() 285 | { 286 | [ -n "$ERL_DIST_PORT" ] && return 287 | "$EPMD" -names 2>/dev/null | grep -q name || "$EPMD" -kill >/dev/null 288 | } 289 | 290 | # make sure node not already running and node name unregistered 291 | # if all ok, ensure runtime directory exists and make it current directory 292 | check_start() 293 | { 294 | ECSIMAGE_DBPATH=$HOME/database/$ERLANG_NODE 295 | [ ! -d "$ECSIMAGE_DBPATH" ] && ln -s $HOME/database $HOME/database/$ERLANG_NODE 296 | [ -n "$ERL_DIST_PORT" ] && return 297 | "$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && { 298 | pgrep -f "$ERLANG_NODE" >/dev/null && { 299 | echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running." 300 | exit 4 301 | } 302 | pgrep beam >/dev/null && { 303 | echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered," 304 | echo " but no related beam process has been found." 305 | echo "Shutdown all other erlang nodes, and call 'epmd -kill'." 306 | exit 5 307 | } 308 | "$EPMD" -kill >/dev/null 309 | } 310 | } 311 | 312 | post_waiter_fork() 313 | { 314 | (FIRST_RUN=$FIRST_RUN "$0" post_waiter)& 315 | } 316 | 317 | post_waiter_waiting() 318 | { 319 | $0 started 320 | [ -n "$FIRST_RUN" ] && [ -n "$CTL_ON_CREATE" ] && (post_waiter_loop $CTL_ON_CREATE) 321 | [ -n "$CTL_ON_START" ] && post_waiter_loop $CTL_ON_START 322 | } 323 | 324 | post_waiter_loop() 325 | { 326 | LIST=$@ 327 | HEAD=${LIST%% ; *} 328 | TAIL=${LIST#* ; } 329 | HEAD2=${HEAD#\! *} 330 | echo ":> ejabberdctl $HEAD2" 331 | $0 $HEAD2 332 | ctlstatus=$? 333 | if [ $ctlstatus -ne 0 ] ; then 334 | if [ "$HEAD" != "$HEAD2" ] ; then 335 | echo ":> FAILURE in command '$HEAD2' !!! Ignoring result" 336 | else 337 | echo ":> FAILURE in command '$HEAD' !!! Stopping ejabberd..." 338 | $0 halt > /dev/null 339 | exit $ctlstatus 340 | fi 341 | fi 342 | [ "$HEAD" = "$TAIL" ] || post_waiter_loop $TAIL 343 | } 344 | 345 | # allow sync calls 346 | wait_status() 347 | { 348 | # args: status try delay 349 | # return: 0 OK, 1 KO 350 | timeout="$2" 351 | status=4 352 | while [ "$status" -ne "$1" ] ; do 353 | sleep "$3" 354 | timeout=$((timeout - 1)) 355 | if [ $timeout -eq 0 ] ; then 356 | status="$1" 357 | else 358 | run_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl -boot start_clean \ 359 | -extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null 360 | status="$?" 361 | fi 362 | done 363 | [ $timeout -gt 0 ] 364 | } 365 | 366 | # ensure we can change current directory to SPOOL_DIR 367 | [ -d "$SPOOL_DIR" ] || FIRST_RUN=true 368 | [ -d "$SPOOL_DIR" ] || run_cmd mkdir -p "$SPOOL_DIR" 369 | cd "$SPOOL_DIR" || { 370 | echo "ERROR: can not access directory $SPOOL_DIR" 371 | exit 6 372 | } 373 | 374 | # main 375 | case $1 in 376 | start) 377 | check_start 378 | exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached 379 | ;; 380 | foreground) 381 | check_start 382 | post_waiter_fork 383 | exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput 384 | ;; 385 | foreground-quiet) 386 | check_start 387 | exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput -ejabberd quiet true 388 | ;; 389 | live) 390 | livewarning 391 | check_start 392 | exec_erl "$ERLANG_NODE" $EJABBERD_OPTS 393 | ;; 394 | debug) 395 | debugwarning 396 | set_dist_client 397 | exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE" \ 398 | -boot start_clean 399 | ;; 400 | etop) 401 | set_dist_client 402 | exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \ 403 | -s erlang halt -output text \ 404 | -boot start_clean 405 | ;; 406 | iexdebug) 407 | debugwarning 408 | set_dist_client 409 | exec_iex "$(uid debug)" --remsh "$ERLANG_NODE" --boot start_clean 410 | ;; 411 | iexlive) 412 | livewarning 413 | exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd 414 | ;; 415 | ping) 416 | PEER=${2:-$ERLANG_NODE} 417 | [ "$PEER" = "${PEER%.*}" ] && PS="-s" 418 | set_dist_client 419 | exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \ 420 | -noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \ 421 | -s erlang halt -output text \ 422 | -boot start_clean 423 | ;; 424 | started) 425 | set_dist_client 426 | wait_status 0 30 2 # wait 30x2s before timeout 427 | ;; 428 | stopped) 429 | set_dist_client 430 | wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout 431 | ;; 432 | post_waiter) 433 | post_waiter_waiting 434 | ;; 435 | *) 436 | set_dist_client 437 | run_erl "$(uid ctl)" -hidden -noinput -boot start_clean \ 438 | -s ejabberd_ctl -extra "$ERLANG_NODE" $NO_TIMEOUT "$@" 439 | result=$? 440 | case $result in 441 | 2|3) help;; 442 | *) :;; 443 | esac 444 | exit $result 445 | ;; 446 | esac 447 | -------------------------------------------------------------------------------- /ecs/bin/erl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | ROOTDIR=/home/ejabberd 5 | BINDIR=$ROOTDIR/bin 6 | EMU=beam 7 | PROGNAME=`echo $0 | sed 's/.*\\///'` 8 | export EMU 9 | export ROOTDIR 10 | export BINDIR 11 | export PROGNAME 12 | exec "$BINDIR/erlexec" ${1+"$@"} 13 | -------------------------------------------------------------------------------- /ecs/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | current=$(date +%y.%m) 4 | version=${1:-$current} 5 | 6 | docker build \ 7 | --build-arg VERSION=$version \ 8 | --build-arg VCS_REF=`git rev-parse --short HEAD` \ 9 | --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ 10 | -t ejabberd/ecs:$version . 11 | 12 | [ "$version" = "latest" ] || docker tag ejabberd/ecs:$version ejabberd/ecs:latest 13 | -------------------------------------------------------------------------------- /ecs/conf/dhparams.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEA6/sznqAfpkS3X0jBBmYgIm3XAq2mteWVGD3/CbQ2rfk8/38fEGN7 3 | j5G+WnulMkf9WvGtRnFQrsIsnHUyMy4ay1p7ERKCA+TLd+biOIFXOnABpvnVcPjQ 4 | LP/G5t7kJ/kM5G8eHDk1R7rvhA8Xecv7oX6QFqsdYRSM1tO9HR0l53tSPQ0swk6v 5 | PhWZmOSfjugfOKwHMuXwI112pyXI1XEqC/mq+CJNJw0Z3eLcOcJWuFIZuoOwXDdU 6 | GXK0kEypq+bMTVuq1B3WMxFon8PffQ/rmbH6Bk3SXrJz6koKCcBhm019/fuNSGQ5 7 | 6uVCmIbxWeYL6Yn8qRBVMlgC3DEGMzONWwIBAg== 8 | -----END DH PARAMETERS----- 9 | -------------------------------------------------------------------------------- /ecs/conf/ejabberd.yml: -------------------------------------------------------------------------------- 1 | ### 2 | ### ejabberd configuration file 3 | ### 4 | ### The parameters used in this configuration file are explained at 5 | ### 6 | ### https://docs.ejabberd.im/admin/configuration 7 | ### 8 | ### The configuration file is written in YAML. 9 | ### ******************************************************* 10 | ### ******* !!! WARNING !!! ******* 11 | ### ******* YAML IS INDENTATION SENSITIVE ******* 12 | ### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY ******* 13 | ### ******************************************************* 14 | ### Refer to http://en.wikipedia.org/wiki/YAML for the brief description. 15 | ### 16 | 17 | define_macro: 18 | HOST: localhost 19 | ADMIN: "admin@localhost" 20 | PORT_C2S: 5222 21 | PORT_C2S_TLS: 5223 22 | PORT_S2S: 5269 23 | PORT_HTTP_TLS: 5443 24 | PORT_HTTP: 5280 25 | PORT_BROWSER: 1880 26 | PORT_STUN: 5478 27 | PORT_MQTT: 1883 28 | PORT_PROXY65: 7777 29 | 30 | hosts: 31 | - HOST 32 | 33 | loglevel: info 34 | 35 | certfiles: 36 | - /home/ejabberd/conf/server.pem 37 | 38 | ca_file: "/home/ejabberd/conf/cacert.pem" 39 | 40 | ## When using let's encrypt to generate certificates 41 | ##certfiles: 42 | ## - /etc/letsencrypt/live/localhost/fullchain.pem 43 | ## - /etc/letsencrypt/live/localhost/privkey.pem 44 | ## 45 | ##ca_file: "/etc/letsencrypt/live/localhost/fullchain.pem" 46 | 47 | listen: 48 | - 49 | port: PORT_C2S 50 | ip: "::" 51 | module: ejabberd_c2s 52 | max_stanza_size: 262144 53 | shaper: c2s_shaper 54 | access: c2s 55 | starttls_required: true 56 | - 57 | port: PORT_C2S_TLS 58 | ip: "::" 59 | module: ejabberd_c2s 60 | max_stanza_size: 262144 61 | shaper: c2s_shaper 62 | access: c2s 63 | tls: true 64 | - 65 | port: PORT_S2S 66 | ip: "::" 67 | module: ejabberd_s2s_in 68 | max_stanza_size: 524288 69 | shaper: s2s_shaper 70 | - 71 | port: PORT_HTTP_TLS 72 | ip: "::" 73 | module: ejabberd_http 74 | tls: true 75 | request_handlers: 76 | /admin: ejabberd_web_admin 77 | /api: mod_http_api 78 | /bosh: mod_bosh 79 | /captcha: ejabberd_captcha 80 | /upload: mod_http_upload 81 | /ws: ejabberd_http_ws 82 | /oauth: ejabberd_oauth 83 | - 84 | port: PORT_HTTP 85 | ip: "::" 86 | module: ejabberd_http 87 | request_handlers: 88 | /admin: ejabberd_web_admin 89 | - 90 | port: PORT_BROWSER 91 | ip: "::" 92 | module: ejabberd_http 93 | request_handlers: 94 | /: ejabberd_web_admin 95 | - 96 | port: PORT_MQTT 97 | ip: "::" 98 | module: mod_mqtt 99 | backlog: 1000 100 | ## 101 | ## https://docs.ejabberd.im/admin/configuration/#stun-and-turn 102 | ## ejabberd_stun: Handles STUN Binding requests 103 | ## 104 | ##- 105 | ## port: 3478 106 | ## ip: "0.0.0.0" 107 | ## transport: udp 108 | ## module: ejabberd_stun 109 | ## use_turn: true 110 | ## turn_ip: "{{ IP }}" 111 | ## auth_type: user 112 | ## auth_realm: "example.com" 113 | ##- 114 | ## port: 3478 115 | ## ip: "0.0.0.0" 116 | ## module: ejabberd_stun 117 | ## use_turn: true 118 | ## turn_ip: "{{ IP }}" 119 | ## auth_type: user 120 | ## auth_realm: "example.com" 121 | ##- 122 | ## port: 5349 123 | ## ip: "0.0.0.0" 124 | ## module: ejabberd_stun 125 | ## certfile: "/home/ejabberd/conf/server.pem" 126 | ## tls: true 127 | ## use_turn: true 128 | ## turn_ip: "{{ IP }}" 129 | ## auth_type: user 130 | ## auth_realm: "example.com" 131 | ## 132 | ## https://docs.ejabberd.im/admin/configuration/#sip 133 | ## To handle SIP (VOIP) requests: 134 | ## 135 | ##- 136 | ## port: 5060 137 | ## ip: "0.0.0.0" 138 | ## transport: udp 139 | ## module: ejabberd_sip 140 | ##- 141 | ## port: 5060 142 | ## ip: "0.0.0.0" 143 | ## module: ejabberd_sip 144 | ##- 145 | ## port: 5061 146 | ## ip: "0.0.0.0" 147 | ## module: ejabberd_sip 148 | ## tls: true 149 | 150 | s2s_use_starttls: optional 151 | 152 | acl: 153 | local: 154 | user_regexp: "" 155 | loopback: 156 | ip: 157 | - 127.0.0.0/8 158 | - ::1/128 159 | admin: 160 | user: 161 | - ADMIN 162 | 163 | access_rules: 164 | local: 165 | allow: local 166 | c2s: 167 | deny: blocked 168 | allow: all 169 | announce: 170 | allow: admin 171 | configure: 172 | allow: admin 173 | muc_create: 174 | allow: local 175 | pubsub_createnode: 176 | allow: local 177 | trusted_network: 178 | allow: loopback 179 | 180 | api_permissions: 181 | "console commands": 182 | from: ejabberd_ctl 183 | who: all 184 | what: "*" 185 | "webadmin commands": 186 | from: ejabberd_web_admin 187 | who: admin 188 | what: "*" 189 | "admin access": 190 | who: 191 | access: 192 | allow: 193 | - acl: loopback 194 | - acl: admin 195 | oauth: 196 | scope: "ejabberd:admin" 197 | access: 198 | allow: 199 | - acl: loopback 200 | - acl: admin 201 | what: 202 | - "*" 203 | - "!stop" 204 | - "!start" 205 | "public commands": 206 | who: 207 | ip: 127.0.0.1/8 208 | what: 209 | - status 210 | - connected_users_number 211 | 212 | shaper: 213 | normal: 214 | rate: 3000 215 | burst_size: 20000 216 | fast: 100000 217 | 218 | shaper_rules: 219 | max_user_sessions: 10 220 | max_user_offline_messages: 221 | 5000: admin 222 | 100: all 223 | c2s_shaper: 224 | none: admin 225 | normal: all 226 | s2s_shaper: fast 227 | 228 | acme: 229 | contact: "mailto:example-admin@example.com" 230 | ca_url: "https://acme-staging-v02.api.letsencrypt.org/directory" 231 | 232 | modules: 233 | mod_adhoc: {} 234 | mod_admin_extra: {} 235 | mod_announce: 236 | access: announce 237 | mod_avatar: {} 238 | mod_blocking: {} 239 | mod_bosh: {} 240 | mod_caps: {} 241 | mod_carboncopy: {} 242 | mod_client_state: {} 243 | mod_configure: {} 244 | mod_disco: {} 245 | mod_fail2ban: {} 246 | mod_http_api: {} 247 | mod_http_upload: 248 | put_url: https://@HOST@:5443/upload 249 | custom_headers: 250 | "Access-Control-Allow-Origin": "https://@HOST@" 251 | "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS" 252 | "Access-Control-Allow-Headers": "Content-Type" 253 | mod_last: {} 254 | mod_mam: 255 | ## Mnesia is limited to 2GB, better to use an SQL backend 256 | ## For small servers SQLite is a good fit and is very easy 257 | ## to configure. Uncomment this when you have SQL configured: 258 | ## db_type: sql 259 | assume_mam_usage: true 260 | default: always 261 | mod_mqtt: {} 262 | mod_muc: 263 | access: 264 | - allow 265 | access_admin: 266 | - allow: admin 267 | access_create: muc_create 268 | access_persistent: muc_create 269 | access_mam: 270 | - allow 271 | default_room_options: 272 | allow_subscription: true # enable MucSub 273 | mam: true 274 | mod_muc_admin: {} 275 | mod_muc_occupantid: {} 276 | mod_offline: 277 | access_max_user_messages: max_user_offline_messages 278 | mod_ping: {} 279 | mod_privacy: {} 280 | mod_private: {} 281 | mod_proxy65: 282 | access: local 283 | max_connections: 5 284 | port: PORT_PROXY65 285 | mod_pubsub: 286 | access_createnode: pubsub_createnode 287 | plugins: 288 | - flat 289 | - pep 290 | force_node_config: 291 | ## Avoid buggy clients to make their bookmarks public 292 | storage:bookmarks: 293 | access_model: whitelist 294 | mod_push: {} 295 | mod_push_keepalive: {} 296 | mod_register: 297 | ## Only accept registration requests from the "trusted" 298 | ## network (see access_rules section above). 299 | ## Think twice before enabling registration from any 300 | ## address. See the Jabber SPAM Manifesto for details: 301 | ## https://github.com/ge0rg/jabber-spam-fighting-manifesto 302 | ip_access: trusted_network 303 | mod_roster: 304 | versioning: true 305 | mod_sip: {} 306 | mod_s2s_bidi: {} 307 | mod_s2s_dialback: {} 308 | mod_shared_roster: {} 309 | mod_stream_mgmt: 310 | resend_on_timeout: if_offline 311 | mod_vcard: {} 312 | mod_vcard_xupdate: {} 313 | mod_version: 314 | show_os: false 315 | 316 | ### Local Variables: 317 | ### mode: yaml 318 | ### End: 319 | ### vim: set filetype=yaml tabstop=8 320 | -------------------------------------------------------------------------------- /ecs/conf/ejabberdctl.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # In this file you can configure options that are passed by ejabberdctl 3 | # to the erlang runtime system when starting ejabberd 4 | # 5 | 6 | #' POLL: Kernel polling ([true|false]) 7 | # 8 | # The kernel polling option requires support in the kernel. 9 | # Additionally, you need to enable this feature while compiling Erlang. 10 | # 11 | # Default: true 12 | # 13 | #POLL=true 14 | 15 | #. 16 | #' ERL_MAX_PORTS: Maximum number of simultaneously open Erlang ports 17 | # 18 | # ejabberd consumes two or three ports for every connection, either 19 | # from a client or from another XMPP server. So take this into 20 | # account when setting this limit. 21 | # 22 | # Default: 65536 (or 8196 on Windows) 23 | # Maximum: 268435456 24 | # 25 | #ERL_MAX_PORTS=65536 26 | 27 | #. 28 | #' FIREWALL_WINDOW: Range of allowed ports to pass through a firewall 29 | # 30 | # If ejabberd is configured to run in cluster, and a firewall is blocking ports, 31 | # it's possible to make Erlang use a defined range of port (instead of dynamic 32 | # ports) for node communication. 33 | # 34 | # Default: not defined 35 | # Example: 4200-4210 36 | # 37 | #FIREWALL_WINDOW= 38 | 39 | #. 40 | #' INET_DIST_INTERFACE: IP address where this Erlang node listens other nodes 41 | # 42 | # This communication is used by ejabberdctl command line tool, 43 | # and in a cluster of several ejabberd nodes. 44 | # 45 | # Default: 0.0.0.0 46 | # 47 | #INET_DIST_INTERFACE=127.0.0.1 48 | 49 | #. 50 | #' ERL_DIST_PORT: Port number for Erlang distribution 51 | # 52 | # For Erlang distribution, clustering and ejabberdctl usage, the 53 | # Erlang VM listens in a random TCP port number, and the Erlang Port 54 | # Mapper Daemon (EPMD) is spawned and used to determine this port 55 | # number. 56 | # 57 | # ERL_DIST_PORT can define this port number. In that case, EPMD is 58 | # not spawned during ejabberd startup, and ERL_EPMD_ADDRESS is 59 | # ignored. ERL_DIST_PORT must be set to the same port number during 60 | # ejabberd startup and when calling ejabberdctl. This feature 61 | # requires at least Erlang/OTP 23.1. 62 | # 63 | # Default: not defined 64 | # 65 | #ERL_DIST_PORT=5210 66 | 67 | #. 68 | #' ERL_EPMD_ADDRESS: IP addresses where EPMD listens for connections 69 | # 70 | # This environment variable may be set to a comma-separated 71 | # list of IP addresses, in which case the EPMD daemon 72 | # will listen only on the specified address(es) and on the 73 | # loopback address (which is implicitly added to the list if it 74 | # has not been specified). The default behaviour is to listen on 75 | # all available IP addresses. 76 | # 77 | # Default: 0.0.0.0 78 | # 79 | #ERL_EPMD_ADDRESS=127.0.0.1 80 | 81 | #. 82 | #' ERL_PROCESSES: Maximum number of Erlang processes 83 | # 84 | # Erlang consumes a lot of lightweight processes. If there is a lot of activity 85 | # on ejabberd so that the maximum number of processes is reached, people will 86 | # experience greater latency times. As these processes are implemented in 87 | # Erlang, and therefore not related to the operating system processes, you do 88 | # not have to worry about allowing a huge number of them. 89 | # 90 | # Default: 262144 91 | # Maximum: 268435456 92 | # 93 | #ERL_PROCESSES=262144 94 | 95 | #. 96 | #' ERL_MAX_ETS_TABLES: Maximum number of ETS and Mnesia tables 97 | # 98 | # The number of concurrent ETS and Mnesia tables is limited. When the limit is 99 | # reached, errors will appear in the logs: 100 | # ** Too many db tables ** 101 | # You can safely increase this limit when starting ejabberd. It impacts memory 102 | # consumption but the difference will be quite small. 103 | # 104 | # Default: 2053 105 | # 106 | #ERL_MAX_ETS_TABLES=2053 107 | 108 | #. 109 | #' ERL_OPTIONS: Additional Erlang options 110 | # 111 | # The next variable allows to specify additional options passed to 112 | # all commands using erlang interpreter. This applies to starting 113 | # ejabberd server itself but also auxiliary commands like for example 114 | # starting debug shell. See erl(1) for list of commands that can be 115 | # used here. 116 | # 117 | # It might be useful to add "-pa /usr/local/lib/ejabberd/ebin" if you 118 | # want to add local modules in this path. 119 | # 120 | # Default: "" 121 | # 122 | #ERL_OPTIONS="" 123 | 124 | #. 125 | #' EJABBERD_OPTS: Additional Erlang options to start ejabberd 126 | # 127 | # The next variable allows to specify additional options passed to erlang while 128 | # starting ejabberd. Some useful options are -noshell, -detached, -heart. When 129 | # ejabberd is started from an init.d script options -noshell and -detached are 130 | # added implicitly. See erl(1) for more info. 131 | # 132 | # For example you can use value "-heart -env HEART_BEAT_TIMEOUT 120 -env ERL_CRASH_DUMP_SECONDS 60" 133 | # 134 | # Default: "" 135 | # 136 | #EJABBERD_OPTS="" 137 | 138 | #. 139 | #' ERLANG_NODE: Erlang node name 140 | # 141 | # The next variable allows to explicitly specify erlang node for ejabberd 142 | # It can be given in different formats: 143 | # ERLANG_NODE=ejabberd 144 | # Lets erlang add hostname to the node (ejabberd uses short name in this case) 145 | # ERLANG_NODE=ejabberd@hostname 146 | # Erlang uses node name as is (so make sure that hostname is a real 147 | # machine hostname or you'll not be able to control ejabberd) 148 | # ERLANG_NODE=ejabberd@hostname.domainname 149 | # The same as previous, but erlang will use long hostname 150 | # (see erl (1) manual for details) 151 | # 152 | # Default: ejabberd@localhost 153 | # 154 | #ERLANG_NODE=ejabberd@$(hostname -s) 155 | 156 | #. 157 | #' ERLANG_COOKIE: Erlang cookie for inter-node communication 158 | # 159 | # When using ejabberd in cluster, you need all nodes to share 160 | # the same erlang cookie. If not defined, a random value is used 161 | # at node first start, which prevent clustering to work. Setting 162 | # a defined cookie for all your nodes is needed to setup cluster. 163 | # 164 | # Default: "" 165 | # 166 | #ERLANG_COOKIE="" 167 | 168 | #. 169 | #. 170 | #' EJABBERD_PID_PATH: ejabberd PID file 171 | # 172 | # Indicate the full path to the ejabberd Process identifier (PID) file. 173 | # If this variable is defined, ejabberd writes the PID file when starts, 174 | # and deletes it when stops. 175 | # Remember to create the directory and grant write permission to ejabberd. 176 | # 177 | # Default: don't write PID file 178 | # 179 | #EJABBERD_PID_PATH=/var/run/ejabberd/ejabberd.pid 180 | 181 | #. 182 | #' EJABBERD_CONFIG_PATH: ejabberd configuration file 183 | # 184 | # Specify the full path to the ejabberd configuration file. If the file name has 185 | # yml or yaml extension, it is parsed as a YAML file; otherwise, Erlang syntax is 186 | # expected. 187 | # 188 | # Default: $ETC_DIR/ejabberd.yml 189 | # 190 | #EJABBERD_CONFIG_PATH=/etc/ejabberd/ejabberd.yml 191 | 192 | #. 193 | #' CONTRIB_MODULES_PATH: contributed ejabberd modules path 194 | # 195 | # Specify the full path to the contributed ejabberd modules. If the path is not 196 | # defined, ejabberd will use ~/.ejabberd-modules in home of user running ejabberd. 197 | # 198 | # Default: $HOME/.ejabberd-modules 199 | # 200 | #CONTRIB_MODULES_PATH=/opt/ejabberd-modules 201 | 202 | #. 203 | #' CONTRIB_MODULES_CONF_DIR: configuration directory for contributed modules 204 | # 205 | # Specify the full path to the configuration directory for contributed ejabberd 206 | # modules. In order to configure a module named mod_foo, a mod_foo.yml file can 207 | # be created in this directory. This file will then be used instead of the 208 | # default configuration file provided with the module. 209 | # 210 | # Default: $CONTRIB_MODULES_PATH/conf 211 | # 212 | #CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules 213 | 214 | #. 215 | #' 216 | # vim: foldmarker=#',#. foldmethod=marker: 217 | -------------------------------------------------------------------------------- /ecs/conf/inetrc: -------------------------------------------------------------------------------- 1 | {lookup,["file","native"]}. 2 | {host,{127,0,0,1}, ["localhost","@@HOSTNAME@@"]}. 3 | {file, resolv, "/etc/resolv.conf"}. 4 | -------------------------------------------------------------------------------- /ecs/conf/server.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDkzs+QWstSzyRN 3 | WaWCYbxyuKzoRfGpxDi54YOLoyISV4ulMVuYn3Uz6AJGH1d4oqh/JAaVOx1h/bdB 4 | nhAYy25c0P7dYtqdco3b1SMZIt3EYwHsgedTVNqZjG1+ExjqUiU8V8r7tGLFBjO/ 5 | O7H9z0zXbJ7IYhVdn99ijro8WHdEqNpnWHxVQF/KoVeTvFfcopD9QBhcu1uvwiMU 6 | G4mCOpYbysl/9NQCsNP4TV9pQ/6D6jQjIGTzuXO74cEhtibaLl7e1aPDIyqzicwS 7 | SgneKM/ypG8X9VgM81r3/nfe5us/vrIW0uXvH3qOu+/b76HULdaZ8OAItazzBoUO 8 | tl+/kakCN5J8uoKdP61hzPZWCLT84T79WQpWOa4dDiQPtuOMMlp0KZDDH+fW3WMG 9 | KmF8xiFigmPmb9SYyAVsZH9OsQeglRSS1dEV2vVzH3WpVTrZdPSM6sOhZel9fOXI 10 | kfrlZXlFvQHltvi0jUeeYM8z1e3iFAzJ6IXIKu2Ubbto6khFCZTx4FAJohOoWRJg 11 | ZcMmnGHlJNkRBYH5ImQupLhwSr2XEPPhidW5u87N+ZNk9np/ZykCcI1xiXFfgcnr 12 | CgmEWjXUV8nhgiXyl5EFAqyOlrsjc1LLL3ykzNZXHyQSFjaZe5HCDx2NjxRsdlKf 13 | gcLuifVvaaM5Vmb4GyHLr3R2HNTchwIDAQABAoICABSYVPCOa5zBjmfz+MTanUbK 14 | Pq4NlaoNQnngxaFtBqUWAjjVT4RWXgtVB9dd/Nab9YS0Lm+CSavHVZZvbs18iiuK 15 | mFY/DqR7ai9uaOFbVRDXRJYQP00t5xtJG5XsjCKTUEy1Lk0nuHg5jbDZ47SP0z/U 16 | xBoPUhMCT+4kILlL0Th55mbE/TQDPlwT17kxi8sNSvWwrkCykJcqZ1PpAqCZO2e3 17 | AholZGv1lK7V8A+ekis3iofa45tYhwVTVbn+FlMvN1ThcAMhiDdu4NKInYjErasO 18 | h/1lFQ7dXMPTwOBscqJjPM53H0E92R895WIrmKprkdR7bP77s1yQqqtfWRD6QHcK 19 | CK3dZ4GRYnL/2nsoFEi2UbKkBy+gy8z7fclv5NUfZG1mjPFMgsVC2m+6xNS1Owld 20 | YFx8pxrudxEoKOzDYd5SBDfpGkda3+1IqsPBme+Mqu4Q1fluQLBBP/oIt+RIqHMu 21 | J3ZZYPJVKUBJHKKGqnYeIsh2Ju/8IrT9dhWWRzfzhh0+hMHJjW7sXrbVm8OYpge0 22 | WBGkDf5zoBL2Kpbf6NIk68JTh+jpDYOvZbYjnPHji8zpDaxFaOgpX/WLaOVxMm10 23 | pw1kAgRhDeV87gjVdW+4NOhWfRjW/m71YAZ3NNTYk7x0KlwNNI//MvwdvHX969Td 24 | T6kUmW9Kg2ezolSs/aphAoIBAQD5Ya6lcuQuBLTBQIS7+eMM1N0j6QhBvd5Tzyr+ 25 | 6oXND3vA08skDd2Zi7m8JiPUn7ywcu+yo+H+MJAqKqPMARWSJQQ/CYQ1N+i/uZN7 26 | 1xqnTWubNtxJtikbRnCWCmVNzCSl+H9Z41eWygrO+V4c6HT9Zx1X6VOSArPlJkWw 27 | fCHzuJ3N5W8bR7RmOuVHZ/3/ZD1APkkOnqBmUZREBfiQNbGmYK3NG1Xa49MRGM3f 28 | 7YRTx3A3sucj9gKV/N1YyaLUcTAy0OUtqqcSBsUTfBPU/ztY0yg3+Xdn5WYRM1ZL 29 | Pim8OMtEP3ZdyKAb07RQr3OM04gximWesxiG74rYVVMyk0u3AoIBAQDq4VliNJya 30 | 7Gb9UyzjCiLfovpVbNSheP/KDSk2mBMwJpzMczMzhuvfIReFQFxefORALpgAmpPq 31 | bD79cOEKfknrseSLfPMGKB38RCkaBXrnaPQZ3aaXktMlrk2rOVIcawrYK3He6j0l 32 | 5fh+6uXws0jeifXzzMAmDvpkFRIGVjeJYZFdXQHMZW2ZdZFpJZj+eiWkTMDtv0L3 33 | Pl2GQVRWma/J4SH5pcHg5kLdTv8CoLRnXkDQt/BgT1Vblj8P92oArLN1zKzd/Vbu 34 | l7kFICwkn91FC0PdzWpoJAWtKlQbX19TWZ0YQLkVPB+DSjiJn+zu5+P1STKoy4eS 35 | V+mnVwS9dJWxAoIBAQDRI0NkywpjMV0pKGNohXMNQsLGJ9rdz05ReM61A5b8VrzR 36 | BI07CknKSCyWhmHMIb4LOAifBuMy2iU8x4+gOVSOwG5kMyXlv6J4jzgJRma64amZ 37 | fJOXWaX1ksg+fC9i5A3kBpc+mfLNqVkRJH3xvlzGWqB4JlwIei3Fwaf2DtQmYbAt 38 | iPj5ptO6XDAGB0cy1Cyt4M5B7XPU+xtdRKikv/Lg9fkrpn4E2MUcdHHLFpS/8eTB 39 | QU6okNqwUGSM3mSoxtfF9fwMpS4BZx4Fbivvl7B8mHEFKDgkMHS9fhEjftlfWT3W 40 | WWZ51hO34n44oDtGYeu4qDj6s3WhS+hj7oKcSnzXAoIBAQChywkfNM6LiTyIU7sf 41 | yeOr2UBHh+gQMqFANUCmcqsFCBQKYXBrlgz0bn8dMvBtxeoUrAPYpqItYNMjEZZy 42 | +/s/eBLOYwukug2tr+YAHrZCoXFEQAJ5dpIr6p1lzN5a5QFbVtHhk8j7SiaahoRO 43 | AbG4WaAqiGfzz217c2gvJUSsRaE0htSuT0/n3ayEmXmCEfHL83MSUiV22mbiDC5k 44 | WQlWLtaQeTXMDdERUVEoJjse2TYckBfsv7k0lZJrFSrXvB8CjjKl19UCFVFFzpuZ 45 | vuVUoiXlq5IYmneuiPHWySOI7rnf8vWLQxcSARZg9uDm0KWeWQWkcE666APzWWXS 46 | e3SBAoIBAQCtRv8ruFBDuv99l4WKn0ZEODdY+Uxbz1rREzVJx7hEzkif5viJl9Hi 47 | AZnqJPd8I0MMEvplDhe2X6TnF1jjxx+z4U72boY8IPY0rw+kYzBqMwywkCzb+Jn2 48 | qmBtX1XXRsSO1U7pW/ej6RyLQqtMt+lKd5vVxu7fOo3OYmcEJxD4AylUNU7cCFwP 49 | ZtFxe+uddzWYM3O55OrjHEj1LIcJb5n/46Owd2OUXMRNxQ3lv0fBKDWN/1bXiNEh 50 | efb02fSq5nIpoxmHMG/s+PEHB1uDqUjNkNZK42DyrMkwQwnN9M8ZetRWhqu5QgxX 51 | LQheTRhu+UYYcbxy+AHQ8pqBBdnRsxLZ 52 | -----END PRIVATE KEY----- 53 | -----BEGIN CERTIFICATE----- 54 | MIIFnDCCA4SgAwIBAgIJANCgN0JN5H4RMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV 55 | BAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwGA1UEBwwFUGFyaXMxEzARBgNVBAoM 56 | ClByb2Nlc3NPbmUxCzAJBgNVBAsMAklUMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcN 57 | MTcxMjI5MTExMzA3WhcNNDUwNTE2MTExMzA3WjBjMQswCQYDVQQGEwJGUjEOMAwG 58 | A1UECAwFUGFyaXMxDjAMBgNVBAcMBVBhcmlzMRMwEQYDVQQKDApQcm9jZXNzT25l 59 | MQswCQYDVQQLDAJJVDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0B 60 | AQEFAAOCAg8AMIICCgKCAgEA5M7PkFrLUs8kTVmlgmG8cris6EXxqcQ4ueGDi6Mi 61 | EleLpTFbmJ91M+gCRh9XeKKofyQGlTsdYf23QZ4QGMtuXND+3WLanXKN29UjGSLd 62 | xGMB7IHnU1TamYxtfhMY6lIlPFfK+7RixQYzvzux/c9M12yeyGIVXZ/fYo66PFh3 63 | RKjaZ1h8VUBfyqFXk7xX3KKQ/UAYXLtbr8IjFBuJgjqWG8rJf/TUArDT+E1faUP+ 64 | g+o0IyBk87lzu+HBIbYm2i5e3tWjwyMqs4nMEkoJ3ijP8qRvF/VYDPNa9/533ubr 65 | P76yFtLl7x96jrvv2++h1C3WmfDgCLWs8waFDrZfv5GpAjeSfLqCnT+tYcz2Vgi0 66 | /OE+/VkKVjmuHQ4kD7bjjDJadCmQwx/n1t1jBiphfMYhYoJj5m/UmMgFbGR/TrEH 67 | oJUUktXRFdr1cx91qVU62XT0jOrDoWXpfXzlyJH65WV5Rb0B5bb4tI1HnmDPM9Xt 68 | 4hQMyeiFyCrtlG27aOpIRQmU8eBQCaITqFkSYGXDJpxh5STZEQWB+SJkLqS4cEq9 69 | lxDz4YnVubvOzfmTZPZ6f2cpAnCNcYlxX4HJ6woJhFo11FfJ4YIl8peRBQKsjpa7 70 | I3NSyy98pMzWVx8kEhY2mXuRwg8djY8UbHZSn4HC7on1b2mjOVZm+Bshy690dhzU 71 | 3IcCAwEAAaNTMFEwHQYDVR0OBBYEFCTwPSToCR8fTNGz5o2Czlc/BlfqMB8GA1Ud 72 | IwQYMBaAFCTwPSToCR8fTNGz5o2Czlc/BlfqMA8GA1UdEwEB/wQFMAMBAf8wDQYJ 73 | KoZIhvcNAQELBQADggIBADnvcqMt+ESTM12BuX6E+4mA0iR//Lxp8FzQkZEb7YPR 74 | eIor6iPVDX+oRo/uVhEPvjH+SXGb+9FOOexIoxoB4C+1UpBRHBS2PROX0BNmIDb7 75 | abRY6iCkIlyrVkVAtswNZdJHLJX5OMPfV52p6HELd4oYlI+AnQDXkrHA8DD7Y59r 76 | o5MonTJV26L2mq2+ceciqviZzQLA0QJxTOPLaz/pq1a2bauP0Q1EjhB0nYJ9hZxp 77 | CuAWXrVA7veElXg7EKyrQrOt6kcnNqpBj7Pk3R1Zq2xNMlfMMqQlJFt7uKy49EwI 78 | qGgmVj1ScL/Savp967LjRaTz0CnJhSLUlCmLq/4JGPWI/AKEi0Hg14EgRiGbha2B 79 | E+3sQxWmCWDeIMLM6m3001VMyT1JgEoJkbhGruDayxPDQuG4nrpK8lNMrnS1Ji0j 80 | 6VQ6OL66RFlpK+/LRYc8cXsh6+hDUaXLQTPs9v880SpoerbjW5Rh9Z7Dh+fX2SJj 81 | 8x6IbNbppn7SGD4iOaHd6+gq0j6iB1zOcTaU5OnZGb4qWNyqm0m94UWFMMr5zlmn 82 | /MwQAnvgLhfcQ1T5iq3AAIrC1D0jn0b5D2CdCFNW1DmbDZiy8db+Pz5g36G9OceQ 83 | oFdxG1n7Nre84DwOlohVYtFkeYy3D6hd+/sbyNa5YqswuKLdm6fWrp/e3es1auXy 84 | -----END CERTIFICATE----- 85 | -------------------------------------------------------------------------------- /ecs/config.exs: -------------------------------------------------------------------------------- 1 | import Config 2 | 3 | # This is standard path in the context of ejabberd release 4 | config :ejabberd, 5 | file: "config/ejabberd.yml", 6 | log_path: 'log/ejabberd.log' 7 | 8 | # Customize Mnesia directory: 9 | config :mnesia, 10 | dir: 'database/' 11 | -------------------------------------------------------------------------------- /ecs/ejabberd-docker-install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: 4 | :: ejabberd Docker installer for Windows 5 | :: ------------------------------------- 6 | :: v0.3 7 | :: 8 | :: This batch script downloads an ejabberd docker image 9 | :: and setups a docker container to run ejabberd. 10 | 11 | :: 12 | :: 1. Download and install Docker: 13 | :: 14 | :: If you use Windows 10, download Docker Desktop from: 15 | :: https://www.docker.com/ 16 | :: 17 | :: If you use Windows 7 or 8, download Docker Toolbox from: 18 | :: https://github.com/docker/toolbox/releases 19 | :: After installation, run Docker Quickstart Installer 20 | :: 21 | 22 | :: 23 | :: 2. Edit those options: 24 | 25 | :: Directory where your ejabberd deployment files will be installed 26 | :: (configuration, database, logs, ...) 27 | :: 28 | :: In Windows 10 you can configure the path: 29 | 30 | set INSTALL_DIR_WINDOWS10=C:\ejabberd 31 | 32 | :: In older Windows, not configurable, it will be installed in: 33 | :: C:\Users\%USERNAME%\ejabberd 34 | 35 | :: Please enter the desired ejabberd domain name. 36 | :: The domain is the visible attribute that is added to the username 37 | :: to form the Jabber Identifier (for example: user@example.net). 38 | :: This computer must be known on the network with this address name. 39 | :: You can later add more in conf/ejabberd.yml 40 | 41 | set HOST=localhost 42 | 43 | :: Please enter the administrator username for the current 44 | :: ejabberd installation. A Jabber account with this username 45 | :: will be created and granted administrative privileges. 46 | :: Don't use blankspaces in the username. 47 | 48 | set USER=admin 49 | 50 | :: Please provide a password for that new administrator account 51 | 52 | set PASSWORD= 53 | 54 | :: By default this downloads 'latest' ejabberd version, 55 | :: but you can set a specific version, for example 21.01 56 | 57 | set VERSION=latest 58 | 59 | :: This tells docker what ports ejabberd will use. 60 | :: You can later configure them in conf/ejabberd.yml 61 | 62 | set PORTS=5180 5222 5269 5443 63 | 64 | :: 65 | :: 3. Now save this script and run it. 66 | :: 67 | 68 | :: 69 | :: 4. When installation is completed: 70 | :: 71 | :: If using Windows 10, open Docker Desktop and you can: 72 | :: 73 | :: - (>) START the ejabberd container 74 | :: - Enter WebAdmin: click the ([->]) OPEN IN BROWSER button 75 | :: - To try ejabberdctl, click the (>_) CLI button, then: bin/ejabberdctl 76 | :: - ([]) STOP the ejabberd container 77 | :: 78 | :: If using an old Windows, open Kitematic and you can: 79 | :: 80 | :: - START the ejabberd container 81 | :: - Open your configuration, logs, ... in Settings > Volumes 82 | :: - Enter WebAdmin in Settings > Hostname/Ports > click on the 5180 port 83 | :: - Try ejabberdctl in EXEC, then: bin/ejabberdctl 84 | :: - STOP the ejabberd container 85 | :: 86 | :: You can delete the container and create it again running this script, 87 | :: the configuration and database are maintained. 88 | :: 89 | 90 | ::=============================================================== 91 | :: Check Windows version 92 | :: 93 | ::=============================================================== 94 | 95 | set INSTALL_DIR_DOCKER=c/Users/%USERNAME%/ejabberd 96 | 97 | for /f "tokens=4-5 delims=. " %%i in ('ver') do set WVERSION=%%i.%%j 98 | if "%wversion%" == "10.0" ( 99 | echo === Preparing paths to install in Windows 10... 100 | set INSTALL_DIR=%INSTALL_DIR_WINDOWS10% 101 | set VC=-v %INSTALL_DIR_WINDOWS10%\conf:/home/ejabberd/conf 102 | set VD=-v %INSTALL_DIR_WINDOWS10%\database:/home/ejabberd/database 103 | set VL=-v %INSTALL_DIR_WINDOWS10%\logs:/home/ejabberd/logs 104 | set VM=-v %INSTALL_DIR_WINDOWS10%\ejabberd-modules:/home/ejabberd/.ejabberd-modules 105 | set DOCKERDOWNLOAD="First download and install Docker Desktop from https://www.docker.com/" 106 | ) else ( 107 | echo === Preparing paths to install in Windows older than 10... 108 | set INSTALL_DIR=C:\Users\%USERNAME%\ejabberd 109 | set VC=-v "/%INSTALL_DIR_DOCKER%/conf:/home/ejabberd/conf" 110 | set VD=-v "/%INSTALL_DIR_DOCKER%/database:/home/ejabberd/database" 111 | set VL=-v "/%INSTALL_DIR_DOCKER%/logs:/home/ejabberd/logs" 112 | set VM=-v "/%INSTALL_DIR_DOCKER%/ejabberd-modules:/home/ejabberd/.ejabberd-modules" 113 | set DOCKERDOWNLOAD="First download and install Docker Toolbox from https://github.com/docker/toolbox/releases" 114 | ) 115 | set VOLUMES=%VC% %VD% %VL% %VM% 116 | 117 | ::=============================================================== 118 | :: Check docker is installed 119 | :: 120 | ::=============================================================== 121 | 122 | docker version >NUL 123 | if %ERRORLEVEL% NEQ 0 ( 124 | echo. 125 | echo === ERROR: It seems docker is not installed!!! 126 | echo. 127 | echo %DOCKERDOWNLOAD% 128 | echo === Then try to run this script again. 129 | echo. 130 | pause 131 | exit 1 132 | ) 133 | 134 | ::=============================================================== 135 | :: Check install options are correctly set 136 | :: 137 | ::=============================================================== 138 | 139 | if [%PASSWORD%]==[] ( 140 | echo. 141 | echo === ERROR: PASSWORD not set!!! 142 | echo. 143 | echo === Please edit this script and set the PASSWORD. 144 | echo === Then try to run this script again. 145 | echo. 146 | pause 147 | exit 1 148 | ) 149 | 150 | ::=============================================================== 151 | :: Download Docker image 152 | :: 153 | ::=============================================================== 154 | 155 | set IMAGE=ejabberd/ecs:%VERSION% 156 | 157 | echo. 158 | echo === Checking if the '%IMAGE%' docker image was already downloaded... 159 | docker image history %IMAGE% >NUL 160 | if %ERRORLEVEL% NEQ 0 ( 161 | echo === The '%IMAGE%' docker image was not downloaded yet. 162 | echo. 163 | echo === Downloading the '%IMAGE%' docker image, please wait... 164 | docker pull %IMAGE% 165 | ) else ( 166 | echo === The '%IMAGE%' docker image was already downloaded. 167 | ) 168 | 169 | ::=============================================================== 170 | :: Create preliminary container 171 | :: 172 | ::=============================================================== 173 | 174 | echo. 175 | echo === Checking if the 'ejabberd' docker container already exists... 176 | docker container logs ejabberd 177 | if %ERRORLEVEL% EQU 0 ( 178 | echo. 179 | echo === The 'ejabberd' docker container already exists. 180 | echo === Nothing to do, so installation finishes now. 181 | echo === You can go to Docker Desktop and start the 'ejabberd' container. 182 | echo. 183 | pause 184 | exit 1 185 | ) else ( 186 | echo === The 'ejabberd' docker container doesn't yet exist, 187 | echo === so let's continue the installation process. 188 | ) 189 | 190 | echo. 191 | if exist %INSTALL_DIR% ( 192 | echo === The INSTALL_DIR %INSTALL_DIR% already exists. 193 | echo === No need to create the preliminary 'ejabberd-pre' image. 194 | ) else ( 195 | echo === The INSTALL_DIR %INSTALL_DIR% doesn't exist. 196 | echo === Let's create the preliminary 'ejabberd-pre' image. 197 | CALL :create-ejabberd-pre 198 | ) 199 | 200 | ::=============================================================== 201 | :: Create final container 202 | :: 203 | ::=============================================================== 204 | 205 | echo. 206 | echo === Creating the final 'ejabberd' docker container using %IMAGE% image... 207 | 208 | setlocal EnableDelayedExpansion 209 | set PS= 210 | for %%a in (%PORTS%) do ( 211 | set PS=!PS! -p %%a:%%a 212 | ) 213 | 214 | docker create --name ejabberd --hostname localhost %PS% %VOLUMES% %IMAGE% 215 | 216 | echo. 217 | echo === Installation completed. 218 | echo. 219 | pause 220 | 221 | EXIT /B %ERRORLEVEL% 222 | 223 | ::=============================================================== 224 | :: Function to create preliminary container 225 | :: 226 | ::=============================================================== 227 | 228 | :create-ejabberd-pre 229 | 230 | echo. 231 | echo === Creating a preliminary 'ejabberd-pre' docker image using %IMAGE% image... 232 | docker create --name ejabberd-pre --hostname localhost %IMAGE% 233 | 234 | echo. 235 | echo === Now 'ejabberd-pre' will be started. 236 | docker container start ejabberd-pre 237 | 238 | echo. 239 | echo === Waiting ejabberd to be running... 240 | set /A timeout = 10 241 | set status=4 242 | goto :while 243 | 244 | :statusstart 245 | docker exec -it ejabberd-pre bin/ejabberdctl status 246 | goto :statusend 247 | 248 | :while 249 | if %status% GTR 0 ( 250 | echo. 251 | timeout /t 1 /nobreak >NUL 252 | set /A timeout = timeout - 1 253 | if %timeout% EQU 0 ( 254 | set status=-1 255 | ) else ( 256 | goto :statusstart 257 | :statusend 258 | set status=%ERRORLEVEL% 259 | ) 260 | goto :while 261 | ) 262 | 263 | echo. 264 | echo === Setting a few options... 265 | docker exec -it ejabberd-pre sed -i "s!- localhost!- %HOST%!g" conf/ejabberd.yml 266 | docker exec -it ejabberd-pre sed -i "s!admin@localhost!%USER%@%HOST%!g" conf/ejabberd.yml 267 | docker exec -it ejabberd-pre sed -i "s!5280!5180!g" conf/ejabberd.yml 268 | docker exec -it ejabberd-pre sed -i "s!\"/admin\"!/!g" conf/ejabberd.yml 269 | docker exec -it ejabberd-pre bin/ejabberdctl reload_config 270 | 271 | echo. 272 | echo === Registering the administrator account... 273 | docker exec -it ejabberd-pre bin/ejabberdctl register %USER% %HOST% %PASSWORD% 274 | docker exec -it ejabberd-pre bin/ejabberdctl stop 275 | 276 | echo. 277 | echo === Copying conf, database, logs... 278 | mkdir %INSTALL_DIR% 279 | mkdir %INSTALL_DIR%\conf 280 | mkdir %INSTALL_DIR%\database 281 | mkdir %INSTALL_DIR%\logs 282 | mkdir %INSTALL_DIR%\ejabberd-modules 283 | docker cp ejabberd-pre:/home/ejabberd/conf/ %INSTALL_DIR% 284 | docker cp ejabberd-pre:/home/ejabberd/database/ %INSTALL_DIR% 285 | docker cp ejabberd-pre:/home/ejabberd/logs/ %INSTALL_DIR% 286 | 287 | echo. 288 | echo === Deleting the preliminary 'ejabberd-pre' docker image... 289 | docker stop ejabberd-pre 290 | docker rm ejabberd-pre 291 | 292 | EXIT /B 0 293 | -------------------------------------------------------------------------------- /ecs/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # See documentation for details: 4 | # https://docs.docker.com/docker-hub/builds/advanced/ 5 | 6 | # Use $VERSION build environment variable or the Docker repository tag being built 7 | version=${VERSION:-${DOCKER_TAG}} 8 | 9 | docker build \ 10 | --build-arg VERSION=$version \ 11 | --build-arg VCS_REF=`git rev-parse --short HEAD` \ 12 | --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ 13 | -f $DOCKERFILE_PATH \ 14 | -t $IMAGE_NAME . 15 | -------------------------------------------------------------------------------- /ecs/rel/config.exs: -------------------------------------------------------------------------------- 1 | use Mix.Releases.Config, 2 | # This sets the default release built by `mix release` 3 | default_release: :default, 4 | # This sets the default environment used by `mix release` 5 | default_environment: :dev 6 | 7 | # For a full list of config options for both releases 8 | # and environments, visit https://hexdocs.pm/distillery/configuration.html 9 | 10 | 11 | # You may define one or more environments in this file, 12 | # an environment's settings will override those of a release 13 | # when building in that environment, this combination of release 14 | # and environment configuration is called a profile 15 | 16 | environment :dev do 17 | set dev_mode: true 18 | set include_erts: false 19 | set config: "rel/dev.exs" 20 | set cookie: :"!Vcuwp?y@d{7=`5Ha*2*PLw:i8;i:9B|tq75|K]kt?T]_nap/or,7xBylYJ!N;m{" 21 | end 22 | 23 | environment :prod do 24 | set include_erts: true 25 | set include_src: false 26 | set config: "rel/prod.exs" 27 | set cookie: :"HmewW_sUao={>LXTD8,g;xBu`.i]tq7Dz.m2?ZqO :ejabberd_auth.try_register("test", "localhost", "passw0rd") 50 | {:atomic, :ok} 51 | ``` 52 | 53 | You can then connect with user test@localhost (password: passw0rd) on server on localhost port 5222 and use those parameters to connect with an XMPP client. 54 | 55 | ## Get into the container 56 | 57 | If you want to run Erlang command line, you can do so by opening a shell inside the container: 58 | 59 | ```bash 60 | docker run -it -v $(pwd):$(pwd) -w $(pwd) --entrypoint="/bin/sh" ejabberd/mix 61 | ``` 62 | 63 | ## Getting Elixir version 64 | 65 | ```bash 66 | docker run -it --rm -v $(pwd):$(pwd) -w $(pwd) ejabberd/mix --version 67 | Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false] 68 | 69 | Mix 1.3.4 70 | ``` 71 | 72 | ## Build the image 73 | 74 | Building the image is not needed if you simply want to use it. You can simply use the one from [ejabberd Docker Hub](https://hub.docker.com/u/ejabberd/dashboard/). 75 | 76 | ```bash 77 | docker build -t ejabberd/mix . 78 | ``` 79 | 80 | ## Troubleshooting 81 | 82 | ### Clock resync 83 | 84 | If you have warning about file timestamp being out of sync (Like 'Clock skew detected'), you may want to force resync your clock before running the build. Docker on MacOS does not force clock resync of Docker after the laptop went to sleep. 85 | 86 | You can force clock resync as follow: 87 | 88 | ```bash 89 | docker run -it --rm --privileged --entrypoint="/sbin/hwclock" ejabberd/mix -s 90 | ``` 91 | 92 | You can check if the clock of your laptop is in sync with the one inside Docker with the following command: 93 | 94 | ```bash 95 | docker run --rm --entrypoint="/bin/sh" ejabberd/mix -c date -u && date -u 96 | ``` 97 | 98 | --------------------------------------------------------------------------------