← Back to posts
comparison guide self-hosted · · 11 min read

ejabberd vs Prosody vs OpenFire: Best Self-Hosted XMPP Server 2026

Compare the top three self-hosted XMPP/Jabber servers — ejabberd, Prosody, and OpenFire. Detailed setup guides, Docker configurations, feature comparison, and deployment recommendations for 2026.

OS
Editorial Team

The Extensible Messaging and Presence Protocol (XMPP), also known as Jabber, is an open, decentralized, XML-based communication standard that has been powering instant messaging, VoIP, video calls, and IoT messaging since 1999. Unlike proprietary platforms that lock your messages into corporate servers, XMPP lets you run your own messaging infrastructure with full control over your data, privacy, and user base.

In this guide, we compare the three most mature and widely deployed self-hosted XMPP server implementations: ejabberd, Prosody, and OpenFire. Each takes a fundamentally different approach to the problem, and choosing the right one depends on your scale, technical stack preferences, and feature requirements.

Why Self-Host an XMPP Server?

XMPP is a federated protocol — anyone can run a server and communicate with users on any other XMPP server, much like email. Self-hosting gives you:

  • Complete data ownership — your messages, contacts, and metadata stay on your infrastructure
  • Federation — talk to users on other XMPP servers worldwide
  • Extensibility — hundreds of XEPs (XMPP Extension Protocols) for features like file transfer, group chat, push notifications, and IoT
  • No vendor lock-in — switch clients freely; the protocol is open and standardized
  • End-to-end encryption — OMEMO support provides Signal-level encryption for XMPP
  • Low resource footprint — even large-scale deployments can run on modest hardware

Whether you’re setting up a team chat for your organization, building a community messaging platform, or just want private personal messaging, a self-hosted XMPP server is one of the most battle-tested solutions available.

Quick Comparison Table

FeatureejabberdProsodyOpenFire
LanguageErlangLuaJava
LicenseGPLv2MITApache 2.0
GitHub Stars6,600+~185 (Docker)3,000+
Last UpdatedApril 2026April 2026April 2026
Max ScalabilityMillions of concurrent usersHundreds to thousandsTens of thousands
Web Admin PanelYesYes (via mod_admin_web)Yes (comprehensive)
ClusteringBuilt-in (Mnesia/Erlang)Via external modulesVia Hazel plugin
Database SupportMnesia, MySQL, PostgreSQL, SQLiteSQLite, MySQL, PostgreSQLMySQL, PostgreSQL, H2, SQL Server
Docker ImageOfficial (ejabberd/ecs)Official (prosody/prosody)Official (igniterealtime/openfire)
Plugin EcosystemModerateLarge and activeVery large
REST APIYes (built-in)Via modules (mod_rest)Yes (built-in)
Memory FootprintLow (~50-200 MB)Very low (~20-80 MB)High (~512 MB+)
Best ForLarge-scale, high-availabilityLightweight, simple setupsEnterprise, admin-friendly

ejabberd: The Massively Scalable Choice

ejabberd (pronounced “Jabberd”) is written in Erlang/OTP and was designed from the ground up for massive scalability and fault tolerance. It powers some of the largest XMPP deployments in the world, including WhatsApp’s early infrastructure and numerous telecom-grade messaging platforms.

Key Features

  • Clustering out of the box — Erlang’s distributed capabilities let you run multiple ejabberd nodes as a single logical server
  • Massive concurrency — handles millions of simultaneous connections on commodity hardware
  • Multi-protocol support — XMPP, MQTT, and SIP on the same server
  • Built-in service discovery — automatically discovers and connects to other XMPP servers
  • Compliance certified — XMPP Standards Foundation compliant
  • Hot code reloading — update server code without disconnecting users

Installation

Package Installation (Debian/Ubuntu)

1
2
sudo apt update
sudo apt install ejabberd

Docker Deployment

ejabberd provides an official containerized server (ECS) image on Docker Hub:

