Loading...
 

How to install Prosody using Tiki for its userlist


Prosody is a lightweight and modular XMPP (Jabber) server.

This page describes how an instance of Prosody can be set up in such a way that it will make use of the Tiki database as its identity provider (IdP) for:

  • Users
  • Groups
  • Authentication


It also shows how to expose anonymous chat for visitors (via Converse.js), and auto-join registered Tiki users to specific group chatrooms.

Note that this is a specialized setup, and comes with some challenges.


Preparation / Assumptions

  • A working instance of Tiki is available. This guide assumes Tiki stores its own users, groups and permissions in its database (default). It has not been tested with setups using LDAP, Shibboleth, etc.
  • Prosody is installed on GNU/Linux (Debian/Ubuntu recommended).

Screenshot From 2025 09 21 09 34 22

  • Domains used in this guide:
    • xmpp.example.org → registered users (authenticated via Tiki)
    • guest.example.org → anonymous visitors
    • conference.example.org → MUC component (group chatrooms)
  • DNS (A/AAAA + SRV) and Let’s Encrypt certificates are set up for these hosts.
  • An administrative account in Tiki is available.


1) Install Prosody


Obtain and install Prosody from your package manager or the official repository.

  • Debian/Ubuntu:
bash
sudo apt update sudo apt install prosody sudo systemctl enable --now prosody


Verify installation:

bash
sudo prosodyctl check config sudo prosodyctl about


Always restart after editing:

bash
sudo systemctl restart prosody sudo systemctl status prosody

1.1. Install community modules (for HTTP auth)


Prosody’s HTTP auth comes from the community module mod_auth_http (community modules repo).

bash
# Common prerequisites (adjust to your distro): sudo apt install lua-sec mercurial -y # Clone community modules (place under /usr/local/lib/prosody) sudo mkdir -p /usr/local/lib/prosody cd /usr/local/lib/prosody sudo hg clone https://hg.prosody.im/prosody-modules/ modules # Alternative (git mirror) # sudo git clone https://github.com/bjc/prosody-modules /usr/local/lib/prosody/modules


In /etc/prosody/prosody.cfg.lua add:

text
plugin_paths = { "/usr/local/lib/prosody/modules" }


This enables authentication = "http" later.


2) TLS Certificates


Using Let’s Encrypt for production:

bash
sudo apt install certbot -y sudo certbot certonly --standalone \ -d xmpp.example.org \ -d guest.example.org \ -d conference.example.org # Import certificates into Prosody’s cert store sudo prosodyctl --root cert import /etc/letsencrypt/live


If your Tiki site is already running under Apache, you can also request and install the certificate using the Apache plugin:

bash
sudo apt update sudo apt install python3-certbot-apache -y sudo certbot --apache -d tiki.example.org -d www.tiki.example.org


Verify:

bash
sudo prosodyctl check certs


Expected output:

  • Certificate found for xmpp.example.org
  • Certificate found for guest.example.org
  • Certificate found for conference.example.org


More details: Prosody Certificate Documentation


3) Enable required modules


In /etc/prosody/prosody.cfg.lua under modules_enabled add the useful modules:

