* Add NATS JetStream support Update shopify/sarama * Fix addresses * Don't change Addresses in Defaults * Update saramajetstream * Add missing error check Keep typing events for at least one minute * Use all configured NATS addresses * Update saramajetstream * Try setting up with NATS * Make sure NATS uses own persistent directory (TODO: make this configurable) * Update go.mod/go.sum * Jetstream package * Various other refactoring * Build fixes * Config tweaks, make random jetstream storage path for CI * Disable interest policies * Try to sane default on jetstream base path * Try to use in-memory for CI * Restore storage/retention * Update nats.go dependency * Adapt changes to config * Remove unneeded TopicFor * Dep update * Revert "Remove unneeded TopicFor" This reverts commit f5a4e4a339b6f94ec215778dca22204adaa893d1. * Revert changes made to streams * Fix build problems * Update nats-server * Update go.mod/go.sum * Roomserver input API queuing using NATS * Fix topic naming * Prometheus metrics * More refactoring to remove saramajetstream * Add missing topic * Don't try to populate map that doesn't exist * Roomserver output topic * Update go.mod/go.sum * Message acknowledgements * Ack tweaks * Try to resume transaction re-sends * Try to resume transaction re-sends * Update to matrix-org/gomatrixserverlib@91dadfb * Remove internal.PartitionStorer from components that don't consume keychanges * Try to reduce re-allocations a bit in resolveConflictsV2 * Tweak delivery options on RS input * Publish send-to-device messages into correct JetStream subject * Async and sync roomserver input * Update dendrite-config.yaml * Remove roomserver tests for now (they need rewriting) * Remove roomserver test again (was merged back in) * Update documentation * Docker updates * More Docker updates * Update Docker readme again * Fix lint issues * Send final event in `processEvent` synchronously (since this might stop Sytest from being so upset) * Don't report event rejection errors via `/send`, since apparently this is upsetting tests that don't expect that * Go 1.16 instead of Go 1.13 for upgrade tests and Complement * Revert "Don't report event rejection errors via `/send`, since apparently this is upsetting tests that don't expect that" This reverts commit 368675283fc44501f227639811bdb16dd5deef8c. * Don't report any errors on `/send` to see what fun that creates * Fix panics on closed channel sends * Enforce state key matches sender * Do the same for leave * Various tweaks to make tests happier Squashed commit of the following: commit 13f9028e7a63662759ce7c55504a9d2423058668 Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 15:47:14 2022 +0000 Do the same for leave commit e6be7f05c349fafbdddfe818337a17a60c867be1 Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 15:33:42 2022 +0000 Enforce state key matches sender commit 85ede6d64bf10ce9b91cdd6d80f87350ee55242f Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 14:07:04 2022 +0000 Fix panics on closed channel sends commit 9755494a98bed62450f8001d8128e40481d27e15 Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 13:38:22 2022 +0000 Don't report any errors on `/send` to see what fun that creates commit 3bb4f87b5dd56882febb4db5621db484c8789b7c Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 13:00:26 2022 +0000 Revert "Don't report event rejection errors via `/send`, since apparently this is upsetting tests that don't expect that" This reverts commit 368675283fc44501f227639811bdb16dd5deef8c. commit fe2673ed7be9559eaca134424e403a4faca100b0 Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 12:09:34 2022 +0000 Go 1.16 instead of Go 1.13 for upgrade tests and Complement commit 368675283fc44501f227639811bdb16dd5deef8c Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 11:51:45 2022 +0000 Don't report event rejection errors via `/send`, since apparently this is upsetting tests that don't expect that commit b028dfc08577bcf52e6cb498026e15fa5d46d07c Author: Neil Alexander <neilalexander@users.noreply.github.com> Date: Tue Jan 4 10:29:08 2022 +0000 Send final event in `processEvent` synchronously (since this might stop Sytest from being so upset) * Merge in NATS Server v2.6.6 and nats.go v1.13 into the in-process connection fork * Add `jetstream.WithJetStreamMessage` to make ack/nak-ing less messy, use process context in consumers * Fix consumer component name in federation API * Add comment explaining where streams are defined * Tweaks to roomserver input with comments * Finish that sentence that I apparently forgot to finish in INSTALL.md * Bump version number of config to 2 * Add comments around asynchronous sends to roomserver in processEventWithMissingState * More useful error message when the config version does not match * Set version in generate-config * Fix version in config.Defaults Co-authored-by: Neil Alexander <neilalexander@users.noreply.github.com>
9.9 KiB
Installing Dendrite
Dendrite can be run in one of two configurations:
-
Monolith mode: All components run in the same process. In this mode, it is possible to run an in-process NATS Server instead of running a standalone deployment. This will usually be the preferred model for low-to-mid volume deployments, providing the best balance between performance and resource usage.
-
Polylith mode: A cluster of individual components running in their own processes, dealing with different aspects of the Matrix protocol (see WIRING.md). Components communicate with each other using internal HTTP APIs and NATS Server. This will almost certainly be the preferred model for very large deployments but scalability comes with a cost. API calls are expensive and therefore a polylith deployment may end up using disproportionately more resources for a smaller number of users compared to a monolith deployment.
In almost all cases, it is recommended to run in monolith mode with PostgreSQL databases.
Regardless of whether you are running in polylith or monolith mode, each Dendrite component that requires storage has its own database connections. Both Postgres and SQLite are supported and can be mixed-and-matched across components as needed in the configuration file.
Be advised that Dendrite is still in development and it's not recommended for use in production environments just yet!
Requirements
Dendrite requires:
- Go 1.15 or higher
- PostgreSQL 12 or higher (if using PostgreSQL databases, not needed for SQLite)
If you want to run a polylith deployment, you also need:
- A standalone NATS Server deployment with JetStream enabled
Building Dendrite
Start by cloning the code:
git clone https://github.com/matrix-org/dendrite
cd dendrite
Then build it:
./build.sh
Install NATS Server
Follow the NATS Server installation instructions and then start your NATS deployment.
JetStream must be enabled, either by passing the -js
flag to nats-server
,
or by specifying the store_dir
option in the the jetstream
configuration.
Configuration
PostgreSQL database setup
Assuming that PostgreSQL 12 (or later) is installed:
-
Create role, choosing a new password when prompted:
sudo -u postgres createuser -P dendrite
At this point you have a choice on whether to run all of the Dendrite components from a single database, or for each component to have its own database. For most deployments, running from a single database will be sufficient, although you may wish to separate them if you plan to split out the databases across multiple machines in the future.
On macOS, omit sudo -u postgres
from the below commands.
-
If you want to run all Dendrite components from a single database:
sudo -u postgres createdb -O dendrite dendrite
... in which case your connection string will look like
postgres://user:pass@database/dendrite
. -
If you want to run each Dendrite component with its own database:
for i in mediaapi syncapi roomserver federationapi appservice keyserver userapi_accounts userapi_devices; do sudo -u postgres createdb -O dendrite dendrite_$i done
... in which case your connection string will look like
postgres://user:pass@database/dendrite_componentname
.
SQLite database setup
WARNING: SQLite is suitable for small experimental deployments only and should not be used in production - use PostgreSQL instead for any user-facing federating installation!
Dendrite can use the built-in SQLite database engine for small setups. The SQLite databases do not need to be pre-built - Dendrite will create them automatically at startup.
Server key generation
Each Dendrite installation requires:
- A unique Matrix signing private key
- A valid and trusted TLS certificate and private key
To generate a Matrix signing private key:
./bin/generate-keys --private-key matrix_key.pem
WARNING: Make sure take a safe backup of this key! You will likely need it if you want to reinstall Dendrite, or any other Matrix homeserver, on the same domain name in the future. If you lose this key, you may have trouble joining federated rooms.
For testing, you can generate a self-signed certificate and key, although this will not work for public federation:
./bin/generate-keys --tls-cert server.crt --tls-key server.key
If you have server keys from an older Synapse instance,
convert them to Dendrite's PEM
format and configure them as old_private_keys
in your config.
Configuration file
Create config file, based on dendrite-config.yaml
. Call it dendrite.yaml
. Things that will need editing include at least:
- The
server_name
entry to reflect the hostname of your Dendrite server - The
database
lines with an updated connection string based on your desired setup, e.g. replacingdatabase
with the name of the database:- For Postgres:
postgres://dendrite:password@localhost/database
, e.g.postgres://dendrite:password@localhost/dendrite_userapi_account
to connect to PostgreSQL with SSL/TLSpostgres://dendrite:password@localhost/dendrite_userapi_account?sslmode=disable
to connect to PostgreSQL without SSL/TLS
- For SQLite on disk:
file:component.db
orfile:///path/to/component.db
, e.g.file:userapi_account.db
- Postgres and SQLite can be mixed and matched on different components as desired.
- For Postgres:
- Either one of the following in the
jetstream
configuration section:- The
addresses
option — a list of one or more addresses of an external standalone NATS Server deployment - The
storage_path
— where on the filesystem the built-in NATS server should store durable queues, if using the built-in NATS server
- The
There are other options which may be useful so review them all. In particular,
if you are trying to federate from your Dendrite instance into public rooms
then configuring key_perspectives
(like matrix.org
in the sample) can
help to improve reliability considerably by allowing your homeserver to fetch
public keys for dead homeservers from somewhere else.
WARNING: Dendrite supports running all components from the same database in PostgreSQL mode, but this is NOT a supported configuration with SQLite. When using SQLite, all components MUST use their own database file.
Starting a monolith server
The monolith server can be started as shown below. By default it listens for
HTTP connections on port 8008, so you can configure your Matrix client to use
http://servername:8008
as the server:
./bin/dendrite-monolith-server
If you set --tls-cert
and --tls-key
as shown below, it will also listen
for HTTPS connections on port 8448:
./bin/dendrite-monolith-server --tls-cert=server.crt --tls-key=server.key
If the jetstream
section of the configuration contains no addresses
but does
contain a store_dir
, Dendrite will start up a built-in NATS JetStream node
automatically, eliminating the need to run a separate NATS server.
Starting a polylith deployment
The following contains scripts which will run all the required processes in order to point a Matrix client at Dendrite.
nginx (or other reverse proxy)
This is what your clients and federated hosts will talk to. It must forward requests onto the correct API server based on URL:
/_matrix/client
to the client API server/_matrix/federation
to the federation API server/_matrix/key
to the federation API server/_matrix/media
to the media API server
See docs/nginx/polylith-sample.conf
for a sample configuration.
Client API server
This is what implements CS API endpoints. Clients talk to this via the proxy in order to send messages, create and join rooms, etc.
./bin/dendrite-polylith-multi --config=dendrite.yaml clientapi
Sync server
This is what implements /sync
requests. Clients talk to this via the proxy
in order to receive messages.
./bin/dendrite-polylith-multi --config=dendrite.yaml syncapi
Media server
This implements /media
requests. Clients talk to this via the proxy in
order to upload and retrieve media.
./bin/dendrite-polylith-multi --config=dendrite.yaml mediaapi
Federation API server
This implements the federation API. Servers talk to this via the proxy in order to send transactions. This is only required if you want to support federation.
./bin/dendrite-polylith-multi --config=dendrite.yaml federationapi
Internal components
This refers to components that are not directly spoken to by clients. They are only contacted by other components. This includes the following components.
Room server
This is what implements the room DAG. Clients do not talk to this.
./bin/dendrite-polylith-multi --config=dendrite.yaml roomserver
Appservice server
This sends events from the network to application services running locally. This is only required if you want to support running application services on your homeserver.
./bin/dendrite-polylith-multi --config=dendrite.yaml appservice
Key server
This manages end-to-end encryption keys for users.
./bin/dendrite-polylith-multi --config=dendrite.yaml keyserver
EDU server
This manages processing EDUs such as typing, send-to-device events and presence. Clients do not talk to
./bin/dendrite-polylith-multi --config=dendrite.yaml eduserver
User server
This manages user accounts, device access tokens and user account data, amongst other things.
./bin/dendrite-polylith-multi --config=dendrite.yaml userapi