1
2
3
4
5
6
7
8
9
docker run -d --name ejabberd \
  -p 5222:5222 \
  -p 5269:5269 \
  -p 5280:5280 \
  -p 5443:5443 \
  -e EJABBERD_USERS="admin@yourdomain.com:securepassword" \
  -e EJABBERD_DOMAIN="yourdomain.com" \
  -v ejabberd_data:/home/ejabberd \
  ejabberd/ecs:latest

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
version: "3.8"

services:
  ejabberd:
    image: ejabberd/ecs:latest
    container_name: ejabberd
    ports:
      - "5222:5222"   # Client connections
      - "5269:5269"   # Server-to-server federation
      - "5280:5280"   # HTTP API and admin panel
      - "5443:5443"   # HTTPS
    environment:
      - EJABBERD_USERS=admin@yourdomain.com:changeme123
      - EJABBERD_DOMAIN=yourdomain.com
      - EJABBERD_ADMINS=admin@yourdomain.com
    volumes:
      - ejabberd_data:/home/ejabberd
    restart: unless-stopped

volumes:
  ejabberd_data:

Configuration Highlights

ejabberd uses a YAML configuration file (/etc/ejabberd/ejabberd.yml). Key settings:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
hosts:
  - "yourdomain.com"

listen:
  -
    port: 5222
    ip: "::"
    module: c2s
    max_stanza_size: 262144
    shaper: c2s_shaper
    access: c2s
    starttls_required: true

  -
    port: 5280
    ip: "::"
    module: http_server
    http_bind: true
    request_handlers:
      "/admin": ejabberd_web_admin
      "/api": mod_http_api
      "/bosh": mod_bosh
      "/ws": ejabberd_http

auth_method: sql
sql_type: pgsql
sql_server: "localhost"
sql_database: "ejabberd"
sql_username: "ejabberd"
sql_password: "dbpassword"

Prosody: The Lightweight Champion

Prosody is written in Lua and prioritizes simplicity, low resource usage, and ease of configuration. It is the go-to choice for small to medium deployments where simplicity matters more than raw scale. Prosody is also the default XMPP server bundled with Jitsi Meet for its internal communication layer.

Key Features

  • Minimal resource usage — runs comfortably on a Raspberry Pi with under 50 MB of RAM
  • Lua-based module system — easy to write and customize modules
  • Clean configuration — a single Lua file with straightforward syntax
  • Large module ecosystem — over 100 community-maintained modules
  • Active development — regular releases with modern XEP support
  • Perfect for small teams — ideal for organizations with under 1,000 users

Installation

Package Installation (Debian/Ubuntu)

1
2
3
4
5
# Add Prosody repository
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/prosody.list
wget https://prosody.im/files/prosody-debian-packages.key -O- | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/prosody.gpg
sudo apt update
sudo apt install prosody

Docker Deployment

1
2
3
4
5
6
7
8
9
docker run -d --name prosody \
  -p 5222:5222 \
  -p 5269:5269 \
  -p 5280:5280 \
  -p 5347:5347 \
  -v /opt/prosody/data:/config/data \
  -v /opt/prosody/certs:/config/certs \
  -v /opt/prosody/prosody.cfg.lua:/config/prosody.cfg.lua \
  prosody/prosody:latest

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
version: "3.8"

services:
  prosody:
    image: prosody/prosody:latest
    container_name: prosody
    ports:
      - "5222:5222"   # Client connections
      - "5269:5269"   # Server-to-server federation
      - "5280:5280"   # HTTP/BOSH
      - "5347:5347"   # Component connections
    volumes:
      - ./prosody.cfg.lua:/config/prosody.cfg.lua:ro
      - ./data:/config/data
      - ./certs:/config/certs
    restart: unless-stopped

Configuration Highlights

Prosody uses a Lua configuration file (/etc/prosody/prosody.cfg.lua):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
-- Global settings
admins = { "admin@yourdomain.com" }