lua
-- Prosody Configuration File -- Complete working configuration with Tiki HTTP auth and Push notifications -- Last updated: 2026-02-13 plugin_paths = { "/usr/local/lib/prosody/modules" } admins = { "admin@xmpp.example.org" } modules_enabled = { -- Core "disco"; -- Service discovery "roster"; -- User rosters "saslauth"; -- Authentication "tls"; -- TLS support -- Essential "blocklist"; -- User blocklists "bookmarks"; -- Groupchat bookmarks "carbons"; -- Message carbons for multi-device "dialback"; -- S2S dialback "limits"; -- Bandwidth limiting "pep"; -- Personal Eventing Protocol "private"; -- Private XML storage "smacks"; -- Stream Management "vcard4"; -- vCard4 "vcard_legacy"; -- Legacy vCard -- Nice to have "csi_simple"; -- Client State Indication "invites"; -- Invites system "invites_adhoc"; -- Ad-hoc invites "invites_register"; -- Invite-based registration "ping"; -- XMPP Ping "time"; -- Entity Time "uptime"; -- Server uptime "version"; -- Server version "mam"; -- Message Archive Management -- HTTP "bosh"; -- BOSH "websocket"; -- WebSockets -- Admin "admin_adhoc"; -- Ad-hoc admin commands "admin_shell"; -- Shell admin -- PUSH NOTIFICATIONS (XEP-0357) - CRITICAL FOR MOBILE CLIENTS "push"; -- XEP-0357: Push Notifications "cloud_notify"; -- Modern push implementation for iOS/Android } modules_disabled = { -- "offline"; -- Uncomment if you want to disable offline storage -- "c2s"; -- Uncomment to disable client connections -- "s2s"; -- Uncomment to disable server-to-server } pidfile = "/run/prosody/prosody.pid" s2s_secure_auth = true limits = { c2s = { rate = "10kb/s" }; s2sin = { rate = "30kb/s" }; } archive_expires_after = "1w" -- 1 week message retention log = { debug = "/var/log/prosody/prosody.debug"; info = "/var/log/prosody/prosody.log"; error = "/var/log/prosody/prosody.err"; { levels = { "error" }; to = "syslog" }; } certificates = "/etc/prosody/certs" ----------- Network ----------- interfaces = { "0.0.0.0" } http_interfaces = { "0.0.0.0" } https_interfaces = { "0.0.0.0" } c2s_interfaces = { "0.0.0.0" } s2s_interfaces = { "0.0.0.0" } http_ports = { 5280 } https_ports = { 5281 } s2s_require_encryption = true consider_websocket_secure = true -- Global SSL https_ssl = { key = "/etc/letsencrypt/live/xmpp.example.org/privkey.pem"; certificate = "/etc/letsencrypt/live/xmpp.example.org/fullchain.pem"; } ----------- VirtualHost: Registered Users (Tiki HTTP Auth) ----------- VirtualHost "xmpp.example.org" ssl = { key = "/etc/letsencrypt/live/xmpp.example.org/privkey.pem"; certificate = "/etc/letsencrypt/live/xmpp.example.org/fullchain.pem"; } authentication = "http" http_auth_url = "https://tiki.example.org/tiki-xmpp-auth.php" http_auth_credentials = "prosody:REPLACE_WITH_YOUR_SECRET_HERE" c2s_require_encryption = true allow_unencrypted_plain_auth = false sasl_mech_list = { "PLAIN" } disco_items = { { "conference.example.org" } } -- PUSH NOTIFICATION SERVICE - REQUIRED FOR MONAL cloud_notify_push_service = "push.xmpp.example.org" ----------- VirtualHost: Anonymous Visitors ----------- VirtualHost "guest.example.org" authentication = "anonymous" ssl = { key = "/etc/letsencrypt/live/xmpp.example.org/privkey.pem"; certificate = "/etc/letsencrypt/live/xmpp.example.org/fullchain.pem"; } c2s_require_encryption = true allow_registration = false ----------- MUC Component ----------- Component "conference.example.org" "muc" ssl = { key = "/etc/letsencrypt/live/xmpp.example.org/privkey.pem"; certificate = "/etc/letsencrypt/live/xmpp.example.org/fullchain.pem"; } restrict_room_creation = false modules_enabled = { "muc_mam" } muc_room_default_persistent = true muc_room_default_public = true muc_room_default_members_only = false muc_room_default_allow_anonymous = true muc_room_default_history_length = 20 muc_max_history_messages = 100 muc_tombstones = true ----------- PUSH COMPONENT - CRITICAL FOR iOS/MONAL ----------- Component "push.xmpp.example.org" "cloud_notify" ssl = { key = "/etc/letsencrypt/live/xmpp.example.org/privkey.pem"; certificate = "/etc/letsencrypt/live/xmpp.example.org/fullchain.pem"; } -- CRITICAL: DO NOT USE CUSTOM APP ID -- Monal uses ITS OWN Apple Push Certificate -- The ONLY app_id that works with Monal is: app_id = "im.monal.monal" -- Optional: Add app_secret if required by your setup -- app_secret = "your-secret-here" ----------- Include additional configs ----------- Include "conf.d/*.cfg.lua"


⚠️ Note: muc and muc_mam are not enabled globally here — they must be loaded in a Component block.


4) VirtualHosts, MUC & Push Components


Prosody requires explicit VirtualHost and Component definitions for different roles:

Role Domain Purpose
Registered users xmpp.example.org Tiki HTTP authentication
Anonymous visitors guest.example.org Converse.js anonymous chat
Group chat conference.example.org MUC rooms with history
Push notifications push.xmpp.example.org XEP-0357 for iOS/Monal


