Protect Your Privacy With An XMPP Tor Hidden Service (Prosody)

The world is changing fast.
Yesterday’s mistake becomes today’s data leak – and tomorrow’s compromise.

Privacy is not a default setting.
It’s constant configuration and calibration.

You know how to install an IRC server as a Tor hidden service.
You’ve seen the modern features and modularity of the XMPP protocol.

A Tor hidden service protects both the server and the user.
This setup is designed to reduce exposure of IP addresses and limit metadata leakage.
It does not protect against compromised endpoints or user mistakes.

As most privacy-focused solutions, it comes with trade-offs:

  • Higher latency due to Tor routing.
  • Limited client compatibility (not all XMPP clients handle .onion well).
  • Increased operational complexity.
  • Smaller user base and ecosystem support.

Planned Features

  1. One to one chats.
  2. Multi User Chats (MUC).
  3. End to end encryption (E2EE).
  4. Single exposed service port (5222 via Tor).
  5. SQLite database backend.
  6. Disabled user registration.
  7. Disabled guest access.
  8. Disabled audio/video.
  9. Only admin created group chats.

Every point is a layer of privacy.
Every misconfiguration is a potential entry point.

This setup does not enable server-to-server federation.
It is designed for a closed, controlled communication environment.

SQLite is suitable for small deployments.
For larger user bases, consider PostgreSQL.

TLS is still used to protect XMPP-level communication and client expectations, even though Tor already encrypts the transport layer.

Prerequisites

  1. Debian or compatible system.
  2. root or sudo permission.
  3. tor daemon installed.

Tor Hidden Service Configuration

In the /etc/tor/torrc file configure the hidden service and the port mapping:

HiddenServiceVersion 3
HiddenServiceDir /var/lib/tor/prosody/ # hidden service base dir
HiddenServicePort 5222 127.0.0.1:5222 # c2s

Do not open port 5222 on the firewall.
The Tor service handles port mapping.

Restart the Tor service:

sudo systemctl restart tor.service

Note your new onion address:

sudo cat /var/lib/tor/prosody/hostname

The /var/lib/tor directory keeps your key to your hidden service.
Back it up carefully on an encrypted drive.

Installation

On Debian and compatible systems the required packages can be installed using apt:

sudo apt install -y prosody prosody-modules sqlite3 lua-dbi-sqlite3

Configuration

Global Configuration

Edit the global configuration file.

sudo vim /etc/prosody/prosody.cfg.lua

Set up the admin user of the XMPP server:

admins = { "user@your.onion" }

Force localhost-only binding:

interfaces = { "127.0.0.1" }

Uncomment the SQL configuration lines:

storage = "sql"
sql = { driver = "SQLite3", database = "prosody.sqlite" }

You can save and close the file.

Virtual Host Configuration

Create and edit the onion virtual host configuration:

sudo vim /etc/prosody/conf.avail/hidden-service.cfg.lua

Change the your.onion to your site’s .onion address.

VirtualHost "your.onion"
ssl = {
key = "/var/lib/prosody/your.onion.key";
certificate = "/var/lib/prosody/your.onion.crt";
}
authentication = "internal_hashed"
allow_registration = false
c2s_require_encryption = true
modules_enabled = {
"roster";
"saslauth";
"tls";
"disco";
"pep";
"carbons";
"smacks";
"mam";
"vcard4";
}
Component "muc.your.onion" "muc"
modules_enabled = { "muc_mam" }
restrict_room_creation = true
muc_room_default_public = false
muc_room_default_members_only = true
muc_room_default_persistent = true

Enable the configuration:

sudo ln -s /etc/prosody/conf.avail/hidden-service.cfg.lua \
/etc/prosody/conf.d/hidden-service.cfg.lua

Generate your self-signed certificates:

sudo prosodyctl cert generate your.onion

Start the Prosody service:

sudo systemctl start prosody.service

Monitor the logs if something is broken.

Clients must trust the self-signed certificate manually.
Some clients may refuse to connect until the certificate is trusted.

Add Your First User

Use the prosodyctl tool to register your first user:

sudo prosodyctl shell user create user@your.onion password

The first created user has admin privileges.
The other user’s default permission is “member”.

Final Thoughts

XMPP over Tor is not anonymity.
It is not designed to save you from OPSEC mistakes.
For example, logging in from a non-Tor client or reusing identities can break your privacy model.

It helps maintain privacy by limiting IP and metadata exposure.

E2EE is handled by XMPP clients (e.g. OMEMO).
The server does not enforce it, only supports message transport.

Always keep strict ethical boundaries while using hidden services.


Discover more from Tom's IT Cafe

Subscribe to get the latest posts sent to your email.

Leave a comment