-- Enable modules you need
modules_enabled = {
    "roster";
    "saslauth";
    "tls";
    "dialback";
    "disco";
    "carbons";
    "mam";        -- Message Archive Management
    "http_files"; -- Static file hosting
    "http_upload"; -- XEP-0363 file uploads
    "bosh";       -- HTTP binding for web clients
    "websocket";  -- WebSocket support
    "admin_web";  -- Web admin interface
    "pep";        -- Personal Eventing Protocol
}

-- Require encryption
c2s_require_encryption = true
s2s_require_encryption = true

-- Virtual host configuration
VirtualHost "yourdomain.com"
    ssl = {
        key = "/etc/prosody/certs/yourdomain.com.key";
        certificate = "/etc/prosody/certs/yourdomain.com.crt";
    }

-- Use SQLite for storage (default)
storage = "internal"

-- Or use PostgreSQL for larger setups
-- storage = "sql"
-- sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }

OpenFire: The Enterprise-Friendly Option

OpenFire, maintained by Ignite Realtime, is a Java-based XMPP server that stands out for its polished web administration interface and extensive plugin ecosystem. If you prefer a GUI-driven management experience and need enterprise-grade user management features, OpenFire is the strongest choice.

Key Features

  • Comprehensive web admin console — manage everything through a browser
  • Huge plugin marketplace — 100+ plugins for monitoring, authentication, integration
  • LDAP/Active Directory integration — connect to existing user directories
  • Group chat (MUC) support — full multi-user chat with moderation
  • Built-in HTTP binding — BOSH and WebSocket for web clients
  • Cross-platform — Java runs everywhere
  • REST API — programmatic management and integration

Installation

Docker Deployment

1
2
3
4
5
6
7
8
9
docker run -d --name openfire \
  -p 9090:9090 \
  -p 9091:9091 \
  -p 5222:5222 \
  -p 5269:5269 \
  -p 7070:7070 \
  -p 7443:7443 \
  -v /opt/openfire/data:/var/lib/openfire \
  igniterealtime/openfire:latest

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
version: "3.8"

services:
  openfire:
    image: igniterealtime/openfire:latest
    container_name: openfire
    ports:
      - "9090:9090"   # HTTP admin console
      - "9091:9091"   # HTTPS admin console
      - "5222:5222"   # Client connections
      - "5269:5269"   # Server-to-server federation
      - "7070:7070"   # HTTP BOSH
      - "7443:7443"   # HTTPS BOSH
    volumes:
      - openfire_data:/var/lib/openfire
    restart: unless-stopped

volumes:
  openfire_data:

Post-Installation Setup

OpenFire requires an initial setup wizard accessed at http://your-server:9090:

  1. Select language and domain
  2. Choose embedded database (H2) or external (PostgreSQL/MySQL)
  3. Set up admin credentials
  4. Configure LDAP/Active Directory if needed

For production use, configure an external database via the admin panel or edit /var/lib/openfire/conf/openfire.xml:

1
2
3
4
5
6
7
<connectionProvider>
    <className>org.jivesoftware.database.DefaultConnectionProvider</className>
    <driver>org.postgresql.Driver</driver>
    <serverURL>jdbc:postgresql://localhost:5432/openfire</serverURL>
    <username>openfire</username>
    <password>dbpassword</password>
</connectionProvider>

Choosing the Right Server for Your Use Case

Small Teams and Personal Use (Under 100 Users)

Pick: Prosody

Prosody’s minimal resource footprint and straightforward configuration make it the obvious choice for small deployments. It can run on a $5/month VPS or even a Raspberry Pi. The Lua configuration is readable and the module system lets you add features as needed without bloat.

Medium Organizations (100–5,000 Users)

Pick: OpenFire or ejabberd