FULL CONFIGURATION AVAILABLE IN SECTION 3

The complete configuration block above (section 3) contains ALL required elements:

  • VirtualHost xmpp.example.org avec cloud_notify_push_service
  • VirtualHost guest.example.org pour anonymes
  • Component conference.example.org pour MUC
  • Component push.xmpp.example.org avec app_id = "im.monal.monal" ⚠️ CRITICAL


Validation :

bash
sudo prosodyctl check config sudo systemctl restart prosody sudo prosodyctl mod_list xmpp.example.org # Doit afficher push, cloud_notify


Push verification :

bash
sudo tail -f /var/log/prosody/prosody.log | grep -i push # Expected: component 'push.xmpp.example.org' loaded


5) Tiki HTTP auth endpoint


Tiki provides tiki-xmpp-auth.php, responding to /check_password and /user_exists for Prosody’s mod_auth_http.

5.1 Web server requirements (Apache)


Make sure Apache forwards the Authorization header to PHP (this is essential if you use HTTP Basic auth). Add these lines inside the <VirtualHost> or in the <Directory> that serves tiki-xmpp-auth.php:
sudo nano /etc/apache2/sites-enabled/example.org.conf

apache
# Ensure Apache forwards the Authorization header to PHP SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 CGIPassAuth On <Directory /home/prosody/public_html> Options -Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch Require all granted # Forward Authorization header SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 CGIPassAuth On </Directory>


Reload Apache:

bash
sudo apache2ctl configtest && sudo systemctl reload apache2


Generate a secure random secret and store it in /etc/prosody/xmpp_http_secret (Prosody and Tiki will use it). Example:

bash
# Generate secret (40 chars, safe characters) and secure it sudo sh -c 'head -c32 /dev/urandom | base64 | tr -d /=+ | cut -c1-40 > /etc/prosody/xmpp_http_secret' sudo chown root:prosody /etc/prosody/xmpp_http_secret sudo chmod 640 /etc/prosody/xmpp_http_secret # Show the secret (as root) to copy it for Prosody config / Tiki settings: sudo cat /etc/prosody/xmpp_http_secret


Important: do not expose this secret in public logs or commit it to git.

5.3 Configure Prosody with that secret (preferred: Basic Auth header)


Set http_auth_credentials in Prosody to prosody:THESECRET (this makes Prosody send an Authorization: Basic ... header). Example:

lua
-- replace REPLACE_WITH_SECRET with the secret content from /etc/prosody/xmpp_http_secret http_auth_credentials = "prosody:XXXXXYYYYYYZZZZ"


Restart Prosody:

bash
sudo systemctl restart prosody

5.4 Configure Tiki (tiki-xmpp-auth.php)


The Tiki tiki-xmpp-auth.php script accepts either:

  • HTTP Basic Auth ( Authorization: Basic ... ) with username prosody and password equal to the shared secret, or
  • the query/post parameter secret=... (less preferred; avoids exposing secret in URLs when possible).


Make sure the Tiki site preference xmpp_shared_secret (if used) matches the file /etc/prosody/xmpp_http_secret, or rely on the file secret logic in the script.

5.5 Quick diagnostics (curl)

bash
# Check endpoint reachable (without auth you may get 403) curl -I "https://tiki.example.org/tiki-xmpp-auth.php" # Using Basic auth (preferred) SECRET=$(sudo cat /etc/prosody/xmpp_http_secret) curl -v -u "prosody:${SECRET}" \ "https://tiki.example.org/tiki-xmpp-auth.php/check_password?user=admin&pass=THEPASSWORD" # Using ?secret= (less recommended) curl -v "https://tiki.example.org/tiki-xmpp-auth.php/check_password?user=admin&pass=THEPASSWORD&secret=${SECRET}"


Expected output for valid credentials: true (plain text) for the /check_password call.

If you see 403 or false, check:

  • Apache SetEnvIf Authorization + CGIPassAuth presence
  • That Prosody is actually sending Basic auth (check Prosody logs)
  • That the secret used by Prosody and Tiki matches exactly


6) Converse.js configuration (in Tiki)


Admin → XMPP → ConverseJS Extra Settings (example):
Minimal configuration example:

Basic configuration
{ "discover_connection_methods": false, "keepalive": true, "persistent_store": "localStorage", "debug": true }
  • sessionStorage avoids harmless warnings about session restore during testing.


