e1e0.net

sources for e1e0 website
git clone https://git.e1e0.net/e1e0.net.git
Log | Files | Refs

self-hosted-xmpp-server.md (10449B)


      1 Title: Self hosted XMPP server (on OpenBSD)
      2 Author: paco
      3 Date: 2019-04-25
      4 Type: article
      5 
      6 _Update 2020-12-15: I've adapted [this ansible role][12] to match my needs.  You
      7 can take a look at it [here][13].  This is running on 6.8-current._
      8 
      9 Tested on OpenBSD 6.5 (prosody version 0.11.2)
     10 
     11 ## Intro
     12 
     13 Self-hosting an instant messaging service is quite simple. This guide shows how
     14 to do it using OpenBSD as a base system and XMPP as the messaging protocol.
     15 
     16 The end result is an End-to-End encrypted chat system for 1:1 or multi-user
     17 conversations.
     18 
     19 The software used for the server is [prosody][1], and it's all based on
     20 [this guide][2].
     21 
     22 For the clients, I've tried [Gajim][3] for the desktop (works for Windows,
     23 Linux and *BSD), [Conversations][4] on the phone (Android) and [profanity][5]
     24 on the terminal (works almost everywhere). There's a client for iOS called
     25 [ChatSecure][8], but I have not tried it.
     26 
     27 ## Rationale
     28 
     29 I used to host my messaging services back in the day. People stopped using this
     30 for some reason, and then came all the Whatsapp and co. So all that was
     31 forgotten.
     32 
     33 Although I never used whatsapp, on recent times I've been testing some instant
     34 messaging systems, but none of them were good enough. In the end, all rely on
     35 central systems, often owned by companies that have to make money from
     36 somwhere. Most of the times is you (one way or another) even if they say the
     37 service is free.
     38 
     39 I wanted something simple, client independent, secure (well, as secure as
     40 possible ...), easy to use from the client point of view and easy to manage
     41 from the server part. My goal is to replace things like Signal that I use with
     42 my family and friends.
     43 
     44 XMPP is federated, just like email is. And with recent extensions like easy to
     45 use End-to-End encryption and http file sharing it's a viable solution for
     46 resilient and secure instant messaging system, that does not spy on you (no
     47 more than encrypted email for instance).
     48 
     49 For now is not a complete replacement, as it does not provide VoIP, but is a
     50 start. I may look for voice alternatives or dig deeper for a jabber client that
     51 supports voice.
     52 
     53 ## Previous steps (DNS and TLS)
     54 
     55 Some DNS configuration is needed for this guide. If you are not using file
     56 uploads or multi-user chat, then is probably fine if your root dns name points
     57 to the machine that will host the xmpp server. If not, you'll have to define
     58 some SRV records, and also any record you may use for the mentioned services.
     59 It may look like this (config depends on your DNS provider):
     60 
     61     _xmpp-client._tcp 1800 IN SRV 5 0 5222 server.mydomain.com.
     62     _xmpp-server._tcp 1800 IN SRV 5 0 5269 server.mydomain.com.
     63 
     64 This will tell xmpp clients and other servers trying to reach your accounts
     65 where (host and port) to knock.
     66 
     67 In this particular case I configured also multi-user chat and http file
     68 uploads, so I defined `uploads`, `proxy` and `groups` as `CNAME` of the
     69 server's `A` record.
     70 
     71 I also configured `acme-client(1)` and `httpd(8)` to get certificates from
     72 letsencrypt, so all communications client/server and server/server is
     73 encrypted.
     74 
     75 How to do that is out of the scope of this guide, just read the man pages, it's
     76 quite easy to do. The only detail to take into account is that is better to
     77 have all the domains/subdomains with its own cert and into separated folders
     78 containing the certificate and the private key. This important for certificate
     79 import on prosody later on. So I ended up configuring it to store certs on a
     80 structure like:
     81 
     82     /etc/ssl/letsencrypt/
     83     |-- mydomain.com
     84     |   |-- cert.pem
     85     |   |-- fullchain.pem
     86     |   `-- privkey.pem
     87     |-- groups.mydomain.com
     88     |   |-- cert.pem
     89     |   |-- fullchain.pem
     90     |   `-- privkey.pem
     91     ...
     92 
     93 ## Server install
     94 
     95 Install the server is as easy as:
     96 
     97     $ doas pkg_add prosody
     98 
     99 ## Server config
    100 
    101 So here comes the fun part.
    102 
    103 First you should get the community modules. Some of them provide functionality
    104 that is needed on any modern IM system.
    105 
    106 The way to do that is cloning the [mercurial][6] repository. I did not want to
    107 have it installed on my server, so I cloned it on my desktop machine and synced
    108 to the server. So, on my desktop I did:
    109 
    110     hg clone https://hg.prosody.im/prosody-modules/ prosody-modules
    111 
    112 Then I uploaded it to `/usr/local/lib/prosody-modules/` on the server.
    113 Here's the important parts I changed from the config files and why:
    114 
    115 Community modules location:
    116 
    117     plugin_paths = { "/usr/local/lib/prosody-modules" }
    118 
    119 List of globally enabled modules:
    120 
    121     modules_enabled = {
    122                     "roster"; -- Allow users to have a roster. Recommended ;)
    123                     "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
    124                     "tls"; -- Add support for secure TLS on c2s/s2s connections
    125                     "dialback"; -- s2s dialback support
    126                     "disco"; -- Service discovery
    127                     "carbons"; -- Keep multiple clients in sync
    128                     "pep"; -- Enables users to publish their mood, activity, playing music and more
    129                     "private"; -- Private XML storage (for room bookmarks, etc.)
    130                     "blocklist"; -- Allow users to block communications with other users
    131                     "vcard"; -- Allow users to set vCards
    132                     "version"; -- Replies to server version requests
    133                     "uptime"; -- Report how long server has been running
    134                     "time"; -- Let others know the time here on this server
    135                     "ping"; -- Replies to XMPP pings with pongs
    136                     "register"; -- Allow users to register on this server using a client and change passwords
    137                     "mam"; -- Store messages in an archive and allow users to access it
    138                     "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
    139                     "server_contact_info"; -- Publish contact information for this service
    140                     "vcard4";
    141                     "vcard_legacy";
    142                     "smacks"; -- XEP-0198: Stream Management, keep chatting even when the network drops for a few seconds
    143                     "csi_simple";
    144                     "bookmarks";
    145                     "cloud_notify"; -- XEP-0357: Push Notifications.
    146     }
    147 
    148 Disable registration, as this will not be a public server. This is the default,
    149 but just check it just in case.
    150 
    151     allow_registration = false
    152 
    153 Force clients to use encrypted connections
    154 
    155     c2s_require_encryption = true
    156 
    157 Force servers to use encrypted connections.
    158 
    159     s2s_require_encryption = true
    160 
    161 
    162 Force certificate authentication for server-to-server connections. This may
    163 bring problems with servers that use self-signed certificates. Today nobody
    164 should be using that, as there are alternatives like letsencrypt but, if you
    165 have some server you want to talk to that uses self-signed certs, check
    166 `s2s_insecure_domains`
    167 
    168     s2s_secure_auth = true
    169 
    170 Location of directory to find certificates in (relative to main config file),
    171 on OpenBSD that's `/etc/prosody/certs`
    172 
    173     certificates = "certs"
    174 
    175 Virtual host. You can have many, for many domains. In my case this is just one
    176 personal domain. I limited the uploads to 9MB, but you can set up any other
    177 limit. Keep in mind that there's a 10MB limit for `http_max_content_size`
    178 
    179     VirtualHost "mydomain.com"
    180     Component "uploads.mydomain.com" "http_upload"
    181     http_upload_file_size_limit = 1024 * 1024 * 9 -- 9MB upload limit
    182     Component "groups.mydomain.com" "muc"
    183     modules_enabled = { "muc_mam", "vcard_muc" }
    184     Component "proxy.mydomain.com" "proxy65"
    185 
    186 At this point you can import the certificates you got from letsencrypt (or from
    187 any other CA), with the command:
    188 
    189     prosodyctl --root cert import /etc/letsencrypt/letsencrypt
    190 
    191 That will copy all needed files to `/etc/prosody/certs` so they are accessible
    192 to the prosody daemon. Now you can start the daemon:
    193 
    194     doas rcctl start prosody
    195 
    196 To make it permanent on boot, add it to the `pkg_scripts` on
    197 `/etc/rc.conf.local`.
    198 
    199 Also remember to open ports on the firewall (pf or any other you may have in
    200 front of your server). They are:
    201 
    202     5000 --> for proxying large file transfers between clients
    203     5222 --> for client to server
    204     5269 --> server to server
    205     5281 --> default https port for http file transfers
    206 
    207 ## Add accounts and client config.
    208 
    209 In order to add an account to your new server just execute:
    210 
    211     prosodyctl adduser user@mydomain.com
    212 
    213 You'll be asked for the new password and that's it !
    214 
    215 On the client side is usually enough to enter the jid (jabber id, in this
    216 example `user@mydomain.com`) and the password. As we configured the necessary
    217 dns records earlier, the client will discover to which server and port to
    218 contact to.
    219 
    220 ## OMEMO
    221 
    222 [OMEMO Multi-End Message and Object Encryption][7] is an extension to XMPP that
    223 provides encryption for 1:1 and multi-user chats.
    224 
    225 This is key for a secure chat system. Some of the most popular xmpp clients
    226 already support it. Conversations, for instance, has it enabled by default.
    227 Do not forget to set it up on your client.
    228 
    229 OMEMO trusts devices on first use, then you should check the key fingerprints
    230 to see if the person you're talking to is who it claims to be.
    231 
    232 Is a good practice to publish those fingerprints on some place public, like you
    233 would do with your GnuPG public key. In fact you could sign those to provide
    234 some proof of ownership.
    235 
    236 On Conversations, for instance, you can later verify a contact fingerprint via
    237 a QR code. From that moment no other key will be allowed for that contact if
    238 you do not explicitly allow it. I think all clients should support that ...
    239 
    240 ## Conclusion
    241 
    242 Now you should have a working XMPP server. It can not only be used for IM, but
    243 also for notifications on your scripts using the libraries for your language of
    244 choice. Here you have some examples in [perl][9], [python][10] and [golang][11]
    245 
    246 [1]: https://prosody.im
    247 [2]: https://homebrewserver.club/configuring-a-modern-xmpp-server.html
    248 [3]: https://gajim.org/
    249 [4]: https://conversations.im/
    250 [5]: http://www.profanity.im/
    251 [6]: https://www.mercurial-scm.org/
    252 [7]: https://en.wikipedia.org/wiki/OMEMO
    253 [8]: https://chatsecure.org/
    254 [9]: https://metacpan.org/pod/Net::XMPP
    255 [10]: https://lab.louiz.org/poezio/slixmpp
    256 [11]: https://github.com/FluuxIO/go-xmpp
    257 [12]: https://github.com/cullum/dank-selfhosted/tree/master/roles/prosody
    258 [13]: https://e1e0.net/repo/prosody_ansible_role.tar.gz