Check ejabberd XMPP server useful configuration steps

ProcessOne
· 5 min read
Send by email

In this article I will share some configuration steps that I made while I was preparing my previous ejabberd XMPP server tutorials. I assume the starting ejabberd configuration from my article on setting up your ejabberd real time IM server and configuring ejabberd video & voice calling, as well as the one on how to get 100% in XMPP server compliance test.

ejabberd XMPP server S2S subdomains

It’s a good practice to configure extra subdomains for your ejabberd XMPP server. “A” records should pointing to the same IP address as your main domain. These subdomains are:

  • conference
  • proxy
  • pubsub
  • upload

Make sure all these subdomains use the SSL certificate supplied to ejabberd XMPP server. If you can, simplify things and use a wildcard certificate and a wildcard subdomain. If you don’t configure these subdomains, you will find a warning about them in the ejabberd XMPP server logs during each startup.

Group chat archiving on ejabberd XMPP server

Using mod_mam you can set your group chats to sync previous messages when a user joins them. It’s very useful in an office environment where not everyone is able to be one the group chat at all times. With mod_mam enabled, they won’t miss any discussions.

You need to change settings of mod_mam and mod_muc. Existing group chats won’t have archiving enabled unless you switch that on in their configuration, one by one. You can do it using a client like Gajim, or using ejabberd XMPP server command-line interface. As a last resort, you can destroy and re-create rooms again after you apply the settings below:

  mod_mam:
    assume_mam_usage: true
    default: always
  ...
  mod_muc:
    default_room_options:
      allow_subscription: true
      persistent: true
      mam: true

Comparing ejabberd XMPP server configuration files

Once you get used to the ejabberd.yml syntax, the best way to debug and fix your problems is to compare config files with others. Here’s my full ejabberd XMPP server configuration file that follows all my previous tutorials: basic setup, HTTP file upload, STUN/TURN video & voice calling, MUC archiving and 100% compliance with the XMPP Test.

Don’t copy-paste this configuration! It is based on the default config from ejabberd XMPP server version 20.04. It may not “just work” in older or newer ejabberd XMPP server versions. This config contains placeholders like “example.com”, “admin@example.com” and “0.0.0.0” that should be changed to your actual domain, email and server IP address.

To learn from this config file, compare it with yours and adjust accordingly. Remember to also refer to the latest official “ejabberd.yml” example, but note it could contain new parameters for features in-development, not yet supported by your ejabberd XMPP server.

###
###'           ejabberd configuration file
###
### The parameters used in this configuration file are explained at
###
###       https://docs.ejabberd.im/admin/configuration
###
### The configuration file is written in YAML.
### *******************************************************
### *******           !!! WARNING !!!               *******
### *******     YAML IS INDENTATION SENSITIVE       *******
### ******* MAKE SURE YOU INDENT SECTIONS CORRECTLY *******
### *******************************************************
### Refer to http://en.wikipedia.org/wiki/YAML for the brief description.
###

hosts:
  - "example.com"

loglevel: 3
log_rotate_size: 10485760
log_rotate_count: 1

certfiles:
  - "/opt/ejabberd/conf/fullchain.pem"
  - "/opt/ejabberd/conf/privkey.pem"

listen:
  -
    port: 5222
    ip: 0.0.0.0
    module: ejabberd_c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    starttls_required: true
  -
    port: 5223
    ip: 0.0.0.0
    tls: true
    module: ejabberd_c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    starttls_required: true
  -
    port: 5269
    ip: 0.0.0.0
    module: ejabberd_s2s_in
    max_stanza_size: 524288
  -
    port: 5270
    ip: 0.0.0.0
    tls: true
    module: ejabberd_s2s_in
    max_stanza_size: 524288
  -
    port: 5443
    ip: 0.0.0.0
    module: ejabberd_http
    tls: true
    request_handlers:
      "/admin": ejabberd_web_admin
      "/api": mod_http_api
      "/bosh": mod_bosh
      "/captcha": ejabberd_captcha
      "/upload": mod_http_upload
      "/ws": ejabberd_http_ws
  -
    port: 5280
    ip: 0.0.0.0
    module: ejabberd_http
    request_handlers:
      "/admin": ejabberd_web_admin
      "/.well-known/acme-challenge": ejabberd_acme
  -
    port: 3478
    transport: udp
    module: ejabberd_stun
    use_turn: true
    turn_min_port: 49152
    turn_max_port: 65535
    turn_ip: 0.0.0.0
  -
    port: 5349
    transport: tcp
    module: ejabberd_stun
    use_turn: true
    tls: true
    turn_min_port: 49152
    turn_max_port: 65535
    ip: 0.0.0.0
    turn_ip: 0.0.0.0
  -
    port: 1883
    ip: 0.0.0.0
    module: mod_mqtt
    backlog: 1000

s2s_use_starttls: optional