To allow anonymous visitors to automatically join chat rooms with auto-generated nicknames set muc_nickname_from_jid to true

converseJS Extra Settings
{ "websocket_url": "wss://xmpp.example.org/xmpp-websocket", "persistent_store": "sessionStorage", }


Optional XEP-0156 discovery (useful if you let Converse discover endpoints):

xml
# /var/www/xmpp/.well-known/host-meta <?xml version='1.0' encoding='utf-8'?> <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0'> <link rel="urn:xmpp:alt-connections:xbosh" href="https://xmpp.example.org:5281/http-bind" /> <link rel="urn:xmpp:alt-connections:websocket" href="wss://xmpp.example.org:5281/xmpp-websocket" /> </XRD>


Permissions :

server
sudo chown -R www-data:www-data /var/www/xmpp sudo chmod -R 755 /var/www/xmpp


Apache snippet (/etc/apache2/sites-enabled/olivierkango.com.conf) :

apache
# Prevent reverse-proxy from eating .well-known ProxyPass /.well-known ! Alias /.well-known/ /var/www/xmpp/.well-known/ <Directory /var/www/xmpp/.well-known> Options -Indexes AllowOverride None Require all granted Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods "GET, OPTIONS" Header set Access-Control-Allow-Headers "Content-Type" </Directory>

Required logs (for troubleshooting):

logs
# real time access log sudo tail -f /var/log/virtualmin/example.org_access_log # real time prosody log sudo tail -f /var/log/prosody/prosody.log # real time apache error log sudo tail -f /home/prosody/logs/php_log # real time error log sudo tail -f /var/log/virtualmin/example.org_error_log # prosody infos log sudo journalctl -u prosody -f


7) Test endpoints

bash
curl -vk https://xmpp.example.org:5281/http-bind curl -vk https://xmpp.example.org:5281/xmpp-websocket


Expected:

  • BOSH: HTML page Prosody BOSH endpoint – It works
  • WebSocket: HTTP/1.1 101 Switching Protocols


8) XMPP rooms and Gajim


This section explains how chat rooms are created and used, based on real use cases.

Room creation model
Chat rooms are not created manually in advance.
Rooms are created automatically on first join by Prosody (MUC), based on:

  • the room JID
  • the configured MUC domain
  • the auto-join logic from Tiki or the XMPP client


Defined rooms

  • Community room (anonymous + registered users): community@conference.example.com
  • Support room (anonymous support): support@conference.example.com
  • Registered users room: registered@conference.example.com
  • Translators room: translators@conference.example.com


Registered users behaviour (Bob, Charlie, Dan)

  • When a user logs into Tiki:
    • he is authenticated to XMPP via HTTP auth
    • he is auto-joined to rooms based on Tiki groups

Examples:

  • Bob (group: Registered) → auto-joined to registered@conference.example.com
  • Charlie (group: Translators) → auto-joined to translators@conference.example.com
  • Dan (external XMPP account configured in Tiki profile) → joins the same rooms based on group mapping


Admin / support workflow (Eve)
Eve uses Gajim instead of the web interface. Add admin account in Gajim

Gajim — manual account settings
JID: admin@xmpp.example.com Password: admin’s Tiki password Server override: Host: xmpp.example.com Port: 5222 Encryption: StartTLS (Require TLS) Auth method: PLAIN Verify server certificate: ON



How Eve creates or joins rooms
Rooms are created simply by joining them.

Gajim
Gajim → + → Join Group Chat Room: support Server: conference.example.com

This creates (if not already created): support@conference.example.com
Eve stays online in this room to answer anonymous visitors.

Anonymous visitors behaviour (Alice)

  • Alice visits the Tiki site
  • Converse.js opens automatically
  • Based on configuration:
    • community use case → joins community@conference.example.com
    • support use case → joins support@conference.example.com

Eve receives messages in Gajim in real time.


Add registered account in Gajim (use admin, not Eve)

Gajim — manual account settings
- JID: admin@xmpp.example.org - Password: (admin’s Tiki password OR the local prosody password if you created one) - Resource: optional (e.g. AdminLaptop) Server (override) - Host: xmpp.example.org - Port: 5222 - Encryption: StartTLS (Require TLS) - Auth method / SASL: PLAIN - Verify server certificate: ON (unless testing with self-signed cert) Notes: - If DNS SRV records are correct you can skip Host override and let the client use the domain. - Only use SASL PLAIN over an encrypted (TLS) connection.


