Run Your Own Matrix Homeserver on NixOS

howto, matrix, nix

Due to current events, alternatives to Discord have been getting a lot of attention recently. As much as I would love for Matrix to succeed here, it isn’t ready for most non-technical users. However, if you are a technical person…

This guide assumes a few things:

  • You’ll be running the server on a computer that’s publically accessible over the internet
  • You have a domain that points to said machine
  • Said machine is running NixOS

Since “Matrix” is a protocol, there are several server implementations - with the most widely used (by far) being Synapse. It was the first implementation, and it’s used to host the official matrix.org server - however, it has performance issues and eats a bunch of RAM and CPU. The main alternative, which is what this guide will use, is Continuwuity1.

Continuwuity is packaged in nixpkgs and already has a NixOS module, which makes the setup process just involve enabling the service and some settings:

let
your-domain = "example.com";
in
services.matrix-continuwuity = {
enable = true;
settings.global = {
server_name = your-domain;
new_user_displayname_suffix = "";
address = null;
unix_socket_path = "/run/continuwuity/continuwuity.sock";
well_known.client = "https://matrix.${your-domain}";
well_known.server = "matrix.${your-domain}:443";
# just in case!
lockdown_public_room_directory = true;
allow_room_creation = false;
require_auth_for_profile_requests = true; # no user enumeration
url_preview_domain_explicit_allowlist = [ "github.com" ];
log = "INFO,conduwuit_core::matrix::state_res=off"; # cleaner logs
};
};

We also need to expose the server to the public internet. Caddy makes this super easy, handles TLS certificates automatically, etc.

let
your-domain = "example.com";
in
services.caddy = {
enable = true;
virtualHosts = {
"${your-domain}".extraConfig = ''
reverse_proxy /.well-known/matrix/* unix//run/continuwuity/continuwuity.sock
'';
"matrix.${your-domain}".extraConfig = ''
route {
@api path /_matrix/* /_continuwuity/*
reverse_proxy @api unix//run/continuwuity/continuwuity.sock
}
'';
};
};
users.users.caddy.extraGroups = [ "continuwuity" ]; # give caddy access to continuwuity's unix socket
networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 443 ];

To test that the server is accessible to the wider network, you can use the Matrix Federation Tester.

Now that the server is up, running and working, you need a client to use to connect. I prefer Cinny since it’s a self-contained web application and has a good UI, but there are many others. You can use the official instance the developer runs at app.cinny.im, or deploy your own:

"matrix.${your-domain}".extraConfig = ''
route {
@api path /_matrix/* /_continuwuity/*
reverse_proxy @api unix//run/continuwuity/continuwuity.sock
root * ${
pkgs.cinny.override {
conf = {
defaultHomeserver = 0;
homeserverList = [ your-domain ];
allowCustomHomeservers = false;
featuredCommunities = {
openAsDefault = false;
spaces = [
"#community:matrix.org"
"#cinny-space:matrix.org"
"#space:continuwuity.org"
"#space:nixos.org"
];
rooms = [ ];
servers = [
"matrix.org"
"mozilla.org"
"nixos.org"
];
};
};
}
}
try_files {path} / index.html
file_server
}
'';

Now it’s time to register your account! Your client will ask for a registration token, which is in the service logs:

Terminal window
sudo journalctl -u continuwuity | grep "registration token"

If you run into any issues, the Continuwuity matrix space is super active and helpful. You might need to create an account on different server like matrix.org if your own isn’t fully set up yet :)

Footnotes

  1. Of all the non-synapse servers - Dendrite is in maintenance mode, Conduit has less active development, and the primary maintainer of Tuwunel is banned by the Matrix Foundation