Introduction
Prosody is a modern and well-known xmpp server written in Lua. This tutorial will help you to deploy a state of the art xmpp server which passes all test in the compliance tester but also has some further tweaks.
In this tutorial the latest ("trunk") version is used. It has the most features and it is quite stable.
If you are behind a firewall which only allows some single ports please follow the advanced guide at the bottom.
We will also minimize the metadata and logfiles being stored for privacy reasons.
What you will need at least:
- A small virtual (cloud) server
- A own domain (example.com in this tutorial)
- Basic knowledge about Linux
Assumptions
All commands are executed by default as root user.
You should have a basic installation and SSH access. Make sure your SSH login is secured.
We do not setup any firewall in this tutorial. After the installation you can find open ports with netstat -tulpen
and restrict them if you want.
The server will be for real on xmpp.example.com. The XMPP-IDs are still user@example.com
.
To make it easier later we will also point example.com to the server. You do not have to do this, just note the steps during certificate creation.
Example terminology
- Server IPv4:
10.0.0.1
- Server IPv6:
2001:db8:1234::1
- XMPP-ID (username):
holu
. - File Upload:
xmpp.example.com
- MUC (Multi User Chat):
conference.example.com
(others also usemuc.
orchat.
) - Pubsub:
pubsub.example.com
- Proxy:
proxy.example.com
- User Directory (VJUD):
vjud.example.com
- Email addresses or aliases:
abuse@example.com
,support@example.com
,security@example.com
- Admin email address:
holu@example.com
Step 1 - Setup DNS Records
Setup following DNS records:
example.com. 7200 IN A 10.0.0.1
example.com. 7200 IN AAAA 2001:db8:1234::1
xmpp.example.com. 7200 IN A 10.0.0.1
xmpp.example.com. 7200 IN AAAA 2001:db8:1234::1
conference.example.com. 7200 IN A 10.0.0.1
conference.example.com. 7200 IN AAAA 2001:db8:1234::1
pubsub.example.com. 7200 IN A 10.0.0.1
pubsub.example.com. 7200 IN AAAA 2001:db8:1234::1
proxy.example.com. 7200 IN A 10.0.0.1
proxy.example.com. 7200 IN AAAA 2001:db8:1234::1
vjud.example.com. 7200 IN A 10.0.0.1
vjud.example.com. 7200 IN AAAA 2001:db8:1234::1
_xmpp-client._tcp.example.com. 14400 IN SRV 5 1 5222 xmpp.example.com.
_xmpps-client._tcp.example.com. 14400 IN SRV 10 1 5223 xmpp.example.com.
_xmpp-server._tcp.example.com. 14400 IN SRV 5 0 5269 xmpp.example.com.
_xmpp-server._tcp.conference.example.com. 14400 IN SRV 10 10 5269 xmpp.example.com.
Step 2 - Installation
First we add the official repository to get the latest ("trunk") versions
wget https://prosody.im/files/prosody-debian-packages.key -O- | gpg --dearmor | tee /etc/apt/trusted.gpg.d/prosody.gpg
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | tee -a /etc/apt/sources.list.d/prosody.list
and then we install the latest build available. We also need gnupg, git and mercurial.
apt-get update && apt-get install prosody-trunk gnupg git mercurial
Do not forget to stop prosody for the moment.
prosodyctl stop
After that we will download the so called "community modules" which will add more super cow power to the xmpp server.
hg clone https://hg.prosody.im/prosody-modules/ /opt/prosody-modules
Prosody needs to be able to access the modules folder, therefore we need to change the owner of the directory.
chown root:prosody -R /opt/prosody-modules/
Now we add a cronjob to update the repository periodically:
First run crontab -e
and go down to the bottom of the file and create a new line. Paste the following line:
0 18 * * 2 cd /opt/prosody-modules && hg pull --update && chown root:prosody -R /opt/prosody-modules/
As we do not need all community modules and also some official modules still have old versions in the community repository we symlink all needed modules.
mkdir /opt/prosody-modules-enabled/ && cd /opt/prosody-modules-enabled/
(Click to expand) You can just paste the next lines into your command line
ln -s ../prosody-modules/mod_addressing/
ln -s ../prosody-modules/mod_auto_answer_disco_info/
ln -s ../prosody-modules/mod_bidi/
ln -s ../prosody-modules/mod_bob/
ln -s ../prosody-modules/mod_bookmarks/
ln -s ../prosody-modules/mod_cache_c2s_caps/
ln -s ../prosody-modules/mod_carbons_copies/
ln -s ../prosody-modules/mod_checkcerts/
ln -s ../prosody-modules/mod_cloud_notify/
ln -s ../prosody-modules/mod_csi_battery_saver/
ln -s ../prosody-modules/mod_default_bookmarks/
ln -s ../prosody-modules/mod_delay/
ln -s ../prosody-modules/mod_http_avatar/
ln -s ../prosody-modules/mod_http_upload/
ln -s ../prosody-modules/mod_idlecompat/
ln -s ../prosody-modules/mod_muc_limits/
ln -s ../prosody-modules/mod_muc_mam_hints/
ln -s ../prosody-modules/mod_presence_cache/
ln -s ../prosody-modules/mod_privacy_lists/
ln -s ../prosody-modules/mod_pubsub_feeds/
ln -s ../prosody-modules/mod_pubsub_text_interface/
ln -s ../prosody-modules/mod_smacks/
ln -s ../prosody-modules/mod_strict_https/
ln -s ../prosody-modules/mod_vcard_muc/
ln -s ../prosody-modules/mod_vjud/
ln -s ../prosody-modules/mod_watchuntrusted/
ln -s ../prosody-modules/mod_webpresence/
For best support when you later use the client AstraChat we also install mod_img2url:
git clone https://github.com/lixmal/mod_img2url.git /opt/external-prosody-modules/mod_img2url
ln -s ../external-prosody-mod/mod_img2url/mod_img2url.lua
Step 3 - Configuration
Time for the configuration file. Move the original configuration file away:
mv /etc/prosody/prosody.cfg.lua /etc/prosody/prosody.cfg.lua.old
Public registration is disabled by default, you can enable it if you remove the --
in front of the lines under VirtualHost "example.com"
.
Edit /etc/prosody/prosody.cfg.lua
and add the content below.
(Click to expand) prosody.cfg.lua
pidfile = "/var/run/prosody/prosody.pid"
default_storage = "internal"
storage = {
account_details = "none"
}
authentication = "internal_hashed"
admins = { "holu@example.com" }
contact_info = {
abuse = { "mailto:abuse@example.com", "xmpp:holu@example.com" };
admin = { "mailto:support@example.com", "xmpp:holu@example.com" };
security = { "mailto:security@example.com" };
support = { "mailto:support@example.com", "xmpp:support@conference.example.com" };
};
https_ssl = {
key = "/usr/lib/prosody/cert/xmpp.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/xmpp.example.com/fullchain.pem";
}
ssl = {
key = "/usr/lib/prosody/cert/example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/example.com/fullchain.pem";
}
legacy_ssl_ports = 5223
c2s_require_encryption = true;
s2s_require_encryption = true;
s2s_secure_auth = true;
consider_bosh_secure = true
http_default_host = "xmpp.example.com"
http_external_url = "https://xmpp.example.com/"
plugin_paths = { "/opt/prosody-modules-enabled" }
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
-- custom
"carbons"; -- Keep multiple clients in sync
"carbons_copies"; -- carbons for legacy clients
"mam"; -- Store messages in an archive and allow users to access it
"pep"; -- Enables users to publish their mood, activity, playing music and more
"private"; -- Private XML storage (for room bookmarks, etc.)
"default_bookmarks"; -- Default bookmarks for all users
"blocklist"; -- Allow users to block communications with other users
"privacy_lists";
"bookmarks"; -- Bookmarks for xmpp channels
"vcard4";
"vcard_legacy";
"http_avatar"; -- serves avatars from local users
"strict_https"; -- force https on web
"offline"; -- Store offline messages
"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
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
"bosh"; -- Enable BOSH clients, aka Jabber over HTTP
"watchregistrations"; -- Alert admins of registrations
"cloud_notify"; -- allows clients to register an app server which is notified about new messages while the user is offline
"legacyauth"; -- Legacy authentication. Only used by some old clients and bots
"announce"; -- Send announcement to all online users
"smacks"; -- allow a client to resume a disconnected session to prevent message loss
"csi"; -- https://modules.prosody.im/mod_csi.html
"csi_battery_saver"; -- Use less battery on mobile phones
"presence_cache"; -- stores a timestamp of the latest presence received from users contacts
"checkcerts"; -- Inform admins before certificates expire
"websocket"; -- Enable mod_websocket
"net_multiplex";
"server_contact_info"; -- contact info
"idlecompat";
"auto_answer_disco_info";
"bidi";
"addressing";
"webpresence";
"img2url";
"watchuntrusted"; -- notify on unencrypted s2s
-- debugging
-- "admin_telnet";
-- "rawdebug";
};
log = {
warn = "/var/log/prosody/prosody.log";
}
checkcerts_notify = 7 -- in days
registration_watchers = { "holu@example.com" } -- mod_watchregistrations will use this list of users instead of the admin list
registration_notification = "$username registered on $host"
untrusted_fail_watchers = { "holu@example.com" }
untrusted_fail_notification = "Establishing a secure connection from $from_host to $to_host failed. Certificate hash: $sha1. $errors"
default_bookmarks = {
{ jid = "support@conference.example.com", name = "Support Room" };
}
hsts_header = "max-age=31556952"
archive_expires_after = "4w" -- configure message archive
max_archive_query_results = 20;
mam_smart_enable = true
default_archive_policy = "roster" -- archive only messages from users who are in your roster
-- cloud_notify
push_notification_with_body = false -- Whether or not to send the message body to remote pubsub node
push_notification_with_sender = false -- Whether or not to send the message sender to remote pubsub node
push_max_errors = 5 -- persistent push errors are tolerated before notifications for the identifier in question are disabled
push_max_devices = 5 -- number of allowed devices per user
VirtualHost "example.com"
name = "Prosody"
modules_enabled = {
-- "register"; -- Allow users to register on this server using a client and change passwords
}
-- allow_registration = true
-- min_seconds_between_registrations = 900
http_host = "xmpp.example.com"
ssl = {
key = "/usr/lib/prosody/cert/example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/example.com/fullchain.pem";
}
disco_items = {
{ "example.com", "Prosody" };
{ "conference.example.com", "example.com chatrooms" };
{ "proxy.example.com" };
{ "vjud.example.com" };
}
-- multi user chat
Component "conference.example.com" "muc"
name = "example.com chatrooms"
restrict_room_creation = false
ssl = {
key = "/usr/lib/prosody/cert/conference.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/conference.example.com/fullchain.pem";
}
modules_enabled = {
"muc_mam"; -- message archive in muc
"muc_mam_hints";
"muc_limits";
"vcard_muc"; -- This module adds the ability to set vCard for MUC rooms.
"bob";
}
muc_log_by_default = true;
muc_log_all_rooms = false;
max_history_messages = 20;
Component "xmpp.example.com" "http_upload"
http_upload_path = "/opt/prosody_http_data"
http_upload_file_size_limit = 10485760 -- in bytes (10 MB)
http_upload_expire_after = 60 * 60 * 24 * 3 -- 3 days
http_upload_quota = 104857600 -- bytes max uploaded by one user (100 MB)
http_host = "xmpp.example.com"
ssl = {
key = "/usr/lib/prosody/cert/xmpp.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/xmpp.example.com/fullchain.pem";
}
-- pubsub
Component "pubsub.example.com" "pubsub"
modules_enabled = { "pubsub_feeds", "pubsub_text_interface" }
ssl = {
key = "/usr/lib/prosody/cert/pubsub.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/pubsub.example.com/fullchain.pem";
}
-- proxy
Component "proxy.example.com" "proxy65"
proxy65_address = "proxy.example.com"
name = "SOCKS5 Bytestreams Service"
ssl = {
key = "/usr/lib/prosody/cert/proxy.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/proxy.example.com/fullchain.pem";
}
-- vjud, user directory
Component "vjud.example.com" "vjud"
ssl = {
key = "/usr/lib/prosody/cert/vjud.example.com/privkey.pem";
certificate = "/usr/lib/prosody/cert/vjud.example.com/fullchain.pem";
}
Step 3.1 - Register Let's Encrypt Certificates
Note: If you have pointed example.com
to another IP address please generate the certificate for example.com
on the other server and copy it over with for example scp.
We will use certbot from EFF for the Let's Encrypt certificates.
apt-get install snapd
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d example.com
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d xmpp.example.com
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d conference.example.com
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d proxy.example.com
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d pubsub.example.com
certbot certonly --standalone --rsa-key-size 4096 -m holu@example.com -d vjud.example.com
You will get an email 30 (and 7) days before the certificates expire to holu@example.com. You will also get a notification via XMPP 7 days before the certificates expire.
Step 3.2 - Install the certificates
mkdir /usr/lib/prosody/cert/
mkdir /usr/lib/prosody/cert/example.com
cp -L /etc/letsencrypt/live/example.com/fullchain.pem /usr/lib/prosody/cert/example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/example.com/privkey.pem /usr/lib/prosody/cert/example.com/privkey.pem ;
mkdir /usr/lib/prosody/cert/xmpp.example.com
cp -L /etc/letsencrypt/live/xmpp.example.com/fullchain.pem /usr/lib/prosody/cert/xmpp.example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/xmpp.example.com/privkey.pem /usr/lib/prosody/cert/xmpp.example.com/privkey.pem ;
mkdir /usr/lib/prosody/cert/conference.example.com
cp -L /etc/letsencrypt/live/conference.example.com/fullchain.pem /usr/lib/prosody/cert/conference.example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/conference.example.com/privkey.pem /usr/lib/prosody/cert/conference.example.com/privkey.pem ;
mkdir /usr/lib/prosody/cert/proxy.example.com
cp -L /etc/letsencrypt/live/proxy.example.com/fullchain.pem /usr/lib/prosody/cert/proxy.example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/proxy.example.com/privkey.pem /usr/lib/prosody/cert/proxy.example.com/privkey.pem ;
mkdir /usr/lib/prosody/cert/pubsub.example.com
cp -L /etc/letsencrypt/live/pubsub.example.com/fullchain.pem /usr/lib/prosody/cert/pubsub.example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/pubsub.example.com/privkey.pem /usr/lib/prosody/cert/pubsub.example.com/privkey.pem ;
mkdir /usr/lib/prosody/cert/vjud.example.com
cp -L /etc/letsencrypt/live/vjud.example.com/fullchain.pem /usr/lib/prosody/cert/vjud.example.com/fullchain.pem ;
cp -L /etc/letsencrypt/live/vjud.example.com/privkey.pem /usr/lib/prosody/cert/vjud.example.com/privkey.pem ;
chown root:prosody -R /usr/lib/prosody/cert/
Step 4 - Check configuration, start prosody server and create the admin user
Run prosodyctl check
to automatically check your configuration file for issues.
You can safely ignore SRV target xmpp.example.com. contains unknown client port: 443
here because we use SSLH to bind to 443 and not prosody itself.
If all checks passes we can start prosody again and check the status if it was successful.
prosodyctl start
prosodyctl status
Check the logfile for further errors.
less /var/log/prosody/prosody.log
Lets create the admin user.
prosodyctl adduser holu@example.com
You can now log in via any XMPP client.
Step 5 - Compliance Tester (Optional)
You should create a separate user for the tester as you have to submit credentials.
prosodyctl adduser compliance@example.com
Enter the credentials into the Compliance Tester and submit them.
You should pass here all tests except the informal tests for XEP-0156, which is not important for ranking nor for the features.
The XEP-0077 only passes if you have enabled mod_register
in the configuration file. You should not enable it for a private server and create new accounts with prosodyctl
.
You can also subscribe to periodic reports for this server at the bottom left after you submitted the credentials.
Further help and issue reporting
Prosody XMPP Chatroom: prosody@conference.prosody.im via Webchat: Join without account
Mailing lists: https://prosody.im/discuss
Reporting:
Conclusion
We now have a fully featured state of the art XMPP server. You can start chatting with the most popular clients are Gajim for desktop and Conversations for mobile usage. A new and modern clients is Dino for example. For more clients take a look here.
Please do not forget to update your packages regularly with apt-get update && apt-get upgrade
, otherwise prosody does not receive any updates.
You can also setup a cronjob for this if you want: Execute crontab -e
and add @weekly apt-get update && apt-get upgrade
at the bottom.
As noticed below we have all features which are required for 100% in the compliance tester https://compliance.conversations.im/.
Next to this, we have more (security) features:
- Enforced transport encryption
- Privacy enhanced push notifications because of disabled message body
- A opt-in user directory
- Bidirectional Server-to-Server Connections
- HSTS header for web
- BOSH under
https://xmpp.example.com:5281/http-bind/
- Websocket under
wss://xmpp.example.com:5281/xmpp-websocket
orhttps://xmpp.example.com:5281/xmpp-websocket
Extra features for the administrator:
- Notification on new registrations
- Serverwide announcements to all users
- Information message when certificates threaten to expire
- Information message when unencrypted connection from another XMPP server fails
Optional advanced features
Expose prosody via port 443 to connect behind a firewall
On public wifi you are often not allowed to use port 5222. The most hotspots only have port 53(DNS), 80(HTTP) and 443(HTTPS) enabled. We can bypass this blockage or better just "use what we have".
We will use SSLH which is an applicative protocol multiplexer.
In both cases add the following DNS records:
_xmpp-client._tcp.example.com. 14400 IN SRV 15 1 443 xmpp.example.com.
_xmpps-client._tcp.example.com. 14400 IN SRV 20 1 443 xmpp.example.com.
We also need SSLH
apt-get install sslh
Create the configuration directory:
mkdir /etc/sslh/
Edit /etc/default/sslh
and put following inside:
RUN=yes
DAEMON=/usr/sbin/sslh
DAEMON_OPTS="-F /etc/sslh/sslh.cfg"
General information if you run a webserver on the same machine
You cannot bind twice to port 443, we will use SSLH to split the http and xmpp traffic.
NOTE: You have to bind your webserver to localhost (127.0.0.1), this will result in a short downtime of your websites as they are not reachable until SSLH is running. You also will see 127.0.0.1 in the access logfiles from your webserver. Check the guide with transparent proxy below if you want to see the real IP addresses.
-
Apache
- Edit
/etc/apache2/ports.conf
and change everywhereListen 443
toListen 127.0.0.1:443
- Check all your VirtualHosts in
/etc/apache2/sites-available/
and change<VirtualHost *:443>
or<VirtualHost 10.0.0.1:443>
to<VirtualHost 127.0.0.1:443>
- Restart Apache with
systemctl restart apache2
- Edit
-
nginx
- Check all your listen directives in
/etc/nginx/sites-available/
and changelisten 443;
orlisten [::]:443;
tolisten 127.0.0.1:443;
- Restart nginx with
systemctl restart nginx
- Check all your listen directives in
With a webserver on the same machine (no transparent proxy)
Edit the configuration file /etc/sslh/sslh.cfg
verbose: false;
foreground: false;
inetd: false;
numeric: false;
transparent: false;
timeout: 5;
log_level: 0;
user: "sslh";
pidfile: "/run/sslh/sslh.pid";
listen:
(
{ host: "xmpp.example.com"; port: "443"; }
);
protocols:
(
{ name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; log_level: 0;},
{ name: "tls"; host: "localhost"; port: "443";},
{ name: "xmpp"; host: "localhost"; port: "5222"; },
{ name: "timeout"; host: "localhost"; port: "443";}
);
on-timeout: "timeout";
And restart SSLH to apply the changes: systemctl restart sslh
.
With a webserver on the same machine (transparent proxy)
You cannot bind twice to port 443, we will use SSLH to split the http and xmpp traffic.
NOTE: You have to bind your webserver to localhost (127.0.0.1), this will result in a short downtime of your websites as they are not reachable until SSLH is running.
Edit the configuration file /etc/sslh/sslh.cfg
verbose: false;
foreground: false;
inetd: false;
numeric: false;
transparent: true;
timeout: 5;
log_level: 0;
user: "sslh";
pidfile: "/run/sslh/sslh.pid";
listen:
(
{ host: "xmpp.example.com"; port: "443"; }
);
protocols:
(
{ name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; log_level: 0;},
{ name: "tls"; host: "localhost"; port: "443";},
{ name: "xmpp"; host: "localhost"; port: "5222"; },
{ name: "timeout"; host: "localhost"; port: "443";}
);
on-timeout: "timeout";
Edit /etc/sysctl.conf
and add at the following to the bottom
net.ipv4.conf.all.route_localnet = 1
net.ipv4.conf.default.route_localnet = 1
Apply the changes with sysctl -p
Install iproute2
and iptables
:
apt-get install iproute2 iptables
Create the bash script which deploys the iptables rules for the transparent proxy /usr/local/bin/sslh-transparent-proxy.sh
.
#!/bin/bash
# DROP martian packets as they would have been if route_localnet was zero
# Note: packets not leaving the server aren't affected by this, thus sslh will still work
iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP
iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP
# Mark all connections made by ssl for special treatment (here sslh is run as user "sslh")
iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f
# Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark)
iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f
# Configure routing for those marked packets
ip rule add fwmark 0x1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
Mark it as executable with chmod +x /usr/local/bin/sslh-transparent-proxy.sh
Source: github.com/sslh#transparent-proxy-support
Edit /etc/rc.local
and add
bash /usr/local/bin/sslh-transparent-proxy.sh
at the bottom of the file.
Without a webserver
Edit the configuration file /etc/sslh/sslh.cfg
verbose: false;
foreground: false;
inetd: false;
numeric: false;
transparent: false;
timeout: 5;
log_level: 0;
user: "sslh";
pidfile: "/run/sslh/sslh.pid";
listen:
(
{ host: "xmpp.example.com"; port: "443"; }
);
protocols:
(
{ name: "tls"; host: "localhost"; port: "5223"; alpn_protocols: [ "xmpp-client" ]; log_level: 0;},
{ name: "tls"; host: "localhost"; port: "5281";},
{ name: "xmpp"; host: "localhost"; port: "5222"; },
{ name: "timeout"; host: "localhost"; port: "5281";}
);
on-timeout: "timeout";
And restart SSLH to apply the changes: systemctl restart sslh
.
XEP-0156: Discovering Alternative XMPP Connection Methods (HTTP)
Although XMPP specifies the use of TCP as the method of connecting to an XMPP server, alternative connection methods exist, including the BOSH (XEP-0124) method (for which XMPP Over BOSH (XEP-0206) is the XMPP profile) and the websocket subprotocol. For some of these methods, it is necessary to discover further parameters before connecting, such as the HTTP URL of an alternative connection manager.
General information
We will create two files host-meta
and host-meta.json
. Both files have to be located under the domain example.com
in the folder /.well-known
, you cannot use a subdomain here. If have example.com
pointed to another servers IP address you have to deploy the files there.
(Click to expand) Content of 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.com:5281/http-bind" />
<Link rel="urn:xmpp:alt-connections:websocket"
href="wss://xmpp.example.com:5281/xmpp-websocket" />
</XRD>
(Click to expand) Content of host-meta.json
{
"links": [
{
"rel": "urn:xmpp:alt-connections:xbosh",
"href": "https://xmpp.example.com:5281/http-bind"
},
{
"rel": "urn:xmpp:alt-connections:websocket",
"href": "wss://xmpp.example.com:5281/xmpp-websocket"
}
]
}
If you have prosody installed without a webserver and exposed via port 443 you can remove :5281
in both host-meta
files.
Otherwise you keep it as it is or you deploy a reverse proxy for both. We will not explain in this tutorial on how to do this.
With a webserver (nginx)
Add both files from above to your document root in the folder .well-known
. Create the folder if it does not exist as below.
mkdir /var/www/example.com/.well-known
And change permissions to your www (www-data
by default) user:
chown www-data:www-data -R /var/www/example.com/.well-known/
We also need to set the Header Access-Control-Allow-Origin "*"
in our configuration for the domain example.com
. Server configurations are located under /etc/nginx/sites-available/*
.
location /.well-known/host-meta {
default_type 'application/xrd+xml';
add_header Access-Control-Allow-Origin '*' always;
}
location /.well-known/host-meta.json {
default_type 'application/jrd+json';
add_header Access-Control-Allow-Origin '*' always;
}
To apply these changes reload nginx with systemctl reload nginx
.
With a webserver (Apache)
Add both files from above to your document root in the folder .well-known
. Create the folder if it does not exist as below.
mkdir /var/www/example.com/.well-known
And change permissions to your www (www-data
by default) user:
chown www-data:www-data -R /var/www/example.com/.well-known/
We also need to set the Header Access-Control-Allow-Origin "*"
in our virtual host for the domain example.com
. Virtual hosts are located under /etc/apache2/sites-available/*
<Location ~ "/\.well-known/host-meta(\.json)?">
Header set Access-Control-Allow-Origin "*"
</Location>
To apply these changes reload Apache with systemctl reload apache2
.
Without a webserver
Add "http_files";
in the configuration file /etc/prosody/prosody.cfg.lua
to the array modules_enabled = { }
.
Outside the modules_enabled array add
http_files_dir = "/var/www/prosody/"
and save the configuration file.
Now you have to create the folder .well-known
with mkdir -p /var/www/prosody/.well-known
and add both files from above into it.
Change permissions with chown root:prosody -R /var/www/prosody/
and restart prosody prosodyctl restart
.
IRC Gateway with Biboumi
Biboumi is a Free, Libre and Open Source XMPP gateway that connects to IRC servers and translates between the two protocols. Its goal is to let XMPP users take part in IRC discussions, using their favourite XMPP client.
You can find more detailed information about the installation progress in the biboumi documentation.