Troubleshooting checklist (brief)

  • Ensure Apache forwards Authorization header (SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 + CGIPassAuth On).
  • Ensure Prosody virtualhost uses auth http and sends credentials ( http_auth_url + http_auth_credentials or http_auth_user/http_auth_password).
  • Confirm certificate names match hostnames and client uses TLS.
  • Check Prosody logs ( /var/log/prosody/prosody.log ) and Tiki PHP log for the debug lines.


-- end of Gajim section (use admin@xmpp.example.org credentials)


9) Configure Tiki (Admin → XMPP)

Section Preference Example value
Common (Openfire & Prosody) XMPP MUC Domain conference.example.org
XMPP BOSH URL (http-bind) https://xmpp.example.org:5281/http-bind/
XMPP WebSocket URL wss://xmpp.example.org:5281/xmpp-websocket
Prosody (HTTP Auth) XMPP domain for registered users xmpp.example.org
XMPP domain for anonymous visitors guest.example.org
Anonymous visitor mode Community room
Default anonymous chat room community@conference.example.com
Anonymous support room support@conference.example.com
Default registered chat room registered@conference.example.org
Mapping Tiki groups to chat rooms { "Registered": "registered@conference.example.org", "Translators": "translators@conference.example.org" }
Auto-join strategy by-groups (recommended)
XMPP shared secret (HTTP auth) (same secret as in Prosody config or leave blank and use file `/etc/prosody/xmpp_http_secret`)
CORS allowed origins (comma-separated) https://tiki.example.org
ConverseJS options (common) Always Load ConverseJS Enable ✅
ConverseJS Debug Mode Enable only for debugging
ConverseJS Extra Settings {"discover_connection_methods": false, "keepalive": true, "persistent_store": "localStorage", "debug": true}


Then, in the wiki page, add the XMPP plugin for the room you want to use (depending on the case):

wiki
{xmpp room="Support"} # or {xmpp room="Registered"} # or {GROUP(groups="Translators")} {xmpp room="Translators"} {GROUP}


Note: Anonymous users will always be automatically projected into the Support room, regardless of which plugin is configured on the page.


10) Pitfalls & troubleshooting

10.1 Firewall (firewalld / nftables) — COMMON BLOCKER


Failed
This is the #1 real-world cause of “No route to host” when Prosody is running correctly.
From a remote machine:

nc -vz xmpp.example.org 5222

Result: nc: connect to xmpp.example.org port 5222 failed: No route to host
Even though on the server: ss -lntp | grep 5222 Shows: LISTEN 0.0.0.0:5222

How to detect firewalld
Run on the server:

systemctl status firewalld

If you see: active (running) Then firewalld IS ACTIVE, even if ufw is not installed. You can also confirm with: nft list ruleset
If you see: table inet firewalld { firewalld is enforcing rules via nftables.

Default problem
By default, the public zone does NOT allow XMPP ports.

Typical allowed ports:

  • 22 (SSH)
  • 80 / 443 (HTTP/HTTPS)
  • mail ports


x Missing:

  • 5222 (XMPP client)
  • 5269 (server-to-server)
  • 5280 / 5281 (BOSH / WebSocket)


FIX — Open XMPP ports properly (RECOMMENDED)
Run one by one as root:

server side
firewall-cmd --permanent --add-port=5222/tcp firewall-cmd --permanent --add-port=5269/tcp firewall-cmd --permanent --add-port=5280/tcp firewall-cmd --permanent --add-port=5281/tcp firewall-cmd --reload


Verify: firewall-cmd --list-ports Expected: 5222/tcp 5269/tcp 5280/tcp 5281/tcp

Mandatory verification (from another machine)

from local machine
nc -vz xmpp.example.org 5222

Expected: Connection to xmpp.example.org 5222 port tcp/xmpp-client succeeded!

Only after this succeeds should you configure Gajim or Converse.js.


10.2 ⚠️ SSL certificate expired but still used by Prosody


Certification Expired

Problem:
When connecting with Gajim, an SSL error appears:
The certificate has expired

Clicking on View Certificate crashes Gajim with:

AttributeError: 'NoneType' object has no attribute 'connect'


Cause:

  • Important: Let's Encrypt certificates expire every 90 days.
  • The server was presenting an expired certificate
  • A new certificate was generated by Let's Encrypt
  • Prosody was still using the old one (loaded in memory)


Diagnosis:

# 1. Check certificate on disk sudo openssl x509 -in /etc/letsencrypt/live/xmpp.example.org/fullchain.pem -noout -dates # 2. Try to renew (shows if renewal is possible) sudo certbot renew # 3. Check what the server actually sends echo | openssl s_client -connect xmpp.example.org:5222 -starttls xmpp -servername xmpp.example.org 2>/dev/null | openssl x509 -noout -dates # 4. Compare results: # - If disk certificate is valid but server sends expired → Prosody needs restart # - If both are expired → renew certificate first


Fix:
Force Prosody to reload the new certificate:

sudo systemctl stop prosody sudo systemctl start prosody


Prevention :

To avoid this issue in the future, create a Certbot deploy hook that automatically imports certificates into Prosody after each renewal. This is the method recommended by the official Prosody documentation: https://prosody.im/doc/letsencrypt

sudo nano /etc/letsencrypt/renewal-hooks/deploy/prosody.sh


Content:

#!/bin/sh /usr/bin/prosodyctl --root cert import /etc/letsencrypt/live


Make it executable:

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/prosody.sh


11) Simple and Reliable Solution (XMPP SEO Blocking)


