How to self-host SimpleX SMP server for VPS
Run your own SimpleX SMP relay on VPS with pinned install, client fingerprint, ports, unprivileged service user, backups, TLS, and clear threat model.
Wetin self-hosted SimpleX chat server dey do
To self-host SimpleX chat server, you go run one daemon for VPS: smp-server, wey be relay for SMP (simplex messaging protocol). E dey keep message queues wey your contacts dey write to and read from. Another optional daemon wey dem call xftp-server dey relay file transfers. Both come from the same project, simplexmq, and each one na single binary, config file, and append-only log.
Dis one na for operator, no be for app user. The relay no dey keep accounts, contact lists, or chat history. E dey keep queues, some ciphertext wey never deliver, and certificate wey identify am. Wetin you dey take responsibility for na uptime, small disk space, and metadata wey pass through your box.
Every command, path, port, and flag below come from the project own documentation: the SMP server hosting page, the XFTP server page, and the protocol security document. Where number matter, dem name the page wey e come from next to am.
Why network wey no get user identifiers still need relays
SimpleX no get usernames, phone numbers, or account IDs. Contact na unidirectional queue: address for one relay wey one side dey write to, while the other side dey read from. Two of your contacts no share any identifier wey server fit use join dem together.
Those queues still need dey somewhere, for one simple reason. Two phones hardly dey online for the same second. Something must accept message now and hold am until the other device ask for am. Na the complete work of SMP relay be that. E also mean say the two devices never connect directly to each other, so neither device learn the other device IP (internet protocol) address. Instead, na the relay dey take that exposure.
The relay hostname dey inside the queue address, so e dey inside every invitation link wey you share from there. Remember this when you read the threat model near the end.
Wetins relay fit see and wetins e no fit see
The project explain this as threat model for protocol/security.md, and e good make you read am before you install anything, because after this guide, na you own that relay. Relay, even if attacker dey control am completely, no fit know the content or type of messages. E no fit add, duplicate, or corrupt individual messages without anybody detecting am. E no fit break end-to-end encryption with active attack.
The same page list wetins relay fit do. E fit know when queue recipient dey online. E fit count how many messages pass through a queue. E fit learn recipient IP address. E fit drop every future message for a queue, or lie about the state of that queue.
So the separation clear. Client dey responsible for confidentiality, and self-hosting no change am. Relay operator dey responsible for metadata and availability, and self-hosting hand both of dem over to you.
Wetin you need before you start
- One VPS wey dey run Ubuntu 22.04 or 24.04. The project publishes release binaries wey dem build exactly for these two, for x86-64 and aarch64.
- One domain name wey get A record pointing to the VPS, plus AAAA record if you get IPv6. The docs use
smp1.example.comas example. - Root or
sudoaccess, plus another SSH session wey dey open while you dey change the firewall. - One place outside the server to store backup, because the config directory na the server identity.
For ARM instance, use aarch64 asset instead of x86-64. Nothing else for this guide go change, and the choice between ARM and x86 VPS plans depend on price and per-core speed, not whether this software fit run.
Install a pinned release, no be "latest"
The project get install script wey dey pull the current release and register one simplex-servers-update command. E dey work. Still pin the version: if relay binary change without your control, you no fit reason about am when something break.
As of August 2026, current simplexmq release na v6.5.0, wey dem publish on 29 April 2026. Check the releases page for the tag wey you want, then use that tag everywhere below.
sudo useradd -m smp
sudo install -d -o smp -g smp -m 755 /etc/opt/simplex /var/opt/simplexuseradd -m smp no set password, so nobody fit log in directly as smp. Create the two directories yourself before you run anything else, because /etc/opt belong to root and get mode 755. This means say smp user no get place to write its own config directory.
VER=v6.5.0
curl -fL "https://github.com/simplex-chat/simplexmq/releases/download/$VER/smp-server-ubuntu-24_04-x86-64" -o /tmp/smp-server
sha256sum /tmp/smp-serverCompare that hash with the SHA2-256 checksums wey dem publish for the same tag inside the release notes. The project still signs release checksums with the SimpleX Chat key FB44AF81A45BDE327319797C85107E357D4A17FC. Dem document the key for the server page, so you fit verify the signature instead of trusting only the page wey you collect the hash from.
sudo install -m 755 -o root -g root /tmp/smp-server /usr/local/bin/smp-serverInstall am as root-owned on purpose. The service dey run as smp, so if attacker breach the service, e no fit rewrite the binary wey e dey start from.
Set up the server, and the two secrets wey e print
sudo su smp -c "smp-server init --yes --store-log --daily-stats --no-password --fqdn=smp1.example.com"--store-log(-l) dey write queue log wey dem fit only append to/var/opt/simplex/smp-server-store.log, so relay fit survive restart. If you no use am, restart go throw away every queue, and every contact wey route through you go stop working.--daily-stats(-s) dey write counters for CSV format to/var/opt/simplex/smp-server-stats.daily.log.--fqdndey put your domain inside the generated certificate. Use--ipinstead if you no get domain.--no-passworddey allow anybody create queue for your relay. To keep am private, setcreate_passwordunder[AUTH]inside/etc/opt/simplex/smp-server.iniafter init, instead of passing--passwordhere, because command line dey visible for your shell history and process list while e dey run.
Init dey generate certificate and print the two values wey you must keep. The first one na the fingerprint, a base64 string wey dem also write to /etc/opt/simplex/fingerprint. The second one na the complete server address, wey be the fingerprint plus your hostname. Copy both now.
Init dey also create /etc/opt/simplex/ca.key, and the docs tell you make you move that file go offline storage. The reason important: clients pin the fingerprint of that certificate authority. So anybody wey get ca.key fit issue fresh server certificate wey your clients go accept as your own. You only need the file again when you wan rotate the server certificate later with smp-server cert.
Treat init as one-time step. The fingerprint inside your address come from the authority wey e generate. So if you generate that authority again, you go get different address, and the one wey you already share go become unusable.
Run am under systemd as user wey no get privilege
Write /etc/systemd/system/smp-server.service exactly as the docs give am:
[Unit]
Description=SMP server systemd service
[Service]
User=smp
Group=smp
Type=simple
ExecStart=/usr/local/bin/smp-server start +RTS -N -RTS
ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex/smp-server-store.log" ] && cp "/var/opt/simplex/smp-server-store.log" "/var/opt/simplex/smp-server-store.log.bak"'
LimitNOFILE=65535
KillSignal=SIGINT
TimeoutStopSec=infinity
[Install]
WantedBy=multi-user.targetThe upstream unit still get AmbientCapabilities=CAP_NET_BIND_SERVICE. That line dey there because process dey run as smp, and non-root process no fit open ports below 1024. Without that line, daemon no fit bind to 80 or 443. Add am if you dey serve those ports. LimitNOFILE=65535 important because every subscribed client dey hold open TCP connection, and the default limit dey far below wetin busy relay need. ExecStopPost dey copy the store log go one .bak file every time dem stop am. This give you one free rollback point.
sudo systemctl daemon-reload
sudo systemctl enable --now smp-server
sudo systemctl status smp-server
sudo journalctl -fu smp-serverHealthy start go log the server address. Then confirm say the sockets don really open:
sudo ss -tlnp | grep -E ':(443|5223)'Both lines suppose name smp-server. To run the daemon under its own account without sudo rights na the same practice we describe for per-service accounts for VPS, and na this one dey stop bug for one network daemon from turning into root shell.
Wich ports to open, and one wey you suppose keep closed
The docs list three: 5223/tcp, 443/tcp and 80/tcp. Port 5223 na the SMP transport. The shipped config set port: 5223,443 under [TRANSPORT], so the same protocol still dey answer for 443. This matter because plenty restrictive networks dey allow outbound 443 and nothing else. Port 80 na only for the optional information page and the redirect go HTTPS.
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 5223/tcp
sudo ufw enableNo open 5224. Na the control port be that, and the docs reach am from the box itself with nc 127.0.0.1 5224. E dey print server state and delete queues, so e suppose stay for loopback with the admin and user passwords set under [AUTH]. If you new to the tool, the basics of ufw for one VPS explain rule order and how to avoid locking yourself out.
One more control dey catch people unaware. Most providers dey run network firewall for the panel, separate from ufw for the box. Port fit dey open for ufw and still get dropped before e reach you.
Server address wey your clients need
smp://<fingerprint>[:<password>]@<public_hostname>[,<onion_hostname>]That string na the complete client-side configuration. Paste am inside the app server settings, or make person scan the QR code wey the app show for am. The docs talk say the QR get the password inside, so anybody wey scan am fit receive messages through your server too.
One documented behaviour dey surprise everybody. When you add your server for the app, e only affect contacts wey you create from that time go front. Existing contacts remain for the relays wey dem queues first create on, and dem no migrate. Na the same reason you no fit switch relay off the next day after you replace am.
XFTP file relay add
XFTP (SimpleX file transfer protocol) na the file side of the network, and e be separate daemon with its own address. According to the project XFTP announcement, relays no get any file metadata: dem only see individual chunks, each one 256kb, 1mb or 4mb, with access authorised by anonymous credentials. Sender fit spread the chunks of one file across different relays, so na pieces dey inside your box, not complete files.
sudo useradd -m xftp
sudo install -d -o xftp -g xftp -m 755 /etc/opt/simplex-xftp /var/opt/simplex-xftp /srv/xftp
curl -fL "https://github.com/simplex-chat/simplexmq/releases/download/$VER/xftp-server-ubuntu-24_04-x86-64" -o /tmp/xftp-server
sudo install -m 755 -o root -g root /tmp/xftp-server /usr/local/bin/xftp-server
sudo su xftp -c "xftp-server init -l --fqdn=xftp1.example.com -q '20gb' -p /srv/xftp/"Its config dey for /etc/opt/simplex-xftp/, its state dey for /var/opt/simplex-xftp/, and the file chunks dey for anywhere -p name. The systemd unit get the same structure with User=xftp and ExecStart=/usr/local/bin/xftp-server start +RTS -N -RTS. Init prints xftp:// address for the same format as the SMP one, with its own fingerprint for /etc/opt/simplex-xftp/fingerprint.
You need plan for one port collision. The documented port for XFTP server na 443, and SMP config too list 443. Two processes no fit bind the same port for the same address, so one thing must change if both dey run for one VPS. The simplest fix na to set port: 5223 inside the SMP [TRANSPORT] section and leave 443 for the file relay. But clients for restrictive networks no go get the 443 fallback again. Other options na to use a second IP address for the same VPS, or use a second VPS.
Set the quota based on the disk wey you truly get. -q '20gb' na a promise about available disk space. File relay na the part wey go use plenty disk and bandwidth. Message relay almost no dey use either one.
Wetin dey for disk, and wetin backup dey restore
Two directories matter. /etc/opt/simplex/ na the identity: smp-server.ini, the server certificate and key, ca.key, and fingerprint. /var/opt/simplex/ na the state: smp-server-store.log dey hold the queues and, when restore_messages: on, the undelivered messages, together with the daily stats file.
sudo systemctl stop smp-server
sudo tar czf /root/simplex-backup.tgz -C / etc/opt/simplex var/opt/simplex
sudo chmod 600 /root/simplex-backup.tgz
sudo systemctl start smp-serverMake you understand wetin dey inside that archive. E no be message archive: the queued items na ciphertext for keys wey the relay never hold, and the shipped [STORE_LOG] config dey expire messages after 21 days anyway. Na copy of the server identity, including ca.key, so anybody wey collect the file fit present themselves as your relay to your contacts. Encrypt am and keep am outside the box.
The main benefit na restore. Put /etc/opt/simplex back for fresh VPS, point the same DNS name to am, and the fingerprint no change, so every address wey you give out still dey work. If you lose that directory, recovery no dey possible: new install means new fingerprint, new fingerprint means new address, and every contact wey route through your relay don disappear.
TLS: certificates two wey dey do different work
SMP transport no dey use public certificate authority. Init dey generate private authority and server certificate, and fingerprint of that authority dey inside server address. Client dey check wetin server present against that pinned fingerprint. Na this one project describe as protection for client-to-server connection against machine-in-the-middle attacks. No ACME (automatic certificate management environment) client dey run for that port, and rotation na manual smp-server cert run with SMP_SERVER_CFG_PATH set.
Optional information page na the other certificate. E [WEB] section dey name static_path, https: 443, cert: /etc/opt/simplex/web.crt and key: /etc/opt/simplex/web.key. Browser never hear of your private authority before, so na here publicly trusted certificate suppose dey. Docs' Docker quick start dey put Caddy in front of the server for exactly this purpose, and e dey issue the certificate automatically.
How to reach the relay through Tor
The docs get one Tor section wey install Tor from the Tor Project repository and add one hidden service for /etc/tor/torrc:
SOCKSPort 0
HiddenServiceNonAnonymousMode 1
HiddenServiceSingleHopMode 1
HiddenServiceDir /var/lib/tor/simplex-smp/
HiddenServicePort 5223 localhost:5223
HiddenServicePort 443 localhost:443Read the two mode lines well. Single hop and non-anonymous mean say the relay own location no dey hidden. The onion address dey fast, and e give clients one way to connect wey no ever reveal their IP address to you. But the server still dey findable through its public IP. The onion hostname from /var/lib/tor/simplex-smp/hostname go for the end of the server address after one comma. If you want hide the server location too, na different configuration be that, and running a real onion service on a VPS explain the trade-off. The difference for wetin each tool dey hide na the subject of Tor compared with a VPN, and e apply directly here.
Threat model: wetin self-hosting change
Wetin e give you. The metadata (which queues dey exist, when dem dey read am, which addresses dey connect) dey for machine wey you control, and na you set how long dem go keep any of am. You no dey part of one big pool wey person fit request all at once.
Wetin e no give you, make we talk am plain:
- The encryption no change. Messages don dey end to end encrypted before you build this, and dem still dey end to end encrypted after. Self-hosting na metadata decision, e no be cryptography decision.
- Your VPS provider dey see the traffic wey dey go your IP address, and e dey keep your billing details. You move trust from messaging operator go hosting operator. You no remove trust.
- Your relay na small crowd. If na one household dey use am, then connecting to am go identify that household, and the hostname dey inside every invitation link wey you send from am. Busy public relay fit hide you better for this one side, and na this be the real trade.
- Availability don become your responsibility. Full disk or dead box mean say messages go stop to deliver, and your contacts no get any way to route around you.
The same reasoning apply to any private service wey you put for box wey you own, whether na this relay or WireGuard VPN for your own VPS. You dey choose which party go see the metadata. You no dey make am disappear.
When e no work
The service start and stop immediately. Read sudo journalctl -u smp-server -n 50. Bind failure go name the port wey e no fit take. Then run sudo ss -tlnp | grep :443 to see which process dey hold am already. For fresh box, na usually nginx, Caddy, or the XFTP server wey you install one hour ago.
Init no fit write im config. If you run smp-server init as the smp user before /etc/opt/simplex exist, e go give permission error because /etc/opt belong to root. Create the directory with the correct owner first, then run init again.
Clients no fit reach the relay. Check say the name resolve to the correct address with dig +short smp1.example.com. Then test the port from your laptop, no be from the server: nc -vz smp1.example.com 5223. If connection fail from outside while ss show say the socket dey open for the box, na the provider network firewall likely cause am. That firewall dey separate from ufw.
A contact no fit connect through your relay. The fingerprint for the address wey you share must match the current contents of /etc/opt/simplex/fingerprint. If you set create_password under [AUTH], the address must carry that password too. Otherwise, the client no get permission to create queue.
Nothing move after you add the server for the app. Na so e suppose be. Na only new contacts go use the relay wey you just add. Existing contacts go continue to use the queues wey dem already get.
FAQ
Self-hosting SimpleX server make my messages more secure?
No, and na so dem design am. SimpleX dey encrypt messages end to end between devices, so relay no ever get the keys, no matter who dey run am. Self-hosting change who fit observe metadata around those messages: which queues dey exist, when dem dey read, and which IP addresses dey connect. Na metadata decision be this. If your reason for self-hosting na stronger encryption, the encryption don already dey there.
Wetin SimpleX relay operator fit actually see?
The project protocol/security.md explain this. Relay no fit read message contents or types, no fit secretly change individual messages without detection, and no fit break end-to-end encryption with active attack. E fit see when queue recipient dey online, count messages wey dey pass through queue, know recipient IP address, drop future messages for queue, or lie about the state of that queue. Na these powers you get once the relay become your own.
I need domain name and TLS certificate?
You need domain for setup wey people fit use, and smp-server init accept --ip if you truly no get domain. You no need certificate from public authority for messaging port: init generate its own authority, and client pin the fingerprint wey dey appear for your smp:// address. Publicly trusted certificate na only for the optional web information page, wey you configure as cert and key for [WEB] section of smp-server.ini.
Wetin go happen if I lose /etc/opt/simplex?
Every address wey you give people go stop to work. That directory hold certificate authority wey fingerprint dey embedded inside your server address, so rebuild go produce different fingerprint and therefore different server. You no fit repair contacts wey queues dey on that relay from client side. Back up the directory encrypted and outside the server, and store ca.key offline as the docs instruct, because anybody wey hold am fit impersonate your relay.
I fit run SMP relay and XFTP file relay for the same VPS?
Yes, but one conflict dey to settle. XFTP server documented port na 443, and default SMP config list port: 5223,443, so both of dem want the same socket. Give 443 to one of dem: set port: 5223 for SMP server, or move file relay go second IP address or second VPS. Also set storage quota based on the disk wey you truly get, because file relay na the component wey dey consume disk and bandwidth.