How to set up ejabberd video & voice calling

Last time, I described how to set up ejabberd real time IM server and migrate your office to XMPP chat. In this tutorial I will explain how to configure ejabberd video & voice calling.

I assume the ejabberd 20.03 configuration from that previous tutorial as a start. It turns out, if you try ejabberd video & voice calling within your local network, it just works. If your office is on the same LAN or Wi-Fi, everyone will be able to voice or video call each other. Follow the setup from my previous tutorial. To achieve the best result, everyone should use the same chat app (“client”) on their phones or computers.

But that’s not good enough. You want your office staff to communicate no matter the location. You could use an office VPN. But all devices connected to it should appear as if on the same local network. That’s a significant overhead, especially for smartphones.

Lucky for us, ProcessOne just released ejabberd 20.04. This new version has a built-in STUN/TURN server. It simplifies service discoverability between clients. This helps chat apps setup a direct link between each other no matter the network they are on. And makes ejabberd video & voice calling possible.

» Don’t want to configure ejabberd video & voice calling yourself?
ProcessOne experts will make your business instantly connected. Contact us »

ejabberd video & voice calling

Updating ejabberd

First, we need to update our current ejabberd instance to version 20.04 or newer. Be sure to make a backup. Please read the upgrade procedure docs to check the migration notes. Once ready, proceed with the update:

wget https://www.process-one.net/downloads/downloads-action.php?file=/20.04/ejabberd_20.04-0_amd64.deb -O ejabberd_20.04.deb
apt install ./ejabberd_20.04.deb
/etc/init.d/ejabberd start

Configuring STUN/TURN for ejabberd video & voice calling

Now, we need to edit ejabberd.yml configuration file to enable STUN/TURN discovery using mod_stun_disco. Add the following somewhere at the bottom of the modules section:

modules:
  ...
  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

Substitute 0.0.0.0 with the IP address of your ejabberd server, and example.com with your ejabberd domain. Also, make sure your server & firewall allows connections on ports 3478, 5349.

Finally, we have to actually listen for STUN/TURN traffic. We need to add new listeners in the listen section at the top of that configuration file:

listen:
  ...
  -
    port: 3478
    transport: udp
    module: ejabberd_stun
    use_turn: true
    turn_min_port: 49152
    turn_max_port: 65535
    ## The server's public IPv4 address:
    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

Substitute 0.0.0.0 with the IP address of your ejabberd server. Make sure that server & firewall allows connections in the range of ports from 49152 to 65535.

Configuring ejabberd STUN/TURN domain records (DNS)

There are a few extra steps to make it easier for clients to discover the STUN/TURN services. Create a list of SRV records under your main ejabberd domain:

_stun._udp   IN SRV  0 0 3478 example.com.
_stun._tcp   IN SRV  0 0 3478 example.com.
_stuns._tcp  IN SRV  0 0 5349 example.com.

_turn._udp   IN SRV  0 0 3478 example.com.
_turn._tcp   IN SRV  0 0 3478 example.com.
_turns._tcp  IN SRV  0 0 5349 example.com.

Different domain providers have different names in the forms to set up such records. The above listings are usually split this way:

  • service: stun
  • protocol: udp or tcp
  • priority: 0
  • weight: 0
  • port: 3478 or 5349
  • target: example.com

Testing ejabberd video & voice calling

In this tutorial I have tested ejabberd video & voice calling using two Android devices. Both were running Conversations. One device was on my local Wi-Fi while the other was on LTE. Both ejabberd video & voice calls were established quickly and the quality was between good and excellent.

Sometimes you may experience long delays while establishing calls. In that case try adjusting the shaper settings in ejabberd configuration as follows:

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

» Do you need a more specific solution?
ProcessOne experts are ready to help. Contact us »

What’s next?

ejabberd server has a lot more to offer. We could experiment with BOSH or WebSocket connections that are useful for web applications. We could try and set up an MQTT broker. Let me know in the comments what kind of tutorials you want the most. For now, let’s tweak your ejabberd server to get 100% in the XMPP compliance test.

In this ejabberd tutorial series:

Photo by Harry Cunningham on Unsplash


Let us know what you think 💬