Objective
Permanently block the xmpp. and guest. subdomains at the server (Apache) level to prevent any SEO indexing.

  • Step 1 — Open the terminal__ Via: - Virtualmin → Terminal or - SSH
  • Step 2 — Create the blocking VirtualHost Run exactly: sudo nano /etc/apache2/sites-available/blocked-subdomains.conf
  • Step 3 — Paste the following content (important)
apache
<VirtualHost *:80> ServerName xmpp.example.org ServerAlias guest.example.org DocumentRoot /var/www/empty <Directory /var/www/empty> Require all granted </Directory> Header set X-Robots-Tag "noindex, nofollow" </VirtualHost>

Save the file: - CTRL + O → Enter, CTRL + X

  • Step 4 — Create the empty directory

sudo mkdir -p /var/www/empty
sudo chown -R www-data:www-data /var/www/empty

  • Step 5 — Enable Apache headers module (if needed): sudo a2enmod headers
  • Step 6 — Enable the site and reload Apache
sudo a2ensite blocked-subdomains.conf sudo systemctl reload apache2


Immediate test (critical)
Open in your browser:


Expected result

  • Empty page or default Apache page
  • No Tiki content
  • No indexable content


If this is the case, the SEO issue is resolved at ~90%.

Others Pitfalls & troubleshooting

  • 🔐 Firewall: open 5222, 5269, 5280, 5281 as needed.
  • 📜 Certificates mismatch: point all vhosts/components to a valid cert pair.
  • 🚫 Room creation restricted: set restrict_room_creation = false (or handle via admin).
  • 👻 Duplicate anonymous nicknames: expected on reload; let Converse generate unique nicks.
  • Apache drops Authorization: add SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 and CGIPassAuth On in the vhost.
  • 🔒 Do not pass secret in URL in production: prefer Basic auth so secret is sent in Authorization header and not logged in server logs.
  • ⚠️ SASL warning (PLAIN forbidden on insecure): enable c2s_require_encryption = true and connect via HTTPS BOSH/WebSocket.
  • 🧹 Converse “_restore: no restoreable session”: benign; clear cache or use sessionStorage.
  • 🛂 Admin not-authorized in logs: ensure the XMPP Admin in Tiki is a real Tiki user and the password matches; do not rely on prosodyctl register for HTTP-auth vhosts.


User Stories

  • Alice (anonymous visitor): She is not registered. She sees the Converse.js pop up and she asks a question.
  • Bob (registered user): Is automatically added to the Registered group and the associated chatroom.
  • Charlie (translator): Is also added to the Translators chatroom in addition to the Registered one.
  • Dan (geek): Uses his own external XMPP JID while still joining group chatrooms.
  • Eve (administrator): Uses Gajim (desktop XMPP client) to answer queries from anonymous visitors.


smile   At this point:

  • Converse.js can connect via BOSH or WebSocket
  • Anonymous visitors (guest.example.org) can chat
  • Registered users (xmpp.example.org) can join
  • Group chats are served by conference.example.org with message history