How to self-host a Matrix homeserver
Install Synapse from Element's docs, point DNS and federation, and size RAM by rooms—not by marketing vCPU.

Install Synapse from Element's documentation, publish federation on your domain, and size RAM by rooms and media. BitCloudVPS does not operate the homeserver.
What people actually host
Matrix: self-hosting is an open federation protocol. Synapse installation is the common homeserver. Clients such as Element talk to your domain. Families and small orgs run this so chat metadata is not sitting at a consumer messenger. We rent the VM; we do not operate your homeserver.
Business $24/mo (6 vCPU / 16 GB DDR5) is the production size. Crypto invoice, no KYC.
Launch nowWhat you do
- Start on Business. Move up when Postgres and media grow.
- Follow Synapse installation. Serve .well-known and federation on your domain.
- Switzerland is the process default; Iceland if speech is the reason; Amsterdam if users are in the EU.
- Pay annual USDT if you want a boring invoice, or BTC if that is the wallet you hold.
Limits
Legal rooms only. Federation is public by default unless you lock it down. Paying in crypto does not hide public room events.
Sizing a homeserver: which plan line Synapse actually fits
A homeserver for one household fits on the smallest plans; a federating server with a dozen rooms grows with the state resolver, not with the user count. Nano at $5.49/mo list - or the flat $36/yr annual price, $3/mo effective - runs Synapse for a few local accounts, but federation workers and media repositories want headroom. Starter at $8.50/mo is the realistic floor for a server that federates daily: 2 vCPU on an EPYC 7443P, 4 GB ECC RAM, 60 GB NVMe. The ECC part is not decoration - the media store and the event database are the two things you do not want to re-sync after a memory fault. If your room history and uploaded media grow past 60 GB, move bulk storage to the storage line: 1-5 TB of NVMe at $24-$56/mo, up to 8 vCPU and 32 GB RAM, and keep Synapse itself on the small box. Terms discount 10% quarterly and 20% yearly, payable in any of 19 crypto assets with no KYC and an optional email address.
From deploy to first federation, in order
- Deploy the VPS - about 60 seconds to a root shell - and point a subdomain like matrix.example.org at its IPv4 address.
- Install Synapse from the official package repository and run the homeserver.yaml generator; set server_name to the domain you actually want identities on, because it is baked into every user ID.
- Put a reverse proxy with TLS in front - port 8448 for federation, 443 for clients - and forward both to Synapse on localhost.
- Create your first user with register_new_matrix_user, then verify federation by joining any public room from an account on your server.
- Set the PTR record for the IP to the matrix hostname; it is editable in the panel before you send a single federated request.
The whole sequence is under an hour. The step people redo is server_name - changing it later means rebuilding every account, so decide it once.
What breaks in month three, and how to plan for it
Synapse failures are operational, not dramatic. The media repository grows with every image until the 60 GB NVMe volume on Starter is full; schedule the media retention job or point the media store at bigger NVMe. The database bloats from state groups in busy federated rooms; run the documented compression scripts monthly rather than discovering a 40 GB table during an outage. Upgrades land every few weeks and occasionally require a schema migration, so snapshot before each upgrade - snapshot-to-restore is minutes on a VPS and hours if you skipped it. Register a support contact address and an abuse contact in your homeserver config; federation peers sometimes email them. And test the backup restore path once: a homeserver backup that has never been restored is a hypothesis, not a backup. None of this needs a bigger plan before you need more disk - the storage line at $24/mo for 1 TB is the usual next purchase, not a Pro VPS.
The client side: Element and what your users will need
The homeserver is half the stack; users arrive through clients, and planning them saves support messages later. Element Web is static files behind the same reverse proxy as Synapse - minutes to deploy on the same box, a few megabytes of the 60 GB NVMe. Mobile and desktop Element clients just need the server URL and credentials, no per-device registration on the server side. Two settings matter at the homeserver level: registration - closed by default, and for a personal server it should stay closed or invite-only, since open registration on a federating server invites spam accounts and state-group bloat - and identity servers, which modern clients no longer require for basic use. If your users bridge to other networks, budget for the bridge process separately: bridges are extra long-running processes with their own memory and API credentials, and a busy bridge is the workload that genuinely pushes a household server from Starter at $8.50/mo toward Plus at $13.50. Decide the client story before inviting anyone: a homeserver whose operator becomes per-user tech support for client settings is a homeserver with a support problem, not a hardware one.
Installing Synapse the maintainable way: packages, PostgreSQL, reverse proxy
The direct answer: the setup that survives years of updates is Synapse from the official package repository, PostgreSQL (not the default SQLite), and Caddy or nginx in front terminating TLS — three moving parts, each replaceable, in that order. Install them in that order and the rest of this guide is checks instead of repairs.
- Add the Matrix packaging repo for your distribution and install
matrix-synapse-py3. Package repos beat pip-on-a-VPS because upgrades arrive with the system's normal update cycle, and a homeserver you forget to update is the one that breaks at federation time. - Install PostgreSQL and create the database:
CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0;— the C locale matters; a locale mismatch in the chainstate of room IDs will refuse to start later. Migrating from SQLite to PostgreSQL later is a documented script, but starting on PostgreSQL costs nothing and saves the migration. - Generate the config:
synapse.app.homeserver --server-name matrix.example.com --config-path homeserver.yaml --generate-config. Theserver_nameis permanent — it becomes your user IDs (@user:example.com) and cannot be renamed without abandoning the account database. Choose it like a domain you will keep forever, because it is. - Point
database:at PostgreSQL, setpublic_baseurlto the URL clients will use, and decideenable_registrationdeliberately — open registration on a public federating server is an invitation to abuse; registration_shared_secret or a closed flag is the norm for personal homeservers. - Reverse proxy: Caddy's two-line config does automatic certificates; nginx with certbot works equally. Forward port 8448 to Synapse or terminate at 443 — next section decides which. Verify with
curl https://matrix.example.com/_matrix/client/versionsreturning JSON.
Total footprint after this: well under a gigabyte of RAM for a handful of users, which is why a Starter-class box carries a personal homeserver comfortably — the cost centers come later, and they are media and federation traffic, not the core.
Server keys, delegation, and serving .well-known correctly
The direct answer: federation identity is three pieces — your signing key, the delegation record that tells other servers where your federation port lives, and the .well-known file clients fetch — and getting these wrong is the single most common reason a fresh homeserver "just doesn't federate".
The signing key lives in /etc/matrix-synapse and is generated at install. Back it up to the anonymous storage you keep for exactly this class of secret: a homeserver that loses its key cannot prove its history to federated rooms and effectively dies socially even if you restore the database. Never regenerate keys casually.
Delegation is how other servers find you. The default path is a DNS SRV record on the server name: _matrix._tcp.example.com pointing at your host and port 8448. The modern, simpler path is well-known delegation: serve https://example.com/.well-known/matrix/server containing {"m.server": "matrix.example.com:443"}. This lets you run federation over 443 on a subdomain while your user IDs stay @user:example.com — no SRV record, no exposing port 8448 through picky firewalls. Client delegation works the same way with /.well-known/matrix/client, pointing Element and friends at your base URL so users can log in with just their username and domain.
Verify all of it with the federation tester tools the Matrix project publishes — they check the whole chain: SRV or well-known resolution, TLS, key exchange, and a round-trip federation handshake. A green result there is the acceptance test for the DNS and certificate work; before you have it, nothing else about the server matters, because nobody else can reach you.
One trap worth naming: the well-known files must be served from the apex domain with correct CORS headers (Access-Control-Allow-Origin: * for the client file), or browser clients will silently fail to resolve your homeserver while server-to-server federation works fine. Symptom and cause look unrelated — users see "unknown server", federation testers see green — which is why this file belongs in your verification checklist rather than in a debugging session three weeks later.
Port 8448 versus 443 federation, and what to open in the firewall
The direct answer: today's recommended setup is federation on 443 via well-known delegation — it passes through networks that block 8448, needs no extra firewall rules beyond your TLS listener, and looks identical to normal web traffic. Port 8448 direct is still fully supported and slightly more direct; pick one, don't run both halves of each.
With well-known delegation on 443, your firewall opens exactly three inbound ports: 80 for ACME challenges (or nothing, if your CA uses TLS-ALPN), 443 for both client and federation traffic, and 22 for your SSH administration. The Synapse listener itself stays bound to localhost — the reverse proxy does the public exposure. This topology also simplifies TLS renewal, since one certificate covers the name clients and servers both resolve.
Direct 8448 federation opens 8448 inbound to the world in addition. The historical reason to prefer it — older server implementations resolving via SRV only — has faded; the modern reason is avoiding a redirect layer at the apex domain if you cannot serve .well-known there. If you do open 8448, rate-limit it in the proxy the same as 443: federation endpoints get probed by scanners within hours of going live, and Synapse's built-in rate limiting handles honest traffic fine but you want the noisy stuff dropped upstream.
What never to expose: the Synapse admin API and the PostgreSQL port. The admin API rides the same client listener with an authenticated token — keep it behind the proxy with a path restriction or an IP allowlist if you script against it, because an admin token leak on a federating server is total compromise. PostgreSQL binds localhost, full stop; the database credentials in homeserver.yaml never need to leave the machine. Audit the exposure with ss -tlnp from the box itself: everything Synapse-related should be either localhost or fronted by the proxy, nothing wild.
Media, retention, and the disk math for a homeserver
The direct answer: media storage is what grows without bound on a Matrix server — every image, video, and file sent in every room your users join gets a local copy — so the disk plan and a media retention policy are the two decisions that keep a homeserver cheap for years. The core database is modest; the media repository is not.
The math: a small group of active users in busy federated rooms accumulates gigabytes of remote media per quarter. Synapse caches remote media with configurable limits (max_spider_size, and the media store's cleanup jobs), but locally-uploaded media is kept until you policy it away. The purge_media_cache and local media retention APIs let you set an age horizon; automating it with a scheduled job — keep everything under 180 days, or keep local uploads and drop remote caches monthly — turns storage from a growing liability into a fixed budget. Size the disk to that budget with 50% headroom, not to your optimism about what users will upload.
The database grows too, but slower: event tables for rooms your users participate in, state groups, and the room directory. Synapse ships admin APIs for purging rooms you have left and for compressing state groups — the latter routinely shrinks the state tables by an order of magnitude on old servers and is a standard maintenance task for multi-year deployments. Run VACUUM after big purges or let autovacuum do its work and monitor table sizes monthly.
This is where the hosting plan line matters: a Starter-class VPS carries the compute comfortably, but if your users are heavy sharers, the dedicated storage line — sized in terabytes rather than gigabytes — exists precisely for this. The interim answer is retention policy; the long-term answer is picking the plan that matches your measured growth rate, which you will know within three months of real usage. Start with the numbers, not the fear of running out.
Upgrades, backups, and migrating a federating server safely
The direct answer: the safe cycle is database backup, one-version-at-a-time package upgrade, health check against the federation tester, then — only if green — the next one, with the signing keys and config directory in every backup. Homeserver downtime is tolerated by federation for a while, but an unrecoverable database is not; treat backups as the feature, upgrades as routine.
The backup set is five things: the PostgreSQL dump (pg_dump synapse nightly, compressed, shipped off-box), the signing keys in /etc/matrix-synapse, homeserver.yaml and any .yaml includes, the reverse-proxy config, and the media store directory — or an agreement that media is expendable while the account database is not. Restoring the first four reconstructs a working federation identity; the fifth decides whether old images survive. Ship the dumps to a second server on the same anonymous account so the backup inherits the threat model instead of sitting on the same disk as the primary.
Upgrades: read the Synapse release notes before anything — deprecations are announced a release or two ahead, and config options get renamed with warnings, not breakage. Apply updates with the package manager, restart, then run the checks in order: synctl or systemd status clean, client login works locally, curl of /_matrix/client/versions answers, federation tester green, and a test message from an account on another homeserver actually arrives. That last check is the real one — local health with dead federation is the failure mode that goes unnoticed for weeks on a server with one user.
Migration to a bigger box — the usual growth path — is the same backup set plus a DNS change: restore PostgreSQL and config on the new server, test federation from the new IP with a hosts-file override if you want to be careful, then flip the DNS record with a low TTL you set the day before. Clients reconnect through well-known; rooms and history follow the database. An hour of planned downtime, not a rebuild.
Troubleshooting federation: symptoms, causes, fixes
The direct answer: Matrix federation failures cluster into five diagnosable patterns — unverifiable keys, unreachable federation port, wrong well-known, TLS chain issues, and clock drift — and each announces itself with a specific message in the Synapse logs or in the remote server's refusal. Read the error, not the guess.
Symptom: invites from other servers arrive, but joining shows "signature invalid" or the room stays stuck on "joining". Cause: the remote cannot verify your server's signing key — usually the keys endpoint /_matrix/key/v2/server is not reachable through your proxy, or a middlebox caches it stale. Fix: curl that endpoint from outside and compare with the local key file; check the proxy is forwarding the path, not just the client routes.
Symptom: federation tester says "connection refused" or times out on 8448 while client logins work. Cause: delegation mismatch — well-known points at a port or host that is not actually listening, or the firewall only opened 443 while delegation still targets 8448. Fix: make the well-known JSON, the DNS record, and the proxy listener tell the same story; one of the three is lying. Symptom: remote servers log TLS errors about your certificate. Cause: an incomplete chain — your proxy serves the leaf without intermediates, which browsers tolerate and server-to-server verification does not. Fix: test with openssl s_client -connect matrix.example.com:443 and confirm the chain completes; reconfigure the proxy to serve the fullchain file.
Symptom: messages you send arrive, responses silently never do. Cause: clock skew large enough that event timestamps fail validation — check timedatectl, enable NTP, drift of minutes is fatal in federation gossip. Symptom: everything works except one specific large room. Cause: that room's state is genuinely heavy; Synapse logs slow state resolution. Fix is capacity, not config: more RAM for the state cache, or leave and rejoin to rebuild state. Log first, change one thing, re-test with the federation tester — Matrix gives honest errors once you look in the right process's log.
BitCloudVPS Starter · Amsterdam · 4 GB ECC NVMe, unmetered 1 Gbps
Deploy a homeserver hostWhere the limits are (October 2026)
Keep the threat model precise. Anonymous-adjacent hosting removes the host-side identity trail: token-only signup, optional email, no KYC review, crypto invoices that record a txid rather than a name. It does not blind the host to traffic it must carry, it does not make a logged-in panel session anonymous, and it does not protect workloads that identify themselves — an admin login from your home IP defeats the whole design. Exact limits of no-KYC anonymity. OPSEC guide. Full checklist. Payment-side note: chain analysis happens on public blockchains, not at the host. Coin choice and network choice are your OPSEC knobs, and the checkout keeps 19 of them open.
Do you manage Synapse?
No.
Dendrite or Conduit?
Your choice. Same VPS.
Do I need to open port 8448 for Matrix federation?
Yes, if you want inbound federation. Port 8448 serves server-to-server traffic; BitCloudVPS does not filter it, so a normal firewall rule and a DNS SRV or direct record is all that is required. Clients-only servers can keep 8448 closed and connect out.
Can I run Synapse and an Element web client on the same VPS?
Yes, and it is the common layout. Element Web is static files behind the same reverse proxy - a few megabytes on the 60 GB NVMe of a Starter plan. Run it on a separate subdomain from the Synapse hostname and serve both over TLS from one small box.
Which plan suits a personal Synapse homeserver?
<p>Starter-class — around 2 vCPU, 4 GB RAM, 60 GB NVMe — carries a personal or small-group homeserver comfortably: Synapse core uses well under a gigabyte, PostgreSQL a few hundred MB, and the growth vector is the media store, not compute. Add retention policies for media, and if your group turns out to be heavy sharers, move to the storage line sized in terabytes — the migration is a database dump and a DNS flip. Reserve Business-class for many-user deployments with heavy federation and indexing, not for a first server.</p>
Which plan suits a small homeserver?
Starter at $8.50/mo — 2 vCPU EPYC 7443P, 4 GB ECC RAM and 60 GB NVMe — covers a household or small community on Synapse. Billing a year up front cuts 20%, and the plan keeps unmetered 1-10 Gbps for federation traffic.
What does the host actually know about me?
Whatever you hand over: a signup token, an optional email address, the invoice you paid and the service traffic. No ID documents, no phone number, no KYC step exists to hand anything else over.
What won't an anonymous VPS protect against?
Self-inflicted links: personal logins from a home IP, leaked cookies, services that publish your address, and on-chain patterns that tie wallets together. The server removes one identifier; it does not fix operational mistakes.
Primary sources
Ready to launch?
Configure a VPS or dedicated server, set a password, then pay the invoice.
Network
Edge RTT
Uptime · 36h
Complaints · 36h