OpenFire excels here if your team values a web-based admin console, LDAP integration, and a rich plugin ecosystem for features like file sharing plugins, monitoring dashboards, and custom authentication. ejabberd is better if you anticipate growth beyond 5,000 users and want clustering capabilities from day one.

Large-Scale and High-Availability (5,000+ Users)

Pick: ejabberd

No other XMPP server comes close to ejabberd’s proven ability to handle millions of concurrent connections. Its Erlang-based clustering, built-in load balancing, and battle-tested architecture make it the only realistic choice for carrier-grade deployments. Companies like WhatsApp and Facebook have used ejabberd-derived technology at massive scale.

Development and Testing

Pick: Prosody

Prosody’s fast startup time and low overhead make it ideal for CI/CD pipelines, automated testing, and development environments. You can spin up a fully functional XMPP server in seconds.

Security Best Practices

Regardless of which server you choose, follow these security fundamentals:

  1. Always enable TLS — require STARTTLS for both client-to-server and server-to-server connections
  2. Use valid certificates — Let’s Encrypt or your own CA; never use self-signed certs in production
  3. Enable SASL authentication — prefer SCRAM-SHA-256 over PLAIN
  4. Configure rate limiting — protect against brute-force login attacks
  5. Keep software updated — all three servers have active security teams
  6. Enable OMEMO — for end-to-end encrypted messaging
  7. Restrict registration — disable open registration unless you run a public server
  8. Monitor logs — set up log aggregation to detect unusual patterns

For related reading, check out our guide on self-hosted email servers with Rspamd for complementary communication infrastructure, and our comparison of Matrix vs XMPP to understand how the two federated messaging protocols compare. If you also need voice communication, see our Mumble vs TeamSpeak comparison for VoIP alternatives that integrate well with XMPP deployments.

FAQ

What is XMPP and how does it differ from Matrix?

XMPP (Extensible Messaging and Presence Protocol) is a decentralized messaging standard based on XML that has existed since 1999. Matrix is a newer open protocol (2014) using JSON and a different architecture. Both support federation, end-to-end encryption, and self-hosting. XMPP has a larger existing ecosystem of clients and servers, while Matrix has more modern features like full message history synchronization across devices. Many organizations run both.

Can XMPP servers communicate with each other?

Yes. XMPP is a federated protocol, meaning any XMPP server can communicate with any other XMPP server on the internet. This works similarly to email — if you run user@yourdomain.com, you can message friend@otherdomain.com as long as both servers have server-to-server (S2S) connections enabled. Federation is enabled by default in ejabberd, Prosody, and OpenFire.

Is XMPP secure enough for enterprise use?

Absolutely. XMPP supports TLS for transport encryption and OMEMO (OMEMO Multi-End Message and Object Encryption) for end-to-end encryption, providing security comparable to Signal. Major enterprises and government agencies use XMPP for secure internal communication. All three servers in this guide support STARTTLS, SASL authentication, and certificate-based security.

Which XMPP server uses the least resources?

Prosody is the lightest by a significant margin. A basic Prosody installation typically uses 20-80 MB of RAM and minimal CPU. ejabberd follows at 50-200 MB, and OpenFire requires the most resources at 512 MB+ due to its Java runtime. For a small team on a budget VPS, Prosody is the clear winner.

Can I migrate users between different XMPP servers?

Direct migration is possible but requires careful planning. User accounts, rosters, and message archives need to be exported from the old server and imported into the new one. ejabberd and OpenFire both support account export/import tools. For large migrations, you can also use XMPP’s account migration XEP (XEP-0244) if both servers support it. Alternatively, you can temporarily run both servers in parallel and let users gradually switch over.

Do these servers support group chat?

Yes, all three support XMPP Multi-User Chat (MUC, XEP-0045), which provides persistent chat rooms with moderation, invitation, and archiving capabilities. ejabberd and OpenFire also offer MUC clustering for distributed room state across server nodes. Prosody supports MUC through its built-in muc module with persistent room storage.

Advertise here