Setting Up ejabberd for XEP-0389 Implementation
Quickly reminder
As part of my Google Summer of Code (GSoC) project, I embarked on the journey of implementing XEP-0389 in ejabberd. This blog post details the process of setting up ejabberd, the challenges I encountered, and how I overcame them. I aim to provide a comprehensive guide for developers, especially those new to ejabberd and XMPP.
Setting Up ejabberd
1. Installation:
- First, I installed ejabberd from the official website. For developers it is strongly recommended to download the source code and follow the instructions : https://docs.ejabberd.im/admin/install/source/ For this project, the configuration file is located at /usr/local/etc/ejabberd/ejabberd.yml.
2. Configuration: (Optional)
- I configured ejabberd to use SQL for user management instead of the default Mnesia database:
yaml auth_method: sql sql_type: pgsql sql_server: "localhost" sql_database: "ejabberd" sql_username: "ejabberd" sql_password: "password"
3. Port Configuration:
- I made sure ejabberd listens on the correct ports by updating ejabberd.yml:
`yaml
listen:
- port: 5222 ip: “::” module: ejabberdc2s starttls: false starttlsrequired: false `
Overcoming Challenges
1. Module Loading Issues:
- Initially, I encountered issues with modules not loading. The command
ejabberdctl modules_installed
returned empty. After verifying that the module files were in place and correctly referenced in the configuration, I realized that I was wrong. I reached out to ejabberd developpers (badlop and prefiks helped oud on this) and got some usefull feedbacks from them. ` if you want to check if an ejabberd module is loaded (this includes internal, external/contrib...)
$ ejabberdctl debug
genmod:loadedmodules(<<“localhost”>>). [modadhoc,modping,modmam,modannounce,mod_offline, ...
genmod:isloaded(<<“localhost”>>, mod_ping). true
you can also check any erlang beam file, not only ejabberd modules:
code:isloaded(modping). {file,“/home/badlop/git/ejabberd/build/dev/lib/ejabberd/ebin/modping.beam”}
code:isloaded(ejabberdsm). {file,“/home/badlop/git/ejabberd/build/dev/lib/ejabberd/ebin/ejabberdsm.beam”}
code:is_loaded(mnesia). {file,“/home/badlop/.asdf/installs/erlang/27.0/lib/mnesia-4.23.2/ebin/mnesia.beam”}`
Also I ensured the ejabberd service user had the necessary permissions:
sh
sudo chown -R assu_2000:ejabberd /usr/local/var/lib/ejabberd
sudo chmod -R 750 /usr/local/var/lib/ejabberd
2. Database Configuration:
I needed to switch from the default Mnesia database to SQL for user management.
Solution:
- Install PostgreSQL and configure the database.
- Update ejabberd.yml with the appropriate database settings as shown above.
3. TLS and Connection Issues:
During testing with xmppconsole, I faced TLS connection issues and errors indicating that the server was refusing to authenticate over an unencrypted connection. I didn't want to encrypt the connection as I was working and testing locally.
Solution: I set
starttls_required: false
in the ejabberd.yml configuration: `yaml listen:- port: 5222 ip: “::” module: ejabberdc2s starttls: false starttlsrequired: false `
Also I ensured that the main.go file (more on this later) was set up to allow un-encrypted connection. ` package main
import ( “fmt” “log” “os”
“github.com/xmppo/go-xmpp” )
func main() { jid := os.Getenv(“JID”) password := os.Getenv(“PASSWORD”) host := os.Getenv(“HOST”)
if jid == “” || password == “” || host == “” { log.Fatal(“Usage: JID, PASSWORD and HOST must be set as environment variables”) }
options := xmpp.Options{ Host: host, User: jid, Password: password, NoTLS: true, StartTLS: false, Debug: true, InsecureAllowUnencryptedAuth: true, Session: true, Status: “available”, StatusMessage: “Welcome on our new codebot overlords.”, Resource: “xmppconsole”, }
talk, err := options.NewClient() if err != nil { log.Fatalf(“Failed to create XMPP client: %v”, err) }
fmt.Println(“Connected to XMPP server.”) for { chat, err := talk.Recv() if err != nil { log.Fatal(err) } switch v := chat.(type) { case xmpp.Chat: fmt.Printf(“Received message from %s: %s\n”, v.Remote, v.Text) case xmpp.Presence: fmt.Printf(“Received presence from %s\n”, v.From) } } }
`
4. Hostname and Hosts File Configuration:
- I faced issues with hostname resolution and had to ensure that my /etc/hosts file was correctly configured:
plaintext 127.0.0.1 localhost mbula
Using ejabberdctl
Instead of using systemctl, I decided to use ejabberdctl to manage the ejabberd server. Here are some useful commands:
Start ejabberd:
sh ejabberdctl start
Stop ejabberd:
sh ejabberdctl stop
Check registered users:
sh ejabberdctl registered_users localhost
Register new user :
sh ejabberdctl register newuser localhost newpassword
Setting Up xmppconsole
xmppconsole has the unique purpose of testing. To execute it , you need it installed alongside Python3 or Go. I chose to go with Go :) By the way, xmppconsole has only 1 required dependency: libstrophe version 0.10.0 or higher This is where the main.go file plays a key role .
1. Installation and Configuration:
- Clone the xmppconsole repository:
sh git clone https://github.com/xmppo/xmppconsole cd xmppconsole go mod init xmppconsole go mod tidy go build
2. Configuring main.go:
Ensure the main.go file is set up to use environment variables for JID, password, and host: `go package main
import ( “fmt” “os” “github.com/mattn/go-xmpp” )
func main() { options := xmpp.Options{ Host: os.Getenv(“HOST”), User: os.Getenv(“JID”), Password: os.Getenv(“PASSWORD”), NoTLS: true, Debug: true, }
client, err := options.NewClient() if err != nil { fmt.Printf(“Failed to create XMPP client: %v\n”, err) return }
fmt.Println(“Connected to XMPP server.”) } `
Set the environment variables before running
xmppconsole
:sh export JID=assu@localhost export PASSWORD=yourpassword export HOST=localhost
3. Running xmppconsole:
- I executed the following command to connect to ejabberd:
sh ./xmppconsole -jid=assu@localhost -password=yourpassword -host=localhost -port=5222
Expected output : ` ./xmppconsole -jid=assu@localhost -password=yourpassword -host=localhost -port=5222 <?xml version='1.0'?> <?xml version='1.0'?> stream:featuresDIGEST-MD5PLAINSCRAM-SHA-1X-OAUTH2/stream:features biwsbj1hc3N1LHI9MDVmMDA0OGFiMWI4NThhMA== cj0wNWYwMDQ4YWIxYjg1OGEwQXpsUnd3b1p4Uk05ZzZTendCOEsyQT09LHM9bFBQdjJJc0hHemdaK1d5eTFsQlcvdz09LGk9NDA5Ng== Yz1iaXdzLHI9MDVmMDA0OGFiMWI4NThhMEF6bFJ3d29aeFJNOWc2U3p3QjhLMkE9PSxwPVFleTE1SWE2T1hydThRaE5yWElJZ1pycHFxTT0= dj1TYzloRFU3a2w0MEp5WXA5UUNQRk15M1Q2Nzg9 <?xml version='1.0'?> <?xml version='1.0'?> stream:features/stream:features xmppconsole assu@localhost/xmppconsole availableWelcome on our new codebot overlords. Connected to XMPP server. availableI for one welcome our new codebot overlords.Bad value of cdata in tag <show/> qualified by namespace 'jabber:client' Received presence from
`
Using xmppconsole
Once connected, I could send messages and manage presence using xmppconsole. Here are a few examples:
*Send a Message:
sh
message recipient@localhost "Hello, this is a test message"
*Set Presence:
sh
presence
Conclusion
Setting up ejabberd for XEP-0389 implementation involved configuring the server, addressing module loading issues, managing database settings, and overcoming connection problems with xmppconsole
. This detailed journey highlights the common challenges and solutions, providing a guide for developers embarking on similar projects.
For more detailed information and troubleshooting, refer to the ejabberd and XMPP documentation and the ejabberd xmpp community group as well. Happy coding!
P.S : This blog post provides a comprehensive overview of my experience setting up ejabberd and troubleshooting various issues. By following this guide, other developers should be able to set up their environments more smoothly and focus on implementing new features other to XEP-0389.
I'd love to hear from you! If you're struggling with XMPP implementation or have any questions, feel free to reach out. I'm always happy to help a fellow coder out.
Github Profile : Link
Thanks for reading !