From d72843056bf3990ab95677dddfb51de625e6bdb1 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:05:49 +0000 Subject: [PATCH] Add some documentation about backing up Synapse (#17931) Fixes: https://github.com/element-hq/element-meta/issues/2155 Fixes: https://github.com/element-hq/synapse/issues/2046 --- changelog.d/17931.doc | 1 + docs/SUMMARY.md | 1 + docs/postgres.md | 4 + docs/setup/installation.md | 4 + docs/usage/administration/backups.md | 125 ++++++++++++++++++ .../configuration/config_documentation.md | 15 ++- 6 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 changelog.d/17931.doc create mode 100644 docs/usage/administration/backups.md diff --git a/changelog.d/17931.doc b/changelog.d/17931.doc new file mode 100644 index 0000000000..9207cb0a1c --- /dev/null +++ b/changelog.d/17931.doc @@ -0,0 +1 @@ +Add documentation about backing up Synapse. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index c50121d5f7..fd91d9fa11 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -54,6 +54,7 @@ - [Using `synctl` with Workers](synctl_workers.md) - [Systemd](systemd-with-workers/README.md) - [Administration](usage/administration/README.md) + - [Backups](usage/administration/backups.md) - [Admin API](usage/administration/admin_api/README.md) - [Account Validity](admin_api/account_validity.md) - [Background Updates](usage/administration/admin_api/background_updates.md) diff --git a/docs/postgres.md b/docs/postgres.md index d06f0cda10..51670667e8 100644 --- a/docs/postgres.md +++ b/docs/postgres.md @@ -100,6 +100,10 @@ database: keepalives_count: 3 ``` +## Backups + +Don't forget to [back up](./usage/administration/backups.md#database) your database! + ## Tuning Postgres The default settings should be fine for most deployments. For larger diff --git a/docs/setup/installation.md b/docs/setup/installation.md index d717880aa5..bfeacab375 100644 --- a/docs/setup/installation.md +++ b/docs/setup/installation.md @@ -656,6 +656,10 @@ This also requires the optional `lxml` python dependency to be installed. This in turn requires the `libxml2` library to be available - on Debian/Ubuntu this means `apt-get install libxml2-dev`, or equivalent for your OS. +### Backups + +Don't forget to take [backups](../usage/administration/backups.md) of your new server! + ### Troubleshooting Installation `pip` seems to leak *lots* of memory during installation. For instance, a Linux diff --git a/docs/usage/administration/backups.md b/docs/usage/administration/backups.md new file mode 100644 index 0000000000..24d250179b --- /dev/null +++ b/docs/usage/administration/backups.md @@ -0,0 +1,125 @@ +# How to back up a Synapse homeserver + +It is critical to maintain good backups of your server, to guard against +hardware failure as well as potential corruption due to bugs or administrator +error. + +This page documents the things you will need to consider backing up as part of +a Synapse installation. + +## Configuration files + +Keep a copy of your configuration file (`homeserver.yaml`), as well as any +auxiliary config files it refers to such as the +[`log_config`](../configuration/config_documentation.md#log_config) file, +[`app_service_config_files`](../configuration/config_documentation.md#app_service_config_files). +Often, all such config files will be kept in a single directory such as +`/etc/synapse`, which will make this easier. + +## Server signing key + +Your server has a [signing +key](../configuration/config_documentation.md#signing_key_path) which it uses +to sign events and outgoing federation requests. It is easiest to back it up +with your configuration files, but an alternative is to have Synapse create a +new signing key if you have to restore. + +If you do decide to replace the signing key, you should add the old *public* +key to +[`old_signing_keys`](../configuration/config_documentation.md#old_signing_keys). + +## Database + +Synapse's support for SQLite is only suitable for testing purposes, so for the +purposes of this document, we'll assume you are using +[PostgreSQL](../../postgres.md). + +A full discussion of backup strategies for PostgreSQL is out of scope for this +document; see the [PostgreSQL +documentation](https://www.postgresql.org/docs/current/backup.html) for +detailed information. + +### Synapse-specfic details + + * Be very careful not to restore into a database that already has tables + present. At best, this will error; at worst, it will lead to subtle database + inconsistencies. + + * The `e2e_one_time_keys_json` table should **not** be backed up, or if it is + backed up, should be + [`TRUNCATE`d](https://www.postgresql.org/docs/current/sql-truncate.html) + after restoring the database before Synapse is started. + + [Background: restoring the database to an older backup can cause + used one-time-keys to be re-issued, causing subsequent [message decryption + errors](https://github.com/element-hq/element-meta/issues/2155). Clearing + all one-time-keys from the database ensures that this cannot happen, and + will prompt clients to generate and upload new one-time-keys.] + +### Quick and easy database backup and restore + +Typically, the easiest solution is to use `pg_dump` to take a copy of the whole +database. We recommend `pg_dump`'s custom dump format, as it produces +significantly smaller backup files. + +```shell +sudo -u postgres pg_dump -Fc --exclude-table-data e2e_one_time_keys_json synapse > synapse.dump +``` + +There is no need to stop Postgres or Synapse while `pg_dump` is running: it +will take a consistent snapshot of the databse. + +To restore, you will need to recreate the database as described in [Using +Postgres](../../postgres.md#set-up-database), +then load the dump into it with `pg_restore`: + +```shell +sudo -u postgres createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse +sudo -u postgres pg_restore -d synapse < synapse.dump +``` + +(If you forgot to exclude `e2e_one_time_keys_json` during `pg_dump`, remember +to connect to the new database and `TRUNCATE e2e_one_time_keys_json;` before +starting Synapse.) + +To reiterate: do **not** restore a dump over an existing database. + +Again, if you plan to run your homeserver at any sort of production level, we +recommend studying the PostgreSQL documentation on backup options. + +## Media store + +Synapse keeps a copy of media uploaded by users, including avatars and message +attachments, in its [Media +store](../configuration/config_documentation.md#media-store). + +It is a directory on the local disk, containing the following directories: + + * `local_content`: this is content uploaded by your local users. As a general + rule, you should back this up: it may represent the only copy of those + media files anywhere in the federation, and if they are lost, users will + see errors when viewing user or room avatars, and messages with attachments. + + * `local_thumbnails`: "thumbnails" of images uploaded by your users. If + [`dynamic_thumbnails`](../configuration/config_documentation.md#dynamic_thumbnails) + is enabled, these will be regenerated if they are removed from the disk, and + there is therefore no need to back them up. + + If `dynamic_thumbnails` is *not* enabled (the default): although this can + theoretically be regenerated from `local_content`, there is no tooling to do + so. We recommend that these are backed up too. + + * `remote_content`: this is a cache of content that was uploaded by a user on + another server, and has since been requested by a user on your own server. + + Typically there is no need to back up this directory: if a file in this directory + is removed, Synapse will attempt to fetch it again from the remote + server. + + * `remote_thumbnails`: thumbnails of images uploaded by users on other + servers. As with `remote_content`, there is normally no need to back this + up. + + * `url_cache`, `url_cache_thumbnails`: temporary caches of files downloaded + by the [URL previews](../../setup/installation.md#url-previews) feature. + These do not need to be backed up. diff --git a/docs/usage/configuration/config_documentation.md b/docs/usage/configuration/config_documentation.md index deb04570bb..005633e46b 100644 --- a/docs/usage/configuration/config_documentation.md +++ b/docs/usage/configuration/config_documentation.md @@ -3128,6 +3128,15 @@ it was last used. It is possible to build an entry from an old `signing.key` file using the `export_signing_key` script which is provided with synapse. +If you have lost the private key file, you can ask another server you trust to +tell you the public keys it has seen from your server. To fetch the keys from +`matrix.org`, try something like: + +``` +curl https://matrix-federation.matrix.org/_matrix/key/v2/query/myserver.example.com | + jq '.server_keys | map(.verify_keys) | add' +``` + Example configuration: ```yaml old_signing_keys: @@ -4391,9 +4400,9 @@ It is possible to scale the processes that handle sending outbound federation re by running a [`generic_worker`](../../workers.md#synapseappgeneric_worker) and adding it's [`worker_name`](#worker_name) to a `federation_sender_instances` map. Doing so will remove handling of this function from the main process. Multiple workers can be added to this map, in which case the work is -balanced across them. +balanced across them. -The way that the load balancing works is any outbound federation request will be assigned +The way that the load balancing works is any outbound federation request will be assigned to a federation sender worker based on the hash of the destination server name. This means that all requests being sent to the same destination will be processed by the same worker instance. Multiple `federation_sender_instances` are useful if there is a federation @@ -4750,7 +4759,7 @@ This setting has the following sub-options: * `only_for_direct_messages`: Whether invites should be automatically accepted for all room types, or only for direct messages. Defaults to false. * `only_from_local_users`: Whether to only automatically accept invites from users on this homeserver. Defaults to false. -* `worker_to_run_on`: Which worker to run this module on. This must match +* `worker_to_run_on`: Which worker to run this module on. This must match the "worker_name". If not set or `null`, invites will be accepted on the main process.