Instant Messaging
Instant messaging is one of the harder problems in the self-hosted space. The centralised services work well precisely because everyone is already on them. Replacing them requires either convincing the people you communicate with to move, or running something alongside your self-hosted infrastructure for the contacts who will not.
This page covers three tools: Dino for XMPP-based messaging on your self-hosted server, Signal for encrypted messaging with contacts who will not move to XMPP, and Jitsi for video conferencing.
Dino XMPP Client
XMPP is the federated messaging protocol, the instant messaging equivalent of email. Like email, you can host your own server, communicate with users on other servers, and choose your own client. Unlike the major centralised messaging platforms, no single company controls the network.
Dino is the right XMPP client for this setup. It is actively maintained, supports OMEMO and OpenPGP end-to-end encryption, handles file transfers, supports voice and video calls via Jingle, and integrates cleanly with the KDE desktop despite being a GTK application.
Installation
sudo apt install dino-im
Adding your XMPP account
Open Dino and click Add Account. Enter your XMPP address in the format username@yourdomain.net. Dino will discover the server configuration automatically via DNS SRV records if they are correctly configured on your XMPP server.
Enter your password. If your server requires a client certificate (as configured in the certificates section), Dino supports TLS client certificate authentication: go to Account Settings and configure the certificate in the Advanced tab.
OMEMO encryption
OMEMO is the recommended encryption method for XMPP. It provides end-to-end encryption with forward secrecy and is supported by all modern XMPP clients.
OMEMO is enabled per-conversation in Dino. Open a conversation, click the lock icon, and enable OMEMO. Dino generates device keys automatically on first use and handles key exchange with your contacts transparently.
For group chats, OMEMO requires all participants to have a compatible client. If a participant does not support OMEMO, Dino will warn you before sending an encrypted message that they cannot read.
OpenPGP encryption
Dino also supports OpenPGP encryption for conversations with contacts who prefer it over OMEMO. This uses the GPG keys configured earlier in this series.
In Dino’s account settings, link your GPG key by selecting it from the keyring. When chatting with a contact whose OpenPGP key you have imported, you can switch to OpenPGP encryption in the conversation.
OpenPGP in XMPP does not provide forward secrecy (unlike OMEMO), meaning a compromised key could decrypt past messages. For most conversations, OMEMO is the better choice. OpenPGP is worth having available for contacts who specifically request it.
Configuring your self-hosted XMPP server
The XMPP server setup is covered in the server section of this series. Once running, your Dino client connects to it the same way it connects to any XMPP server. The difference is that you control the server: you can see message logs if needed, manage user accounts, and configure federation with other XMPP servers.
File transfers
Dino supports HTTP upload for file transfers (XEP-0363), which requires the XMPP server to have an HTTP upload component configured. Files are uploaded to the server and the recipient downloads them via a URL shared in the chat. The upload component on a self-hosted server stores files within your own infrastructure.
For direct transfers without server involvement, Dino supports Jingle file transfer (XEP-0234) for peer-to-peer exchange when both clients support it.
Voice and video calls
Dino supports voice and video calls via Jingle (XEP-0166). Both parties need a Dino client or another Jingle-capable XMPP client. Calls are peer-to-peer and encrypted. No server component is required for the call itself, though a TURN server improves connectivity through NAT, which is covered in the server section.
Signal Messenger
Signal is the right tool for encrypted messaging with contacts who will not move to XMPP. It is widely trusted, end-to-end encrypted by default, and the desktop client is actively maintained. The trade-off is that Signal is centralised and requires a phone number as an identifier. For contacts already on Signal, it is the lowest-friction option for end-to-end encrypted messaging.
Installation
The Signal repository uses the modern signed-by approach rather than the deprecated apt-key:
wget -qO- https://updates.signal.org/desktop/apt/keys.asc | \
sudo tee /usr/share/keyrings/signal-desktop-keyring.asc > /dev/null
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.asc] https://updates.signal.org/desktop/apt jammy main' | \
sudo tee /etc/apt/sources.list.d/signal-xenial.list
sudo apt update
sudo apt install signal-desktop
Signal Desktop requires linking to a Signal account on a mobile device. Open Signal on your phone, go to Settings > Linked Devices, and scan the QR code shown in the desktop application on first launch.
Privacy settings
Once linked, configure the privacy settings:
- Note to Self: useful as a scratchpad across devices
- Read receipts: disable if you prefer not to send read confirmations
- Typing indicators: disable if you prefer not to send typing notifications
- Link previews: disable to avoid Signal fetching external URLs
- Call relay: enable to route calls through Signal’s servers rather than peer-to-peer, which protects your IP address at the cost of slightly higher latency
Note on Signal and self-hosting
Signal’s server code is open source but the Signal Foundation operates the server infrastructure as a centralised service. You cannot self-host Signal in the way you can self-host XMPP. Signal is included here because it is the pragmatic choice for contacts who will not use XMPP, not because it fits the self-hosted philosophy of the rest of this series.
Jitsi Video Conferencing
Jitsi Meet is a free, open-source video conferencing solution. It works in any modern browser without plugin installation, and self-hosted instances are covered in the server section of this series.
Browser access
Jitsi Meet works in Brave, Firefox, and other modern browsers. Point your browser at your self-hosted instance or a public instance and create or join a meeting. No account is required.
For your self-hosted instance:
https://meet.yourdomain.net/
Create a meeting by entering a room name. Share the URL with participants. The meeting is end-to-end encrypted when all participants use the Jitsi desktop application or a browser with end-to-end encryption support enabled.
Note: the source material this series draws on states that Firefox is not supported by Jitsi. This is no longer accurate as of 2022. Jitsi Meet works in Firefox, though Chromium-based browsers including Brave have historically offered slightly better WebRTC performance.
Installation
The Jitsi Electron application provides a dedicated desktop experience rather than using the browser:
wget -qO /tmp/jitsi.deb \
https://github.com/jitsi/jitsi-meet-electron/releases/latest/download/jitsi-meet-x86_64.deb
sudo apt install /tmp/jitsi.deb
rm /tmp/jitsi.deb
Configure the default server to your self-hosted instance: open Jitsi, go to Settings, and set the server URL.
Public servers
If you have not yet set up a self-hosted Jitsi instance, several public servers are available for use in the meantime. A community-maintained list is available at:
https://jitsi.github.io/handbook/docs/community/community-instances/
The official public instance at meet.jit.si is operated by 8x8 following their acquisition of Jitsi and remains available for public use.
Self-hosted Jitsi
Running your own Jitsi instance means no dependency on third-party infrastructure for video calls. The server setup is covered in the server section of this series. Once running, set your Jitsi desktop application’s server URL to your own instance and all calls route through your own infrastructure.
Signal and centralised services like Zoom or Teams exist on one end of a spectrum that has your self-hosted XMPP server on the other. The right tool depends on who you are communicating with and what they will use. Trying to force all contacts onto XMPP is a losing battle. Running XMPP for people who will use it while maintaining Signal for those who will not is the pragmatic position.