Matrix is an open standard that enables modern chat and voice and video. It is federated (like email) so you can run your own server and still communicate with others running their own servers or who have registered accounts with other servers. If you’d like to try it, check out Riot; a graphical client that can run in the browser, desktop, or on a mobile device.
Synapse is an open source server implementation of Matrix, and currently the standard server to use when setting up a Matrix homeserver. There are already packages and options in NixOS to setup Synapse.
We had been using Telegram as our sole chat service for about four years, however the fact that Telegram is a closed network (meaning you cannot run your own server) has been a growing concern for us. We care about our privacy and independence. Running our own Matrix homeserver allows chats between ourselves to stay on our server and frees us from being dependant on a provider for our chat service. Further, Matrix’s end-to-end encryption (still in beta) works between multiple users each having multiple devices, while Telegram’s end-to-end only works between one-to-one chats.
Before starting, I assume you already have a NixOS server and a domain name.
Setup DNS
You have a few options when setting up DNS. My preference is to have a subdomain like matrix.example.com
point to my matrix server and then setup a SRV
record so that our users full username will by @user:example.com
instead of @user:matrix.example.com
. You can have the base domain, example.com
, point to the matrix server to get the same effect, but I like having the flexibility of using a subdomain.
My DNS records look like this:
1 2 |
_matrix._tcp.example.com. 1800 IN SRV 10 0 8448 matrix.example.com. matrix 1800 IN A 1.2.3.4 |
You’ll need to replace example.com
and the IPv4 address 1.2.3.4
with your own values. You could also use a AAAA
record for IPv6. I did not use IPv6 since my host (currently Scaleway) does not provide IPv6 addresses that persist after reboot.
The SRV
record is in this format:
1
|
_matrix._tcp.<yourdomain.com.> <ttl> IN SRV 10 0 <port> <synapse.server.name.> |
The period (.
) at the end of the domains is important to include if you are using the full domain name. Without the period at the end, the base domain name is assumed and appended. For example, matrix
would translate to matrix.example.com
if your base domain was example.com
.
Setup PostgreSQL
Synapse supports using either SQLite (the default) or PostgreSQL. If you decide you are fine with using SQLite, you can skip this step.
Add the following snippet to configuration.nix
:
|
|
Then apply the change by running:
1
|
$ sudo nixos-rebuild switch |
This should start PostgreSQL. Next, you’ll want to create a user and a database for Synapse:
To connect to the PostgreSQL server, run:
1
|
$ sudo -u postgres psql |
Execute the following SQL:
|
|
Then to quit psql
, run:
1
|
postgres=# \q |
I named the user and the database matrix-synapse
since that is the default username the Synapse server will run as once we enable it and by default PostgreSQL uses the process owner to authenticate users.
Edit: After doing an update via nixos-rebuild switch --upgrade
, the matrix-synapse service did not run. The reason is that an ExecStartPre=
in the Systemd service that checks to see if a file at /var/lib/matrix-synapse/db-created
exists and creates the matrix-synapse
user and database (essentially what I did by hand). Creating an empty file where it expected solved this.
Configure Synapse
Configuring Synapse on NixOS is fairly easy. Many options you would set in in the homeserver.yaml
file are available as NixOS options.
Add the following snippet to your configuration.nix
file:
|
|
Replace the server_name
with your own domain. The server_name
option specifies the hostname other servers will use to connect to this server and the last part of user IDs.
Replace the registration_shared_secret
with your own. You can generate one if you install pwgen
and run pwgen -s 64 1
. This option will allow you to register users via the command line later.
The database_type
and database_args
options configure Synapse to use the PostgreSQL database we setup earlier. If you prefer to use SQLite, these options can be omitted and a SQLite database will be stored as /var/lib/matrix-synapse/homeserver.db
.
The extraConfig
option allows you to specify arbitrary extra configuration that gets appended to the homeserver.yaml
file after other configuration options. In my example, I set the max_upload_size
to 50MB, allowing video files to be transfered that are up to 50MB. The default is 10MB and I found that users who had signed up with Matrix.org accounts could upload videos that were larger than 10MB but I couldn’t download them. After opening issue #2824 on GitHub a helpful developer let me know that the max_upload_size
also determines the maximum download size via federation.
Once you are ready, run the following to apply the configuration changes:
1
|
$ sudo nixos-rebuild switch |
You should be able to connect to your server via the URL https://matrix.example.com:8448/
, if you replace example.com
with your own domain. Your browser will alert you that you are navigating to an insecure site, but this is because Synapse uses self-signed certificates by default. You should be able to go into advanced options in your browser and add a temporary exception to continue to the login screen.
Registering a User
You can either open up user registration online or register users via the command-line. Since my server is a private server I only want to allow registration via the command-line.
Synapse comes with a script named register_new_matrix_user
, but this won’t be found in your PATH
after you enable the service. You have to find this in /nix/store
and the easiest way I have found is to run systemctl status matrix-synapse
which will output something similar to the following:
1 2 3 4 5 6 7 8 9 |
$ systemctl status matrix-synapse ● matrix-synapse.service - Synapse Matrix homeserver Loaded: loaded (/nix/store/g918vn57j2l1zviqgk9rgpy6id3qmn3n-unit-matrix-synapse.service/matrix-synapse.service; > Active: active (running) since Sun 2018-02-04 15:26:59 EST; 32min ago Process: 26139 ExecStartPre=/nix/store/hz7zsqjzz91ra5zh9sf0bvazb87pp4dc-unit-script/bin/matrix-synapse-pre-start > Main PID: 26222 (.homeserver-wra) Tasks: 7 (limit: 4915) CGroup: /system.slice/matrix-synapse.service └─26222 /nix/store/6yb5rvr6rvgvx8ylpchwz808djfw07rb-python-2.7.14/bin/python2.7 /nix/store/xh56g1s5abr9c> |
In the Loaded:
line you’ll find the path to the Systemd service file that is loaded for the server. In my case, it’s /nix/store/g918vn57j2l1zviqgk9rgpy6id3qmn3n-unit-matrix-synapse.service/matrix-synapse.service
, but this will possibly be a different path for you. Read the contents of this file by running:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ cat /nix/store/g918vn57j2l1zviqgk9rgpy6id3qmn3n-unit-matrix-synapse.service/matrix-synapse.service [Unit] After=network.target Description=Synapse Matrix homeserver [Service] # ... ExecStart=/nix/store/xh56g1s5abr9c1r9q3qkjdba9j6d9fj5-matrix-synapse-0.26.0/bin/homeserver \ --config-path /nix/store/b66rpj1jmnmgq6wgrbab32j51pxz0ldm-homeserver.yaml \ --keys-directory /var/lib/matrix-synapse # ... |
You want to look at the ExecStart=
within the [Service]
section to find the directory where the process is being run for Synapse. The register_new_matrix_user
script is kept in the same directory. You also want to find where the homeserver.yaml
is kept so the registration script can read the registration_shared_secret
from it.
In my case, I will run the following:
1 2 3 4 5 6 7 8 |
$ /nix/store/xh56g1s5abr9c1r9q3qkjdba9j6d9fj5-matrix-synapse-0.26.0/bin/register_new_matrix_user \ -c /nix/store/b66rpj1jmnmgq6wgrbab32j51pxz0ldm-homeserver.yaml New user localpart: myuser Password: Confirm password: Make admin [no]: Success! |
The paths for you will likely be different since part of the path for each Nix derivative is a cryptographic hash. This is a part of how NixOS sandboxes dependencies on the filesystem.
If you want to enable users to create accounts on your server for themselves, you can set the following options:
|
|
This enables a ReCAPTCHA challenge to new registrants to prevent bots from creating accounts on your server. If you do not want a ReCAPTCHA challenge, you can omit the related options.
You should now be at a point where you can login to your server.
Setup Certificates with Let’s Encrypt
You can operate your server with self-signed certificates, but users will be presented with a pretty big warning from their browser and some clients, like Riot, won’t let you login without a signed certificate from a trusted certificate authority (CA). Thankfully we can get a free certificate from Let’s Encrypt with NixOS.
Update the options to your configuration.nix
to be similar to the following:
|
|
Be sure to replace example.com
with your own domain.
We use services.nginx
to create a virtual host, matrix.example.com
, and set enableACME
to true
. This will automatically fetch certs from Let’s Encrypt for that host and also sets up auto-renewal.
The security.acme.certs
option is used to further configure what happens when we fetch certs. We allow the group matrix-synapse
to read the certs and keys so the Synapse process can be configured with them, which is required for federation. We also set it up so that both Nginx and Synapse get restarted after certificate renewal.
For services.matrix-synapse
the options tls_certificate_path
and tls_private_key_path
have been added with the paths to the certificate and key. We also opened up a new listener that only listens locally, provides the client, and does not use TLS on port 8008
. Nginx is setup to proxy to this new listener and forces SSL. The default is to only listen on 8448
, the federation port. Since we want to preserve this, the default configuration for the federation port listener is copied.
Update your server with the following command:
1
|
$ sudo nixos-rebuild switch |
You should now be able to navigate to https://matrix.example.com/
without your browser warning you of an insecure connection. You can also now connect to your server with Riot. Select the Custom Server option when logging in and enter https://matrix.example.com/
as your Home server URL (leave the Identity server URL option alone).
Happy chatting!