Run your own Matrix chat server, a guide to installing Synapse on Ubuntu 22.04

Having recently dived deeper into the world of Matrix , I’ve naturally set up my own home server by installing Synapse . It’s been a fun journey! This Matrix homeserver has become my go-to for chatting with friends and family over the past few months. Sure, there have been a few hiccups here and there, but overall I’m pleased with its performance.

If you’re new to Matrix and Synapse, getting everything up and running can seem a bit daunting. This article aims to walk you through the process, so you can get to the point where you’re able to register users and start chatting away.

Think of this guide as a mishmash of the official Synapse installation docs, with beginner-friendly explanations, alongside my own experiences and suggestions for taking things further.

I’m assuming you’ve got a fair bit of tech know-how, including knowledge of domains and DNS, basic Linux terminal skills, and a rough idea of what Matrix is.

Matrix

Why Synapse? I went for Synapse because it’s the most tried-and-tested Matrix server in terms of production and scaling. It gets regular updates, and offers a lot of configurability.

Specs? My setup runs on Ubuntu 22.04 LTS (Jammy), so that’s what this guide will focus on. You don’t need a super beefy machine – a couple of gigs of RAM should be plenty. But, if you’re not planning on joining massive public rooms, you could easily get by with less than 1GB.

Choose a Domain Name

First off, you’ll need a domain name. This will be your server’s identifier moving forward. Later, you’ll configure your DNS provider to direct requests for this domain to your server.

The name you pick will shape your user IDs, showing others how to reach you. In Matrix, user IDs look like @username:example.com, with the domain name coming after the colon :. When registering users, you can choose any username (the bit before the colon), but the domain name :example.com is set in stone.

Installing Synapse

Synapse Architecture

I installed Synapse directly on Ubuntu 22.04, using Debian packages from Element . Element is the company that founded Matrix and maintains Synapse. For other ways to install, including Docker, see here .

Add the matrix.org repository keys and install matrix-synapse-py3 & its dependencies:

sudo apt install -y lsb-release wget apt-transport-https
sudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" |
    sudo tee /etc/apt/sources.list.d/matrix-org.list
sudo apt update
sudo apt install matrix-synapse-py3

Setting Up the Database

Synapse supports both SQLite and PostgreSQL. But honestly, Synapse with PostgreSQL is better in almost every way, especially for anything beyond a demo. The Synapse team strongly recommends using PostgreSQL and thats what we’ll do.

Installing & Configuring PostgreSQL

To install PostgreSQL:

sudo apt install postgresql 
sudo apt install postgresql-client-common 
sudo systemctl start postgresql.service

Connect to PostgreSQL to setup a synapse_user and database for Synapse, remember to keep the synapse_user password somewhere safe!

sudo su -l postgres
createuser --pwprompt synapse_user
createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse

Next, tell Synapse to use the synapse database with your synapse_user credentials.

You’ll find all Synapse’s settings in a YAML file called homeserver.yaml. Add the following to /etc/matrix-synapse/homeserver.yaml:

database:
  name: psycopg2
  args:
    user: synapse_user
    password: [the password you created]
    database: synapse
    host: 127.0.0.1
    cp_min: 1
    cp_max: 25

Routing

Now, we need to make sure your messaging client (more on that later) and other Matrix servers can talk to yours.

Here’s what you’ll need to do.

DNS

You’ve likely purchased a domain name for your server.

Depending on your provider (e.g., GoDaddy or Cloudflare), you’ll need to tweak the DNS settings via their portal so that your domain points to your server’s IP. This way, any requests to yourdomain.com will reach your server and, by extension, the Synapse software we’re setting up.

Reverse Proxy & SSL

To securely direct requests to your Synapse server, set up a reverse proxy. This lets you expose Synapse’s required ports without giving it root privileges and allows SSL termination at the proxy level.

Setting up a reverse proxy can be a bit tricky. You can use popular options like Apache, Caddy, or Nginx for your reverse proxy. I had Apache already running, so it was a no-brainer for me.

I set up a new VirtualHost for my domain, forwarding the necessary URLs to Synapse: /_matrix and /_synapse/client.

Delegation & Ports

Matrix server to server communication operates on 8448 and client to server communication is on port 443. I made a change using Synapse’s delegation functionality to have both server-server and server-client communication on port 443 instead. This gave me the added bonus of being able to use Cloudflare’s DNS proxy setting, which hides your server’s IP address for security (Cloudflare does not support proxying traffic on 8448).

My VirtualHost file therefore listens on port 443 and looks like this:

<VirtualHost *:443>
        ServerName example.com
        AllowEncodedSlashes NoDecode
        ServerAdmin [email protected]
        ServerAlias example.com www.example.com
        DocumentRoot /var/www/html/example.com

        <Location /_matrix>
                RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
                ProxyPreserveHost On
                ProxyPass "http://127.0.0.1:8008/_matrix" nocanon
                ProxyPassReverse "http://127.0.0.1:8008/_matrix"
        </Location>

        <Location /_synapse/client>
                RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
                ProxyPreserveHost On
                ProxyPass "http://127.0.0.1:8008/_synapse/client" nocanon
                ProxyPassReverse "http://127.0.0.1:8008/_synapse/client"
        </Location>

        # Logging options
        # SSL Options
</VirtualHost>

Add this to a .conf file in your Apache2 sites-enabled directory, then give Apache2 a restart.

For a deeper dive into reverse proxies, including setups other than Apache2, check the reverse proxy documentation from the Synapse team.

SSL

The reverse proxy should handle SSL for you. LetsEncrypt is a straightforward way to set this up.

