I'll show you how to set up a completely private Matrix server, accessible only via an onion address—no domain, no public IP, and no need to trust someone else's infrastructure. This is a case where control over the server provides a fundamentally different level of privacy than even the most encrypted messenger on third-party servers.
Why is this necessary if there's Element with regular Matrix?
Element connects by default to the matrix.org server or any other public server. This server sees the real IP address with every connection, sees metadata—who is in which chat with whom, when they were last online, even if the message content is end-to-end encrypted.
A private server, via an onion address, hides exactly this. The server only sees the IP address of the Tor exit node. The server owner has complete control over the hardware and logs, and no one else decides how long the data is stored.
What you'll need before you begin:
a VPS server, paid for anonymously—for example, through Njalla, 1984 Hosting, or Frantech—paid with cryptocurrency, registered via Tor Browser with a temporary email address. For testing, a minimal configuration of 1-2 GB of RAM and 20 GB of disk space is sufficient.
Access to the server via SSH.
Any Linux machine for management and subsequent connection via Element.
Step 1 - Connecting to the server and basic preparation
Connect to the VPS via SSH from the terminal:
ssh root@ip_address_of_the_server<br>
Update the system:
apt update && apt upgrade -y<br>
Step 2 — Install Synapse (the Matrix backend)
apt install -y lsb-release wget apt-transport-https<br>
Add the official Matrix repository:
wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg <br>echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/matrix-org.list<br>
Install:
apt update<br>apt install matrix-synapse-py3<br>
During the installation process, you will be asked for the server name - this is a fundamental point, which is discussed below.
Step 3 — install Tor and configure hidden service
apt install tor -y<br>
Open Tor config:
nano /etc/tor/torrc<br>
Add to the end:
HiddenServiceDir /var/lib/tor/matrix/<br>HiddenServicePort 443 127.0.0.1:8448<br>HiddenServicePort 8448 127.0.0.1:8448<br>
Save, restart Tor:
systemctl restart tor<br>
Look at your onion address:
cat /var/lib/tor/matrix/hostname<br>
You will get something like abcdefghijklmnop.onion — this is the server address, which never changes unless you recreate the hidden service.
Step 4 — a critical point about server_name
Open the main Synapse config:
nano /etc/matrix-synapse/homeserver.yaml
Find the line:
server_name: "..."
Here, enter the exact onion address you got in the previous step:
server_name: "abcdefghijklmnop.onion"
This cannot be changed after creating the first user — if you change the server_name later, all accounts will become invalid and you'll have to start from scratch. Before moving on, make sure you entered it correctly.
Step 5 — Configuring TLS and Ports
In the same homeserver.yaml, we find the listeners section:
listeners:<br> - port: 8448<br> tls: false<br> type: http<br> x_forwarded: true<br> bind_addresses: ['127.0.0.1']<br> resources:<br> - names: [client, federation]<br> compress: false<br>
Note — tls: false. This is normal and correct in this scheme, because all traffic already goes through an encrypted Tor tunnel, additional TLS on top is redundant and only complicates the configuration.
Step 6 - User Registration
Disable open registration so that outsiders cannot create an account on the server:
enable_registration: false<br>
Create the first user manually:
register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8448 <br>
The program will ask for a username, password, and administrator rights - yes/no.
Step 7 - start the service
systemctl enable matrix-synapse<br>systemctl start matrix-synapse<br>systemctl status matrix-synapse<br>
Make sure the status is active (running), without errors.
Step 8 - Connect via Element
You must connect via Tor, otherwise the whole point is lost. Open Element via Orbot on your phone or via Torsocks on your desktop:
torsocks element-desktop<br>
When logging in, don't select the default matrix.org, click Change home server (Edit → Homeserver URL) and enter:
http://abcdefghijklmnop.onion:8448 <br>
Enter the login and password you created in step 6 - that's it, your account in the private Matrix network is active.
Inviting other participants
Each new participant needs to: create an account on the server (registration is disabled for outsiders, so only the administrator can create one using the same register_new_matrix_user command), provide the onion address and login via a secure channel - for example, via OnionShare or Signal.
What does this architecturally provide?
No third-party server sees the metadata of the messages. The IP addresses of all participants are hidden via Tor on both sides. Complete control over the retention policy—the server owner decides how long messages are stored. Logging can be disabled completely at the server level.
What you should know in advance:
The server must be constantly online for participants to receive messages—unlike one-time file transfer tools, this requires a persistent infrastructure.
If the server is confiscated or access is lost, all messages, if retention is enabled, are physically stored there. Therefore, it's worth setting up a minimum storage level via redaction and a separate retention policy.
Synapse should be updated regularly—vulnerabilities in the server software are patched quickly, but only if you keep up with the updates.
The bottom line:
It wasn't the easiest setup, but the result is a completely independent private chat server without a single point of trust for third parties. For a team of several people, an editorial team, or simply a closed circle of people who value privacy without compromise, this is a fundamentally stronger position than any public messenger, no matter how encrypted.
Why is this necessary if there's Element with regular Matrix?
Element connects by default to the matrix.org server or any other public server. This server sees the real IP address with every connection, sees metadata—who is in which chat with whom, when they were last online, even if the message content is end-to-end encrypted.
A private server, via an onion address, hides exactly this. The server only sees the IP address of the Tor exit node. The server owner has complete control over the hardware and logs, and no one else decides how long the data is stored.
What you'll need before you begin:
a VPS server, paid for anonymously—for example, through Njalla, 1984 Hosting, or Frantech—paid with cryptocurrency, registered via Tor Browser with a temporary email address. For testing, a minimal configuration of 1-2 GB of RAM and 20 GB of disk space is sufficient.
Access to the server via SSH.
Any Linux machine for management and subsequent connection via Element.
Step 1 - Connecting to the server and basic preparation
Connect to the VPS via SSH from the terminal:
ssh root@ip_address_of_the_server<br>
Update the system:
apt update && apt upgrade -y<br>
Step 2 — Install Synapse (the Matrix backend)
apt install -y lsb-release wget apt-transport-https<br>
Add the official Matrix repository:
wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg <br>echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/matrix-org.list<br>
Install:
apt update<br>apt install matrix-synapse-py3<br>
During the installation process, you will be asked for the server name - this is a fundamental point, which is discussed below.
Step 3 — install Tor and configure hidden service
apt install tor -y<br>
Open Tor config:
nano /etc/tor/torrc<br>
Add to the end:
HiddenServiceDir /var/lib/tor/matrix/<br>HiddenServicePort 443 127.0.0.1:8448<br>HiddenServicePort 8448 127.0.0.1:8448<br>
Save, restart Tor:
systemctl restart tor<br>
Look at your onion address:
cat /var/lib/tor/matrix/hostname<br>
You will get something like abcdefghijklmnop.onion — this is the server address, which never changes unless you recreate the hidden service.
Step 4 — a critical point about server_name
Open the main Synapse config:
nano /etc/matrix-synapse/homeserver.yaml
Find the line:
server_name: "..."
Here, enter the exact onion address you got in the previous step:
server_name: "abcdefghijklmnop.onion"
This cannot be changed after creating the first user — if you change the server_name later, all accounts will become invalid and you'll have to start from scratch. Before moving on, make sure you entered it correctly.
Step 5 — Configuring TLS and Ports
In the same homeserver.yaml, we find the listeners section:
listeners:<br> - port: 8448<br> tls: false<br> type: http<br> x_forwarded: true<br> bind_addresses: ['127.0.0.1']<br> resources:<br> - names: [client, federation]<br> compress: false<br>
Note — tls: false. This is normal and correct in this scheme, because all traffic already goes through an encrypted Tor tunnel, additional TLS on top is redundant and only complicates the configuration.
Step 6 - User Registration
Disable open registration so that outsiders cannot create an account on the server:
enable_registration: false<br>
Create the first user manually:
register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml http://localhost:8448 <br>
The program will ask for a username, password, and administrator rights - yes/no.
Step 7 - start the service
systemctl enable matrix-synapse<br>systemctl start matrix-synapse<br>systemctl status matrix-synapse<br>
Make sure the status is active (running), without errors.
Step 8 - Connect via Element
You must connect via Tor, otherwise the whole point is lost. Open Element via Orbot on your phone or via Torsocks on your desktop:
torsocks element-desktop<br>
When logging in, don't select the default matrix.org, click Change home server (Edit → Homeserver URL) and enter:
http://abcdefghijklmnop.onion:8448 <br>
Enter the login and password you created in step 6 - that's it, your account in the private Matrix network is active.
Inviting other participants
Each new participant needs to: create an account on the server (registration is disabled for outsiders, so only the administrator can create one using the same register_new_matrix_user command), provide the onion address and login via a secure channel - for example, via OnionShare or Signal.
What does this architecturally provide?
No third-party server sees the metadata of the messages. The IP addresses of all participants are hidden via Tor on both sides. Complete control over the retention policy—the server owner decides how long messages are stored. Logging can be disabled completely at the server level.
What you should know in advance:
The server must be constantly online for participants to receive messages—unlike one-time file transfer tools, this requires a persistent infrastructure.
If the server is confiscated or access is lost, all messages, if retention is enabled, are physically stored there. Therefore, it's worth setting up a minimum storage level via redaction and a separate retention policy.
Synapse should be updated regularly—vulnerabilities in the server software are patched quickly, but only if you keep up with the updates.
The bottom line:
It wasn't the easiest setup, but the result is a completely independent private chat server without a single point of trust for third parties. For a team of several people, an editorial team, or simply a closed circle of people who value privacy without compromise, this is a fundamentally stronger position than any public messenger, no matter how encrypted.