74 thoughts on “How to set up ejabberd video & voice calling

  1. It’s just great that ejabberd now supports audio and video calls. Thanks for this tutorial. Personally I lilke to see another one about how to set up BOSH.

  2. Does this setting not support passwords hashed in SCRAM?
    Does this setting only support plaintext passwords story?

      • Not exactly. Although ejabberd STUN/TURN server doesn’t support SCRAM, the settings in my tutorial rely on default ejabberd config that uses SCRAM. Conversations client relies on a temporary auth tokens, and this works with SCRAM.

  3. Hey, thank you so much for this great tutorial.
    I was able to make audio/video calls using Conversations until I had to reboot my server.
    After the reboot I can’t make any video/audio calls.
    The devices can’t succesfully establish connection.
    Can you help me please?

    • If you rebooted your server, it’s possible ejabberd didn’t start on your server boot. Check running command `/etc/init.d/ejabberd status` and if it’s not running then `/etc/init.d/ejabberd start`, otherwise `/etc/init.d/ejabberd restart`.

      • Hey Marek, thank you very much for your reply.
        Ejabberd is running, everything is working just fine, I can send messages with no problem.
        My only problem is connecting the devices to successfully establish the call.
        It only works inside my local network. Before you ask, the ports for the turn/stun server are open.

        When I reboot the server I usually run “./bin/ejabberdctl start” anyway I tried the commands you suggested and the result is the same.

        Could it be related with the fact that I didn’t the SRV records on the DNS provider?

        Sorry if I said something dumb.

  4. Hi, Thank you for this post. I would love to see how you connect the ejabberd server to a web application (website). I am trying to create a web live chat on an ejabberd server. The web live chat I am creating is similar to the ones seen on e-commerce websites used for customer support.

    Thanks in advance for your reply.

    • Yes. You don’t need a STUN/TURN server for that, it will just work. But, your ejabberd server needs to be inside your LAN and your config file needs to use the local IP address of this server. Additionally, you most likely have to ensure all servers and clients inside your LAN correctly resolve your ejabberd server domain. So if accounts on your ejabberd look like user@example.com, each server and client should have in its hosts file an entry with example.com pointing to ejabberd server local IP address.

        • He probado varias, para chat, en general todas funcionan bien, para llamadas estoy tratando con Jitsi (el software cliente los soporta, pero recién estoy probando voz.

  5. @Marek Foss, Can you link the version of conversations used for video call? I cant seem to see that option in the one i downloaded from the playstore. Did you build from source?

  6. Hola Marek Foss he quedado super impresionado con este proyecto y de verdad que lo estoy usando y tratando de sacar el máximo provecho aunque todavía no he entendido como configurarlo al 100 %.
    Estoy intentando configurar los servidores STUN / TURN para video ejabberd y llamadas de voz y no me ha resultado muy facil, por favor podrias explicarme mejor como hacerlo, yo uso Windows.
    He recomendado este grandioso proyecto a muchos de mis amigos y que bueno que encontre ese blog para ayuda.
    Por favor me podrias contactar en privado por mi correo.
    Muchas gracias por esta super herramienta, un saludo desde Cuba, recuerda contactarme.

    • Yes, but on the client side, so it depends on the client implementation. Conversations, for example, encrypts the calls.

        • You should test it in real world conditions. The TURN docs state “that each TURN relay allocation requires a dedicated port, and that several TURN relays might be allocated for a single, e.g., audio/video call. Therefore, make sure to keep the port range large enough.”

          • Hello. Thank you for tutorial (: I have set up almost everything. Sorry, but one thing i don’t understand clearly, how should be forwarded portrange 49152-65535 on router? Incoming to ejabberd’s IP or to clients’ IP?
            And is it possible in iptables DNAT from portrange to portrange?

    • What do you mean? I tested the connection between users registered on the same ejabberd server and domain, but interop should work as well.

      • Thx for your answer.
        I mean, is the stun/turn services are publicly reachable or is only usable by users of ejabberd server itself (and their contacts on others servers to reach them) ?
        Great “how to” anyway, work like a charm.

        • Thanks, glad it works well! By default, so in this tutorial as well, the stun/turn server setting is “auth_type: user” meaning ejabberd authentication backend is used, but that doesn’t block external people from calling you. It is enough if at least one party has a stun/turn server: in case you are calling someone, it will give that person your reachable address and port; in case someone is calling you, that person will receive your reachable address and port from your stun/turn server. So you should be able to call anyone, and everyone should be able to call you. However, there can be issues with some home routers that exhibit terrible network behaviour around port forwarding ;)

  7. According to your «how to» and documentation with «auth_realm» option, I have to multiply listen port for each virtual host. I understand that multiple vhost can’t share the same couple of stun/turn port (5349/3478). Right ?

    Another thing, «turn_ip» is deprecated according to log at launch, «turn_ipv4_address» must be used with 20.07 version.

  8. I digress about the original subject. I saw that ejabberd support the sip protocol, do you know if it is possible to make a call from sip to xmpp ?
    ty again for your answer.

  9. How to deal with dynamic ip addresses? I’m using ejabberd on a server in my basement with an ip address that changes every night. Until now clients connect via DynDNS, which works perfectly fine. However, STUN and TURN seem to require static ips, is that correct?
    So how can I use STUN/TURN with dynamic IPs?

  10. With the voice call service, you’ll be ready to send your messages to a plethora of recipients in just one click. And it’ll actually help your business to grow by establishing proper communication with the customers/purchasers.

  11. Hello,

    Does ejabberd or XMPP in general support conference (multiparty) calls ? Only thing I find is Jitsi but it’s less integrated to XMPP. I’d like to have conference calls and other features in a single app.

  12. Failed to start ejabberd application: Invalid value of option modules->mod_disco: Unknown option: credentials_lifetime. Did you mean extra_domains? Available options are: extra_domains, name, server_info

  13. Failed to start ejabberd application: Invalid value of option modules->mod_disco: Unknown option: services. Did you mean server_info? Available options are: extra_domains, name, server_info

    • Both your errors are pretty much explained. You are adding config options to “mod_disco” instead of “mod_stun_disco”.

  14. So with the changes added in the examples above, I can only get ejabberd to start in live mode but when I try starting the daemon, it fails. I’m still trying to find the right systemd commands to give me enough verbose information to find out why.

  15. Hi Marek. I installed a server on a VM in a local network behind NAT IPv4 with a subdomain name dc.example.com. Everything works in the local network. I cannot establish an Audio connection from LTE. From Conversation the call goes to the second subscriber, but there is no call to the STUN server and the connection is not established. I do not see packets on the router to ports 3478 5349. The SRV record is directed to the dc.example.com subdomain. NSLOOKUP: Server: dc.example.com
    Address: XX.XX.XX.XX # 53 _stun._tcp.dc.example.com service = 5 0 3478 dc.example.com. For the test, I put the coturn server and all tests pass with it. Is there a problem with subdomain names or is there something wrong with the settings?

  16. I configured server for stun and turn. and also enabled the port , but my turn server were not working ?? what username and password should i provide to check the turn server ?? because at time of configuration there was not any username or password field set ??
    Kindly guide me on this i am newbie on server installation.

    • The best way to check the server is to use the Conversations app from F-droid repo and establish a audio or video chat between an account on your wifi and an account on a mobile network for example. Both accounts can be from the same server, just the networks should be separated for the stun/turn to kick in (it is not used for audio/video calls on a local network).

  17. I installed a server and tested video & voice calling using two Android devices(The same wifi),after the call answered,it’s show “Unable to connect the call”(i use the Conversations),I want to know where could be wrong
    1、server’s log (Forgive me for using *.*.*.* replace the actual IP address):
    [info] @mod_stun_disco:handle_call:331 Offering STUN/TURN services to ***@***.***/Conversations.iOcJ (7e60b8331deff47c
    [info] @mod_stun_disco:handle_call:331 Offering STUN/TURN services to ***@***.***/Conversations.8aD5 (b45567da1deff47c)
    [info] @ejabberd_listener:accept:273 () Accepted connection *.*.*.*:38541 -> *.*.*.*:5349
    [info] @ejabberd_listener:accept:273 () Accepted connection *.*.*.*:38542 -> *.*.*.*:5349
    [info] Creating TURN allocation (lifetime: 599 seconds) [TLS, session wy, user 1611943099:7e60b8331deff47c, client *.*.*.*:38541, relay 0.0.0.0:53247]
    [info] Creating TURN allocation (lifetime: 599 seconds) [TLS, session xe, user 1611943088:b45567da1deff47c, client *.*.*.*:38542, relay 0.0.0.0:61265]
    [info] Relayed 0 KiB (in 0 B / 0 packets, out 0 B / 0 packets), duration: 12 seconds [TLS, session xe, user 1611943088:b45567da1deff47c, client *.*.*.*:38542, relay 0.0.0.0:61265]
    [info] Relayed 0 KiB (in 0 B / 0 packets, out 0 B / 0 packets), duration: 15 seconds [TLS, session wy, user 1611943099:7e60b8331deff47c, client *.*.*.*:38541, relay 0.0.0.0:53247]

    2、shaper
    shaper:
    normal: 1000
    fast: 50000

    3、STUN/TURN domain records
    SRV _stuns._tcp 0 0 5349 mydomain
    SRV _stun._tcp 0 0 3478 mydomain
    SRV _stun._udp 0 0 3478 mydomain
    SRV _turns._tcp 0 0 5349 mydomain
    SRV _turn._tcp 0 0 3478 mydomain
    SRV _turn._udp 0 0 3478 mydomain

    4、ejabberd version:
    ejabberd-20.12-linux-x64

  18. Hello, maybe my English is not the best. Is it correct to put the
    _stun._udp IN SRV 0 0 3478 example.com.
    _stun._tcp IN SRV 0 0 3478 example.com.
    _stuns._tcp IN SRV 0 0 5349 example.com.

    _turn._udp IN SRV 0 0 3478 example.com.
    _turn._tcp IN SRV 0 0 3478 example.com.
    _turns._tcp IN SRV 0 0 5349 example.com.

    entries into ejabberd.yml?

    • No no, this is the configuration of your example.com domain. You set the SRV records using your domain registrar. The UI for each registrar is may differ, and some domain registrars don’t allow adding SRV records, so you need to check with yours.

  19. Hello,
    I have been looking for a solution for a long time, and I hope you can guide me.
    In fact I installed an ejabberd server thanks to your tutorials. and with conversions we can make audio / video calls and also messaging. Honestly the course is cool.
    Now for internal needs we have to program an android application which integrates audio / video calls with android.
    I did several searches and found that smack could be used to communicate with an xmpp server.
    We have, via Android studio, program the connection with our ejabberd server and nopus have been able to implement the sending of sms via our server and via smack. This was just for testing as our goal is audio / video calls for internal purposes (not exactly like Conversations).
    But for the audio / video calling part, smack cannot do this. Do you have a solution to use the ejabberd server already configured for audio / video calls?

    Thank you

  20. Hello,

    Thank you for writing these. I am having a difficult time getting the Voice/Video configuration to work and am not sure if this can even work for the setup I am attempting. I setup a debian server on a beaglebone black and was hoping to make a small ejabberd server.

    When setting up the configuration for STUN/TURN,

    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

    For host, I do not have a static ip, so would I need to check this every day and make sure that the ip hasn’t changed? Or is this looking for the local ip on my network? Or can I just put in the no-ip domain name, which is the impression I got from https://docs.ejabberd.im/admin/configuration/modules/#mod-stun-disco ?

    The same question applies to the listen section:
    listen:


    port: 3478
    transport: udp
    module: ejabberd_stun
    use_turn: true
    turn_min_port: 49152
    turn_max_port: 65535
    ## The server’s public IPv4 address:
    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

    under ip and turn_ip, do I need to local ip, the public ip, or can the domain name suffice?

    Plus, by default the config file contains an entry for 3478
    port: 3478
    ip: “::”
    transport: udp
    module: ejabberd_stun
    use_turn: true
    ## The server’s public IPv4 address:
    # turn_ipv4_address: “203.0.113.3”
    ## The server’s public IPv6 address:
    # turn_ipv6_address: “2001:db8::3”

    Do I need an additional one to this?

    • Honestly, I don’t know if with no-ip it will work, but what I suggest is to try. Works by elimination: first test the no-ip, if it doesn’t work, try the local address, if it doesn’t work, so you must have a public address. If others have already tried, they will tell you their results. But while waiting for an answer, I give you an applicable solution.

      • Thank you for the reply. I was able to get ejabberd to start after modifying the config with the mod_stun_disco added, but when the listen was added, I am unable to start ejabberd

        root@salus:/etc/ejabberd# /etc/init.d/ejabberd start
        [….] Starting ejabberd (via systemctl): ejabberd.serviceJob for ejabberd.service failed because the control process exited with error code.
        See “systemctl status ejabberd.service” and “journalctl -xe” for details.
        failed!
        root@salus:/etc/ejabberd# systemctl status ejabberd.service
        ● ejabberd.service – robust, scalable and extensible realtime platform (XMPP server + MQTT broker + SIP service)
        Loaded: loaded (/lib/systemd/system/ejabberd.service; enabled; vendor preset: enabled)
        Active: activating (start) since Fri 2021-03-12 00:27:09 UTC; 14s ago
        Docs: https://www.process-one.net/en/ejabberd/docs/
        Cntrl PID: 12204 (sh)
        Tasks: 41 (limit: 1026)
        Memory: 27.0M
        CGroup: /system.slice/ejabberd.service
        ├─12204 /bin/sh -c /usr/sbin/ejabberdctl start && /usr/sbin/ejabberdctl started
        ├─12221 /bin/sh /usr/sbin/ejabberdctl started
        ├─12223 /usr/lib/erlang/erts-10.2.4/bin/beam.smp -K true -P 250000 — -root /usr/lib/erlang -progname erl — -home /var/lib/ejabberd — -sname ejabberd@localhost -sm
        ├─12232 erl_child_setup 65536
        ├─12291 /usr/lib/erlang/lib/p1_eimp-1.0.19/priv/bin/eimp
        ├─12296 /usr/lib/erlang/erts-10.2.4/bin/beam.smp -K true -P 250000 — -root /usr/lib/erlang -progname erl — -home /var/lib/ejabberd — -sname e2b-ctl-ejabberd@local
        └─12307 erl_child_setup 65536

        Mar 12 00:27:09 salus systemd[1]: Starting robust, scalable and extensible realtime platform (XMPP server + MQTT broker + SIP service)…
        root@salus:/etc/ejabberd# systemctl status ejabberd.service


        port: 3478
        transport: udp
        module: ejabberd_stun
        use_turn: true
        turn_min_port: 49152
        turn_max_port: 65535
        ## The server’s public IPv4 address:
        turn_ip: (I added my public ip address)
        #port: 3478
        # ip: “::”
        # transport: udp
        # module: ejabberd_stun
        # use_turn: true
        ## The server’s public IPv4 address:
        # turn_ipv4_address: “203.0.113.3”
        ## The server’s public IPv6 address:
        # turn_ipv6_address: “2001:db8::3”


        port: 5349
        transport: tcp
        module: ejabberd_stun
        use_turn: true
        tls: true
        turn_min_port: 49152
        turn_max_port: 65535
        ip: (I ADDED MY PUBLIC IP ADDRESS)
        turn_ip: (IADDED MY PUBLIC IP ADDRESS)

        For port 3478, I commented out what was in the file for the stun since the instructions on this page appeared to be a duplicate. I tried it with both and neither would allow ejabberd to start.

        Any help would be much appreciated.

  21. I have followed every step for setup tutorial and this one, I am able to communicate by text message but not able to make calling. Someone told me it is the TSL certificate issue. Because without a valid certificate calling can never be established over internet. My ejabberd is running on a VPS no web service. So I assume I have to apply for a certificate and place it in the server. Can you make a tutorial for this? Please make it as simple as the previous ones, those helped a lot. Thanks!

  22. Hi all,

    I Install it on Ubuntu 18.04, with 20.04.
    Chat working normal.
    But when i try for voice calling using astrachat application, it ringing but no sound when the call pickup.
    Its still on same LAN.

    Any help would be much appreciated.

    Regards,
    Dona H S

    • Check using Conversations (Android) and BeagleIM (iOS) first. They have a tested implementation and are known to work. This way you will rule out client issues. If problem persists, it means your server or network is misconfigured.

Leave a Comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.