Head over to the certbot website for instructions on installing certificates on your machine. This will automatically tweak the VirtualHost file above. After that, restart Apache2, and you should be all set for secure communication.

Configuring Synapse

Before you start Synapse for the first time, have a look at the Synapse configuration manual to familiarise yourself with the various settings. These configuration options can be added to your homeserver.yaml file.

Here’s a good starting configuration:

pid_file: "/var/run/matrix-synapse.pid"
registration_shared_secret: [passphrase]
listeners:
  - port: 8008
    tls: false
    type: http
    x_forwarded: true
    bind_addresses: ['::1', '127.0.0.1']
    resources:
      - names: [client, federation, media]
        compress: false

  - port: 9000
    type: metrics
    bind_addresses: ['::1', '127.0.0.1']

database:
  name: psycopg2
  args:
    user: synapse_user
    password: [passphrase]
    database: synapse
    host: 127.0.0.1
    cp_min: 1
    cp_max: 25

log_config: "/etc/matrix-synapse/log.yaml"
media_store_path: /var/lib/matrix-synapse/media
signing_key_path: "/etc/matrix-synapse/homeserver.signing.key"
trusted_key_servers:
  - server_name: "matrix.org"
user_directory:
    enabled: false
    search_all_users: false
    prefer_local_users: false

presence:
  enabled: false

enable_metrics: true

enable_media_repo: true
max_upload_size: 500M
media_retention:
      local_media_lifetime: 45d
      remote_media_lifetime: 45d

forgotten_room_retention_period: 7d

event_cache_size: 200K
federation_rc_concurrent: 3
federation_rc_reject_limit: 50
federation_rc_sleep_delay: 500
federation_rc_sleep_limit: 10
federation_rc_window_size: 10000
rc_message_burst_count: 10
rc_messages_per_second: 10
gc_thresholds: [1500, 20, 10]
caches:
    global_factor: 5

    expire_caches: true
    cache_entry_ttl: 10m

    cache_autotuning:
        max_cache_memory_usage: 600M
        target_cache_memory_usage: 400M
        min_cache_ttl: 30s

    per_cache_factors:
        get_current_state_ids: 3
        _get_joined_users_from_context: 3
        get_users_in_room: 3
        get_destination_retry_timings: 10
        _get_joined_profile_from_event_id: 10
        get_unread_event_push_actions_by_room_for_user: 20

This includes some sensible caching and tuning settings (thanks to the Tech Lead of Synapse, Erik Johnston !) and disables presence to save on CPU. It also keeps the user directory private, with a placeholder for your registration_shared_secret, which you’ll use to create users.

Start Synapse!

Finally go ahead and start Synapse..

systemctl restart matrix-synapse

At this point, give the Matrix Federation Tester a whirl by entering your domain name. This tool checks if your server is reachable on the expected ports. If you hit any issues, it’s likely to do with the reverse proxy or delegation setup, assuming there’s nothing amiss in the Synapse logs.

Then, create your first user and follow the prompts:

register_new_matrix_user -c /etc/matrix-synapse/homeserver.yaml

Pick a Client and Sign In

Woohoo! Your Matrix homeserver is up and running 🚀

Now, choose a client or app to log in with.

I went with the Element app from the iOS app store. It let me log into my server using the credentials from above. Element has downloads available for most platforms.

Since then, Element X has been released and I’d recommend giving it a go..

Element X

Element X is categorised as the latest generation of Matrix clients. It’s super speedy, modern, and its feature set is steadily catching up with the last generation apps.

There’s a bit of a catch – you need to set up ‘sliding sync’, another app on your server, to use Element X. The hope is that sliding sync will eventually be integrated into Synapse, making this extra step unnecessary.

For now, follow the setup instructions on the sliding-sync GitHub page , then tweak your reverse proxy settings as needed.

Using Apache2 as above and running sliding-sync on port 8009:

        <Location /_matrix/client/unstable/org.matrix.msc3575/sync>
                RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
                ProxyPreserveHost On
                ProxyPass "http://127.0.0.1:8009/_matrix/client/unstable/org.matrix.msc3575/sync" nocanon
                ProxyPassReverse "http://127.0.0.1:8009/_matrix/client/unstable/org.matrix.msc3575/sync"
        </Location>

Now go and grab Element X from your app store and give it a go.

Message me on Matrix!

What’s Next?

The world’s your oyster, here are some next steps and improvements I made after installing Synapse.

👥 Get some pals (or make some dummy accounts) signed up and start messaging.

🏛️ Dive into some public rooms and check out the federated wonder that is Matrix. But, a heads-up – steer clear of matrix-hq:matrix.org at first. It’s the biggest room on Matrix, and your server might struggle a bit trying to join.

🌉 Bridge the gap! With Matrix, you can chat across different platforms through something called bridges, like WhatsApp , Instagram , and Signal .

📈 For a performance boost, consider setting up Synapse Workers .

💻 Keep an eye on things by adding monitoring and alerting. I’ve enabled the Synapse metrics endpoint in the homeserver.yaml above. Hook it up to Prometheus and set up a Grafana dashboard (heres one from the Synapse team) for real-time insights.

🚀 Speed things up with a local DNS server. Synapse does a ton of DNS queries, especially in big public rooms. A DNS server like dnsmasq can significantly boost performance.

🛜 Lastly, the biggest bottleneck in performance I experienced was actually down to the poor specs of my ISP provided router. It couldn’t handle the number of requests that Synapse demands when you’re part of a few large rooms. Upgrading to a more business orientated router dramatically improved my overall performance and experience.

Related Posts

Connecting Differently: The [Matrix] Approach to Communication