Private Matrix: Hosting a Synapse Server Over Tor (Modern Chat On The Dark Net)

Tired of corporate servers watching every chat?
Host your own Matrix on Tor, no public IP, zero tracking.
By running Matrix over Tor, you eliminate exposure to public servers and keep your chats private.

This isn’t just another guide – it’s a battle‑tested recipe for keeping your Matrix chats private on Tor.

This guide walks you through deploying a self-contained Matrix Synapse server accessible only via a Tor .onion address.

No public exposure. No certificates. Just encrypted chat through the hidden network.

What you’ll learn

  • Spin up Synapse in minutes with Python‑venv
  • Expose it only via a .onion address
  • Lock down registration to invite‑only users
  • Run Element Web on the same hidden service

What you’ll get

  • Encrypted text chat (end-to-end)
  • Hidden service access via Tor
  • PostgreSQL backend
  • Invite-only registration
  • Element Web client

1. Install Synapse And Dependencies

Dependencies

sudo apt install -y python3 python3-pip python3-venv tor postgresql-17 libpq5 libpq-dev

Create Environment

mkdir -p ~/matrix-synapse
cd ~/matrix-synapse
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install "matrix-synapse[postgres]"

2. Tor Hidden Service

Edit Tor’s config:

sudo nano /etc/tor/torrc

Add:

HiddenServiceDir /var/lib/tor/matrix/
HiddenServicePort 80 127.0.0.1:8008

Restart Tor:

sudo systemctl restart tor
sudo cat /var/lib/tor/matrix/hostname

The file contains your new .onion address – this will become your servername in Synapse.

3. Configure Synapse

Generate a new configuration:

# Replace with your .onion address from /var/lib/tor/matrix/hostname
python3 -m synapse.app.homeserver \
    --server-name yourhiddenchat.onion \
    --config-path homeserver.yaml \
    --generate-config \
    --report-stats=no

4. Set Up PostgreSQL

sudo -u postgres bash
createuser --pwprompt synapse_user
createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse
exit

Edit the database section in homeserver.yaml:

database:
  name: psycopg2
  args:
    user: synapse_user
    password: "your_password"
    dbname: synapse
    host: localhost

5. Synapse Configuration for Tor

Minimal homeserver.yaml:

server_name: "yourhiddenchat.onion"
public_baseurl: "http://yourhiddenchat.onion"
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: false
    bind_addresses: ['127.0.0.1']
    resources:
      - names: [client]
        compress: false

report_stats: false
registration_shared_secret: "long_random_secret"
federation_domain_whitelist: []
federation_ip_range_blacklist: ["0.0.0.0/0"]
enable_registration: false
registration_requires_token: true

6. Start Synapse

synctl start

Register the first user:

register_new_matrix_user -c homeserver.yaml http://localhost:8008

7. Install Element Web

Element Web is a lightweight matrix client.

Limitations through the Tor browser:

  • No WebRTC = no media service.
  • No audio.
  • No video.

On the Onion Network, these are not real limitations.

On Tor Browser, avatars are not displayed, but text chat remains fully functional.
Brave can handle media fully, but only use it for your private .onion server to maintain privacy.
Element Web requires JavaScript – only load your own .onion instance to avoid exposure.

Check the current release on:

https://github.com/element-hq/element-web/releases

Install Nginx and download Element Web:

# on the same server as Synapse
sudo apt install nginx
cd /var/www/
sudo wget https://github.com/vector-im/element-web/releases/download/v1.11.83/element-v1.11.83.tar.gz
sudo tar xzf element-v1.11.83.tar.gz
sudo mv element-v1.11.83 element

Open the site configuration file:

sudo nano /etc/nginx/sites-available/element-web.conf

Add the site config:

server {
    listen 127.0.0.1:8080;
    server_name your-element.onion;

    root /var/www/element;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/element-web.conf /etc/nginx/sites-enabled/
sudo systemctl reload nginx

Reload the Nginx configuration:

sudo nginx -t && sudo systemctl reload nginx

Set up the Element Web via /var/www/element/config.json:

{
  "default_server_config": {
    "m.homeserver": {
      "base_url": "http://yourhiddenchatxxxxxxxx.onion",
      "server_name": "yourhiddenchatxxxxxxxx.onion"
    }
  },
  "disable_custom_urls": true,
  "disable_guests": true,
  "brand": "Private Matrix over Tor"
}

Enable the Element Web site in the torrc:

# Synapse onion
HiddenServiceDir /var/lib/tor/matrix/
HiddenServicePort 80 127.0.0.1:8008

# Element onion
HiddenServiceDir /var/lib/tor/element/
HiddenServicePort 80 127.0.0.1:8080

8. Possible Improvements

  1. SystemD synapse service unit (enable / auto start the service)
  2. SystemD backup service unit (automated, quick backups)
  3. Systemd backup timer (schedule the backups)
  4. Admin maintenance scripts (e.g. removing idle users, rooms)
  5. Fail2ban or ufw minimal ruleset (limit external noise)

9. Closing Thoughts

Running chat over Tor isn’t about going dark – it’s about reducing exposure.
You control who can register, who can connect, and how data flows.

It’s a lab for privacy-centric network design, and a reminder:

Visibility is a choice.

Privacy is not hiding.
It’s choosing when to be seen.

2 thoughts on “Private Matrix: Hosting a Synapse Server Over Tor (Modern Chat On The Dark Net)

  1. This is pretty much my setup, but I can’t get encrypted v3 notifications running… which 100% defeats the purose of this. Every single message, that’s not longer than 150 chars can be read in clear text bei apns and fcm, as soon as some mobile client is in use.
    Unified push isn’t encrypted either afaik.
    Each device gets a unique token assigned for push notifications, combined with fingerprinting etc and they can read every single message as well as profile you. Graphene phones with ntfy are the only exception… but then again, as long as I can’t use encrypted notification, or turn off notifications all together, all of this is basically a fools errand.

    Like

    1. Thank you for the detailed comment – this is an important point that doesn’t get discussed enough.

      You’re right about the current limitations: when a Matrix client on iOS or Android relies on APNS/FCM, the push payload must remain very small and cannot contain end-to-end encrypted content. That means metadata about a message (or in extreme cases a short preview) can end up visible to the push provider. It’s a structural limitation of the mobile OS push systems, not Synapse itself.

      Encrypted v3 notifications were introduced to address this, but support is still incomplete across the ecosystem. Some clients have partial implementations, others not at all, and mobile OS constraints make it slow to roll out in a fully private form.

      Today, the realistic options look like this:

      1. Use a client + setup that supports encrypted notification attempts, understanding that the ecosystem is catching up.
      2. Disable notifications on mobile and rely on polling. Less convenient, more private.
      3. Use UnifiedPush where possible, but yes – the encryption story there is not perfect either.
      4. GrapheneOS + local notification handling (for example with ntfy) is currently the most privacy-preserving setup on mobile, as you mentioned.
      5. Desktop clients remain the most private since they don’t rely on third-party push frameworks.

      You’re absolutely correct that push notification design on mainstream mobile platforms remains a weak link for strong end-to-end privacy. Synapse over Tor solves transport-level exposure, but push delivery is still limited by what Apple and Google allow clients to do.

      I still think hosting your own Synapse – especially over Tor – gives you significant privacy and control over metadata, even if mobile notifications remain a compromise. But yes, it’s important to be transparent: for the strongest privacy, the only full solution today is disabling notifications or using a hardened Android environment.

      Thanks again for raising the topic. It’s a critical part of understanding the real-world privacy model of Matrix outside the marketing claims.

      Like

Leave a comment