acl:
  local:
    user_regexp: ""
  loopback:
    ip:
      - 127.0.0.0/8
      - ::1/128
      - ::FFFF:127.0.0.1/128
  admin:
    user:
      - "admin@example.com"

access_rules:
  local:
    allow: local
  c2s:
    deny: blocked
    allow: all
  announce:
    allow: admin
  configure:
    allow: admin
  muc_create:
    allow: local
  pubsub_createnode:
    allow: local
  trusted_network:
    allow: loopback

api_permissions:
  "console commands":
    from:
      - ejabberd_ctl
    who: all
    what: "*"
  "admin access":
    who:
      access:
        allow:
          acl: loopback
          acl: admin
      oauth:
        scope: "ejabberd:admin"
        access:
          allow:
            acl: loopback
            acl: admin
    what:
      - "*"
      - "!stop"
      - "!start"
  "public commands":
    who:
      ip: 127.0.0.1/8
    what:
      - status
      - connected_users_number

shaper:
  normal:
    rate: 3000
    burst_size: 20000
  fast: 100000

shaper_rules:
  max_user_sessions: 10
  max_user_offline_messages:
    5000: admin
    100: all
  c2s_shaper:
    none: admin
    normal: all
  s2s_shaper: fast

max_fsm_queue: 10000

acme:
   contact: "mailto:admin@example.com"
   ca_url: "https://acme-v02.api.letsencrypt.org"

modules:
  mod_adhoc: {}
  mod_admin_extra: {}
  mod_announce:
    access: announce
  mod_avatar: {}
  mod_blocking: {}
  mod_bosh: {}
  mod_caps: {}
  mod_carboncopy: {}
  mod_client_state: {}
  mod_configure: {}
  mod_disco:
    server_info:
        -
          modules: all
          name: "abuse-addresses"
          urls: ["mailto:abuse@example.com"]
        -
          modules:
            - mod_disco
            - mod_vcard
          name: admin-addresses
          urls:
            - https://example.com
            - mailto:admin@example.com
            - xmpp:admin@example.com
  mod_fail2ban: {}
  mod_http_api: {}
  mod_http_upload:
    put_url: https://@HOST@:5443/upload
    docroot: /var/www/upload
    custom_headers:
      "Access-Control-Allow-Origin": "https://@HOST@"
      "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS"
      "Access-Control-Allow-Headers": "Content-Type"
  mod_last: {}
  mod_mam:
    ## Mnesia is limited to 2GB, better to use an SQL backend
    ## For small servers SQLite is a good fit and is very easy
    ## to configure. Uncomment this when you have SQL configured:
    ## db_type: sql
    assume_mam_usage: true
    default: always
  mod_mqtt: {}
  mod_muc:
    access:
      - allow
    access_admin:
      - allow: admin
    access_create: muc_create
    access_persistent: muc_create
    access_mam:
      - allow
    default_room_options:
      allow_subscription: true  # enable MucSub
      persistent: true
      mam: true
  mod_muc_admin: {}
  mod_offline:
    access_max_user_messages: max_user_offline_messages
  mod_ping: {}
  mod_privacy: {}
  mod_private: {}
  mod_proxy65:
    access: local
    max_connections: 5
  mod_pubsub:
    access_createnode: pubsub_createnode
    plugins:
      - flat
      - pep
    force_node_config:
      ## Avoid buggy clients to make their bookmarks public
      storage:bookmarks:
        access_model: whitelist
  mod_push: {}
  mod_push_keepalive: {}
  mod_register:
    ## Only accept registration requests from the "trusted"
    ## network (see access_rules section above).
    ## Think twice before enabling registration from any
    ## address. See the Jabber SPAM Manifesto for details:
    ## https://github.com/ge0rg/jabber-spam-fighting-manifesto
    ip_access: trusted_network
  mod_roster:
    versioning: true
  mod_s2s_dialback: {}
  mod_shared_roster: {}
  mod_stream_mgmt:
    resend_on_timeout: if_offline
  mod_stun_disco:
    credentials_lifetime: 12h
    services:
        -
          host: 0.0.0.0
          port: 3478
          type: stun
          transport: udp
          restricted: false
        -
          host: 0.0.0.0
          port: 3478
          type: turn
          transport: udp
          restricted: true
        -
          host: example.com
          port: 5349
          type: stuns
          transport: tcp
          restricted: false
        -
          host: example.com
          port: 5349
          type: turns
          transport: tcp
          restricted: true
  mod_vcard: {}
  mod_vcard_xupdate: {}
  mod_version:
    show_os: false

### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8

Please remember that this configuration is not strict. You could use a differently defined config to achieve same results. However, this one is what I built over the course of my tutorials and it should help you with setting up your ejabberd XMPP server.

Conclusion

This tutorial explains the steps I used on fresh installations of ejabberd XMPP server versions 20.03 and 20.04. What are your common configuration tricks and issues with ejabberd XMPP server? Let me know in the comments.

In this ejabberd XMPP server tutorial series:

Photo by Jake Hills on Unsplash