Setting up Prosody for mage party

Tags: #<Tag:0x00007f0fa5560c00> #<Tag:0x00007f0fa5560818> #<Tag:0x00007f0fa5560200>


Here are some notes on setting up the jabber server.

It is the smallest VPS at Digital Ocean, in an SF datacenter. I’ve never had issues with jabber latency, but that’s nearest me, so that’s my default. Ubuntu 18.04.

I followed the instructions at HOMEBREWSERVER.CLUB

I used a cloud firewall, so in addition to the ports listed, I also needed to open up port 80 for certbot to work.

Something strange about that tutorial… I think the file shown in the post is different than the one I copied and modified a few days ago. Huh. Anyhow, here is mine:

-- a custom prosody 0.11 config focused on high security and ease of use across (mobile) clients
-- provided to you by the
-- the original config file (prosody.cfg.lua.original) will have more information 

admins = { "" }

plugin_paths = { "/usr/src/prosody-modules" } -- non-standard plugin path so we can keep them up to date with mercurial

modules_enabled = {
                "roster"; -- Allow users to have a roster. Recommended ;)
                "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
                "tls"; -- Add support for secure TLS on c2s/s2s connections
                "dialback"; -- s2s dialback support
                "disco"; -- Service discovery
                "private"; -- Private XML storage (for room bookmarks, etc.)
                "vcard4"; -- User Profiles (stored in PEP)
                "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
                "version"; -- Replies to server version requests
                "uptime"; -- Report how long server has been running
                "time"; -- Let others know the time here on this server
                "ping"; -- Replies to XMPP pings with pongs
                "register"; --Allows clients to register an account on your server
                "pep"; -- Enables users to publish their mood, activity, playing music and more
                "carbons"; -- XEP-0280: Message Carbons, synchronize messages accross devices
                "smacks"; -- XEP-0198: Stream Management, keep chatting even when the network drops for a few seconds
                "mam"; -- XEP-0313: Message Archive Management, allows to retrieve chat history from server
                "csi_simple"; -- XEP-0352: Client State Indication
                "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
                "blocklist"; -- XEP-0191  blocking of users
                "bookmarks"; -- Synchronize currently joined groupchat between different clients.
                "server_contact_info"; --add contact info in the case of issues with the server
                "cloud_notify"; -- Support for XEP-0357 Push Notifications for compatibility with ChatSecure/iOS.
                -- iOS typically end the connection when an app runs in the background and requires use of Apple's Push servers to wake up and receive a message. Enabling this module allows your server to do that for your contacts on iOS.
                -- However we leave it commented out as it is another example of vertically integrated cloud platforms at odds with federation, with all the meta-data-based surveillance consequences that that might have.

allow_registration = false; -- Enable to allow people to register accounts on your server from their clients, for more information see

certificates = "/etc/prosody/certs" -- Path where prosody looks for the certificates see:

https_certificate = "certs/"

c2s_require_encryption = true -- Force clients to use encrypted connections

-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
-- with to support encryption AND present valid, trusted certificates.
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see

s2s_secure_auth = true

pidfile = "/var/run/prosody/"

authentication = "internal_hashed"

-- Archiving
-- If mod_mam is enabled, Prosody will store a copy of every message. This
-- is used to synchronize conversations between multiple clients, even if
-- they are offline. This setting controls how long Prosody will keep
-- messages in the archive before removing them.

archive_expires_after = "1w" -- Remove archived messages after 1 week

--log = { --disable for extra privacy
--        info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
--        error = "/var/log/prosody/prosody.err";
--       "*syslog";

-- add contact information for other server admins to contact you about issues regarding your server
-- this is particularly important if you enable public registrations
contact_info = { 
  admin = { "", "" };
  abuse = { "" };

VirtualHost ""

-- Enable http_upload to allow image sharing across multiple devices and clients
Component "" "http_upload"

http_max_content_size = 10485760;
http_upload_file_size_limit = 10485760;

---Allow setting up groupchats on this subdomain:
Component "" "muc"
modules_enabled = { "muc_mam", "vcard_muc" } -- enable archives and avatars for group chats

-- Set up a file transfer proxy to facilitate clients sending larger files to each other
Component "" "proxy65"

The uploads are in bytes, and @trashHeap shared with me that multiplying your MB value with 1024*1024 gets the correct value (in our case 10485760 = 10*1024*1024).

I’m gonna go through and fine tune that, but for now it works as expected. :slight_smile:

Make Prosody config generator

I need to read up on the disco module. You don’t look like your passing any configuration to it. Whereas I am. I may not need to, though. I had some difficulty with getting MUC discoverable, but I also found some configuration errors in the advice I was using (I think due to a prosody version missmatch). Now that those configurations are gone, I might wanna try pulling the extra configuration im passing to the disco module.

I thought I might need disco confiuration items, because my services are nested two subdomains deep as opposed to one. However Im doubting it in retrospect.

My whole setup is working, but every child service is kind of vocally advertising all other services. So when you use a tool to browse the XMPP services it can look recursive. It doesn’t break anything per se; but looks sloppy.


Okay, I was equally surprised, because my config never contained the disco services stanza in the tutorial config.

I bet it defaults smartly, and just picks up services as stated.

I also need to read up on it. And now we can, together, since #mage-party is pur jabber forum! :slight_smile:


From mod_disco – Prosody IM

mod_disco implements XEP-0030. Some modules automatically add their service details such as mod_register and mod_proxy65. Additional disco items can be added using the configuration option in Prosody 0.7 and later.

The details for what it are sparse, though. I think we could contribute by cleaning these up once and for all, a lot of the Prosody docs say enough to get going, but rarely list all possible options.

Anyhow, I’d let it automatically add your services, @trashHeap, and see what happens. Make sure to reboot server and log out of clients to test!


Lessons learned:

  1. mod_disco is needed if your services are nested an additional subdomain deep. The auto discovery just doesn’t work unless their directly below the host’s domain.
  2. the disco_items configuration block needs to be nested under your main virtualhost entry to avoid the recursive behavior im seeing. Which makes a kind of sense. In the global block applies configuration to every virtualhost and component. So I was telling every component to advertise itself and all other components.
  3. I found prosody documentation unclear that disco_items was supported outside of the global configuration. Stumbling across this bug helped me reach an “ah ha” moment. #1080 mod_discoitems: overrides for all domains if loaded globally (open) - Prosody IM Issue Tracker ; Maybe this is more obvious if one is more well versed in lua.

NOTE: I mainly did the subdomain of a subdomain thing because I was JIDs to be from the root domain but my domain may host additional services in the future. I wanted to avoid possible future conflicts with other services.