Deploying ejabberd
Introduction
ejabberd is a robust, scalable, and extensible XMPP (Extensible Messaging and Presence Protocol) server written in Erlang. Used by organizations worldwide, from small teams to platforms with millions of users, ejabberd provides reliable instant messaging, presence information, and real-time communication capabilities.
Originally developed in 2002, ejabberd has matured into one of the most trusted XMPP servers available. Its Erlang foundation provides exceptional concurrency and fault tolerance, making it capable of handling massive user bases while maintaining low latency and high availability. The server supports modern messaging features including group chats, file transfers, voice and video calls, and message archiving.
Key highlights of ejabberd:
- Scalability: Handle millions of concurrent users with clustering support
- Reliability: Erlang’s fault-tolerant design ensures high availability
- XMPP Compliance: Full support for core XMPP specifications and extensions
- Federation: Connect with other XMPP servers across the internet
- Multi-Protocol: Support for XMPP, MQTT, SIP, and WebSocket
- Multi-User Chat: Group chat rooms with moderation and persistence
- Message Archive: Server-side message storage for offline access
- Push Notifications: Mobile push support for iOS and Android
- LDAP/OAuth: Enterprise authentication integration
- Web Admin: Browser-based administration interface
- 100% Open Source: GPL licensed with commercial support available
This guide walks through deploying ejabberd on Klutch.sh, configuring XMPP services, and managing your instant messaging platform.
Why Deploy ejabberd on Klutch.sh
Deploying ejabberd on Klutch.sh provides several advantages for real-time communication:
Simplified Deployment: Klutch.sh handles container orchestration while you focus on messaging configuration.
Data Ownership: Keep all messages and user data on your own infrastructure.
Persistent Storage: Attach volumes for message archives and user data that persist securely.
Scalable Resources: Allocate resources based on your user base and scale as needed.
Custom Domains: Use your own domain for professional XMPP addresses.
Always-On Availability: Your messaging server remains accessible 24/7 for real-time communication.
Prerequisites
Before deploying ejabberd on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your configuration
- A domain name with DNS control
- TLS certificates for your domain
- Basic understanding of XMPP protocol concepts
- (Optional) An XMPP client for testing
Understanding ejabberd Architecture
ejabberd uses Erlang’s OTP framework for reliability:
Erlang BEAM: The virtual machine provides lightweight processes and fault tolerance.
Mnesia Database: Built-in distributed database for user data and configurations.
External Database: Optional PostgreSQL or MySQL for larger deployments.
Module System: Modular architecture allows enabling specific features as needed.
Clustering: Multiple nodes can form a cluster for high availability.
Preparing Your Repository
Create a GitHub repository with your ejabberd configuration.
Repository Structure
ejabberd-deploy/├── Dockerfile├── config/│ └── ejabberd.yml├── scripts/│ └── entrypoint.sh└── .dockerignoreCreating the Dockerfile
Create a Dockerfile for your ejabberd deployment:
FROM ejabberd/ecs:latest
# Copy configurationCOPY config/ejabberd.yml /home/ejabberd/conf/ejabberd.yml
# Copy entrypoint scriptCOPY scripts/entrypoint.sh /entrypoint.shUSER rootRUN chmod +x /entrypoint.shUSER ejabberd
# Create directoriesRUN mkdir -p /home/ejabberd/database /home/ejabberd/upload
# Expose ports# XMPP client connectionsEXPOSE 5222# XMPP client connections (TLS)EXPOSE 5223# XMPP server-to-serverEXPOSE 5269# XMPP BOSH/WebSocketEXPOSE 5280# XMPP secure BOSH/WebSocketEXPOSE 5443
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD ejabberdctl status || exit 1
ENTRYPOINT ["/entrypoint.sh"]CMD ["foreground"]Creating ejabberd Configuration
Create config/ejabberd.yml:
###### ejabberd configuration file###
# Loggingloglevel: infolog_rotate_size: 10485760log_rotate_count: 5
# Virtual hostshosts: - ${XMPP_DOMAIN:-localhost}
# Certificatescertfiles: - /home/ejabberd/certs/*.pem
# Listening portslisten: - port: 5222 ip: "::" module: ejabberd_c2s max_stanza_size: 262144 shaper: c2s_shaper access: c2s starttls_required: true - port: 5223 ip: "::" module: ejabberd_c2s max_stanza_size: 262144 shaper: c2s_shaper access: c2s tls: true - port: 5269 ip: "::" module: ejabberd_s2s_in max_stanza_size: 524288 - port: 5443 ip: "::" 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: "::" module: ejabberd_http request_handlers: /admin: ejabberd_web_admin /.well-known/acme-challenge: ejabberd_acme
# S2S configurations2s_use_starttls: required
# Authenticationauth_method: internalauth_password_format: scram
# ACLsacl: admin: user: - admin@${XMPP_DOMAIN:-localhost} local: user_regexp: "" loopback: ip: - 127.0.0.0/8 - ::1/128
# Access rulesaccess_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 permissionsapi_permissions: "admin access": who: access: allow: - acl: admin what: - "*" - "!stop" - "!start"
# Shaper rulesshaper: 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
# Modulesmodules: mod_adhoc: {} mod_admin_extra: {} mod_announce: access: announce mod_avatar: {} mod_blocking: {} mod_bosh: {} mod_caps: {} mod_carbons: {} mod_client_state: {} mod_configure: {} mod_disco: {} mod_fail2ban: {} mod_http_api: {} mod_http_upload: put_url: https://@HOST@:5443/upload custom_headers: "Access-Control-Allow-Origin": "*" "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS" "Access-Control-Allow-Headers": "Content-Type" mod_last: {} mod_mam: default: always request_activates_archiving: true mod_muc: access: - allow access_admin: - allow: admin access_create: muc_create access_persistent: muc_create default_room_options: mam: true persistent: true public: true public_list: 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: storage:bookmarks: access_model: whitelist mod_push: {} mod_push_keepalive: {} mod_register: welcome_message: subject: Welcome! body: |- Welcome to the XMPP server! ip_access: trusted_network access: register mod_roster: versioning: true mod_s2s_dialback: {} mod_shared_roster: {} mod_stream_mgmt: resend_on_timeout: if_offline mod_vcard: {} mod_vcard_xupdate: {} mod_version: show_os: falseCreating Entrypoint Script
Create scripts/entrypoint.sh:
#!/bin/bashset -e
# Substitute environment variables in configenvsubst < /home/ejabberd/conf/ejabberd.yml > /home/ejabberd/conf/ejabberd.yml.tmpmv /home/ejabberd/conf/ejabberd.yml.tmp /home/ejabberd/conf/ejabberd.yml
# Start ejabberdexec /home/ejabberd/bin/ejabberdctl "$@"Creating the .dockerignore File
Create a .dockerignore file:
.git.github*.mdLICENSE.gitignore.DS_StoreDeploying ejabberd on Klutch.sh
Follow these steps to deploy your ejabberd server:
- Port 5222: Client connections (STARTTLS)
- Port 5223: Client connections (Direct TLS)
- Port 5269: Server-to-server federation
- Port 5443: HTTPS (admin, BOSH, WebSocket)
Configure DNS Records
Set up DNS records for XMPP:
| Record Type | Name | Value |
|---|---|---|
| A | xmpp | Your server IP |
| SRV | _xmpp-client._tcp | 5 0 5222 xmpp.example.com |
| SRV | _xmpp-server._tcp | 5 0 5269 xmpp.example.com |
Prepare TLS Certificates
Obtain TLS certificates for your domain. You can use Let’s Encrypt or commercial certificates.
Push Your Repository to GitHub
Initialize and push your configuration:
git initgit add .git commit -m "Initial ejabberd configuration"git remote add origin https://github.com/yourusername/ejabberd-deploy.gitgit push -u origin mainCreate a New Project on Klutch.sh
Navigate to the Klutch.sh dashboard and create a new project for your messaging platform.
Create a New App
Create a new app within your project and connect your GitHub repository.
Configure Traffic Settings
ejabberd requires multiple ports:
Set Environment Variables
Configure the following environment variables:
| Variable | Value |
|---|---|
XMPP_DOMAIN | example.com |
EJABBERD_ADMINS | admin@example.com |
Attach Persistent Volumes
Add persistent volumes for ejabberd:
| Mount Path | Recommended Size | Purpose |
|---|---|---|
/home/ejabberd/database | 50 GB | Mnesia database and message archive |
/home/ejabberd/upload | 50 GB | File uploads |
/home/ejabberd/certs | 100 MB | TLS certificates |
Deploy Your Application
Click Deploy to build and start ejabberd.
Create Admin Account
After deployment, create the admin account:
ejabberdctl register admin example.com your-passwordAccess Web Admin
Access the web admin at https://xmpp.example.com:5443/admin/
Managing Users
Creating Users
Create user accounts via command line:
ejabberdctl register username example.com passwordOr via the web admin interface.
User Registration
Configure in-band registration for self-service:
mod_register: access: register welcome_message: subject: Welcome! body: Welcome to our XMPP server!Control who can register:
access_rules: register: allow: all # Or restrict to specific IPsManaging Accounts
Common account operations:
# Change passwordejabberdctl change_password user example.com newpassword
# Delete accountejabberdctl unregister user example.com
# List registered usersejabberdctl registered_users example.comMulti-User Chat (MUC)
Creating Chat Rooms
Users create rooms by joining a new room address, or admins can create persistent rooms:
ejabberdctl create_room roomname conference.example.com example.comRoom Configuration
Configure default room options:
mod_muc: default_room_options: persistent: true public: true members_only: false allow_private_messages: true mam: trueRoom Administration
Manage rooms via ejabberdctl:
# List roomsejabberdctl muc_online_rooms conference.example.com
# Destroy roomejabberdctl destroy_room roomname conference.example.com
# Get room affiliationsejabberdctl get_room_affiliations roomname conference.example.comMessage Archive Management (MAM)
Enabling MAM
MAM stores messages server-side for offline access:
mod_mam: default: always request_activates_archiving: true db_type: sql # Or mnesia cache_size: 1000 cache_life_time: 3600Archive Retention
Configure message retention:
mod_mam: clear_archive_on_room_destroy: true default: alwaysQuerying Archives
Users query archives using MAM XEP-0313 from compatible clients.
Federation
Server-to-Server
Enable federation with other XMPP servers:
s2s_use_starttls: requireds2s_access: allRestricting Federation
Limit federation to specific domains:
s2s_access: allow: - domain: partner.com - domain: trusted.org deny: allPush Notifications
Configuring Push
Enable push notifications for mobile apps:
mod_push: {}mod_push_keepalive: {}iOS/Android Support
Push requires app-specific configuration:
- Configure APNs for iOS
- Configure FCM for Android
- Set up push gateway service
Web Clients
BOSH
Enable BOSH for web client support:
listen: - port: 5280 module: ejabberd_http request_handlers: /bosh: mod_bosh
mod_bosh: {}WebSocket
Enable WebSocket for modern web clients:
listen: - port: 5280 module: ejabberd_http request_handlers: /ws: ejabberd_http_wsProduction Best Practices
Performance Optimization
- Mnesia Tuning: Adjust Mnesia settings for large deployments
- Connection Limits: Set appropriate max_stanza_size
- Shaper Rules: Configure traffic shaping for fairness
Security Recommendations
- TLS Required: Enforce TLS for all connections
- Strong Authentication: Use SCRAM-SHA-256
- Rate Limiting: Enable mod_fail2ban
- Regular Updates: Keep ejabberd updated
High Availability
For critical deployments:
- Set up ejabberd clustering
- Configure external database (PostgreSQL)
- Use load balancer for client connections
Backup Strategy
Regular backups should include:
- Mnesia database directory
- Configuration files
- TLS certificates
- Upload directory
Troubleshooting Common Issues
Connection Failures
Symptoms: Clients cannot connect.
Solutions:
- Verify DNS SRV records
- Check TLS certificate validity
- Ensure ports are exposed
- Review ejabberd logs
Authentication Issues
Symptoms: Users cannot log in.
Solutions:
- Verify account exists
- Check password format
- Ensure auth module is configured
- Review auth logs
Federation Not Working
Symptoms: Cannot communicate with other servers.
Solutions:
- Verify DNS configuration
- Check S2S port accessibility
- Confirm TLS certificates
- Review s2s logs
Message Delivery Issues
Symptoms: Messages not arriving.
Solutions:
- Check offline message limits
- Verify MAM configuration
- Review message routing
- Check recipient status
Additional Resources
- ejabberd Documentation
- ejabberd GitHub Repository
- XMPP Extensions
- ProcessOne (ejabberd developers)
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Conclusion
Deploying ejabberd on Klutch.sh gives you a battle-tested, scalable XMPP server for real-time communication. The combination of ejabberd’s Erlang-based reliability and Klutch.sh’s container management means you can run enterprise-grade messaging without complex infrastructure.
With support for federation, multi-user chat, message archiving, and modern features like push notifications and WebSocket, ejabberd handles everything from small team chat to large-scale communication platforms. Whether you’re building internal messaging for your organization or creating a public chat service, ejabberd on Klutch.sh provides the foundation for reliable, secure real-time communication.