The file should be a plain text file, containing only the secret.
-Synapse reads the secret from the given file once at startup.
+The file should be a plain text file, containing only the secret. Synapse reads the secret from the given file once at startup.
+Controls sending of outbound federation transactions on the main process.
-Set to false if using a federation sender worker.
-Defaults to true.
+Controls sending of outbound federation transactions on the main process. Set to false if using a federation sender worker.
+It is possible to scale the processes that handle sending outbound federation requests
-by running a generic_worker and adding it's 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.
-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
-with multiple servers.
-This configuration setting must be shared between all workers handling federation
-sending, and if changed all federation sender workers must be stopped at the same time
-and then started, to ensure that all instances are running with the same config (otherwise
-events may be dropped).
-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 with multiple servers.
+This configuration setting must be shared between all workers handling federation sending, and if changed all federation sender workers must be stopped at the same time and then started, to ensure that all instances are running with the same config (otherwise events may be dropped).
+Experimental: When using workers you can define which workers should
-handle writing to streams such as event persistence and typing notifications.
-Any worker specified here must also be in the instance_map.
-These options configure an individual worker, in its worker configuration file.
-They should be not be provided when configuring the main process.
-These options configure an individual worker, in its worker configuration file. They should be not be provided when configuring the main process.
+There is no default for this option.
A unique name for the worker. The worker needs a name to be addressed in
-further parameters and identification in log files. We strongly recommend
-giving each worker a unique worker_name.
+Specifies whether the worker should be started as a daemon process.
-If Synapse is being managed by systemd, this option
-must be omitted or set to false.
-
Configuration settings related to background updates.
-Background updates are database updates that are run in the background in batches.
-The duration, minimum batch size, default batch size, whether to sleep between batches and if so, how long to
-sleep can all be configured. This is helpful to speed up or slow down the updates.
-This setting has the following sub-options:
+(object) Background updates are database updates that are run in the background in batches. The duration, minimum batch size, default batch size, whether to sleep between batches and if so, how long to sleep can all be configured. This is helpful to speed up or slow down the updates.
+This setting has the following sub-options:
-background_update_duration_ms: How long in milliseconds to run a batch of background updates for. Defaults to 100.
-Set a different time to change the default.
-sleep_enabled: Whether to sleep between updates. Defaults to true. Set to false to change the default.
-sleep_duration_ms: If sleeping between updates, how long in milliseconds to sleep for. Defaults to 1000.
-Set a duration to change the default.
-min_batch_size: Minimum size a batch of background updates can be. Must be greater than 0. Defaults to 1.
-Set a size to change the default.
-default_batch_size: The batch size to use for the first iteration of a new background update. The default is 100.
-Set a size to change the default.
+-
+
background_update_duration_ms (integer): How long in milliseconds to run a batch of background updates for. Defaults to 100.
+
+-
+
sleep_enabled (boolean): Whether to sleep between updates. Defaults to true.
+
+-
+
sleep_duration_ms (integer): If sleeping between updates, how long in milliseconds to sleep for. Defaults to 1000.
+
+-
+
min_batch_size (integer): Minimum size a batch of background updates can be. Must be greater than 0. Defaults to 1.
+
+-
+
default_batch_size (integer): The batch size to use for the first iteration of a new background update. Defaults to 100.
+
Example configuration:
background_updates:
- background_update_duration_ms: 500
- sleep_enabled: false
- sleep_duration_ms: 300
- min_batch_size: 10
- default_batch_size: 50
+ background_update_duration_ms: 500
+ sleep_enabled: false
+ sleep_duration_ms: 300
+ min_batch_size: 10
+ default_batch_size: 50
Configuration settings related to automatically accepting invites.
-Automatically accepting invites controls whether users are presented with an invite request or if they
-are instead automatically joined to a room when receiving an invite. Set the enabled sub-option to true to
-enable auto-accepting invites. Defaults to false.
-This setting has the following sub-options:
+(object) Automatically accepting invites controls whether users are presented with an invite request or if they are instead automatically joined to a room when receiving an invite. Set the enabled sub-option to true to enable auto-accepting invites.
+NOTE: Care should be taken not to enable this setting if the synapse_auto_accept_invite module is enabled and installed. The two modules will compete to perform the same task and may result in undesired behaviour. For example, multiple join events could be generated from a single invite.
+This setting has the following sub-options:
-enabled: Whether to run the auto-accept invites logic. Defaults to false.
-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
-the "worker_name". If not set or null, invites will be accepted on the
-main process.
+-
+
enabled (boolean): Whether to run the auto-accept invites logic. Defaults to false.
+
+-
+
only_for_direct_messages (boolean): Whether invites should be automatically accepted for all room types, or only for direct messages. Defaults to false.
+
+-
+
only_from_local_users (boolean): Whether to only automatically accept invites from users on this homeserver. Defaults to false.
+
+-
+
worker_to_run_on (string|null): 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. Defaults to null.
+
-NOTE: Care should be taken not to enable this setting if the synapse_auto_accept_invite module is enabled and installed.
-The two modules will compete to perform the same task and may result in undesired behaviour. For example, multiple join
-events could be generated from a single invite.
Example configuration:
auto_accept_invites:
- enabled: true
- only_for_direct_messages: true
- only_from_local_users: true
- worker_to_run_on: "worker_1"
+ enabled: true
+ only_for_direct_messages: true
+ only_from_local_users: true
+ worker_to_run_on: worker_1
Below is a sample homeserver configuration file. The homeserver configuration file
@@ -8358,7 +7955,7 @@ loggers:
The above logging config will set Synapse as 'INFO' logging level by default,
with the SQL layer at 'WARNING', and will log JSON formatted messages to a
remote endpoint at 10.1.2.3:9999.
-
+
Synapse uses parametrised templates to generate the content of emails it sends and
webpages it shows to users.
By default, Synapse will use the templates listed here.
@@ -10786,9 +10383,15 @@ this callback.
First introduced in Synapse v1.37.0
Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated.
-async def user_may_create_room(user_id: str) -> Union["synapse.module_api.NOT_SPAM", "synapse.module_api.errors.Codes", bool]
+Changed in Synapse v1.132.0: Added the room_config argument. Callbacks that only expect a single user_id argument are still supported.
+async def user_may_create_room(user_id: str, room_config: synapse.module_api.JsonDict) -> Union["synapse.module_api.NOT_SPAM", "synapse.module_api.errors.Codes", bool]
Called when processing a room creation request.
+The arguments passed to this callback are:
+
+user_id: The Matrix user ID of the user (e.g. @alice:example.com).
+room_config: The contents of the body of a /createRoom request as a dictionary.
+
The callback must return one of:
-
@@ -10867,6 +10470,35 @@ callback returns
synapse.module_api.NOT_SPAM, Synapse falls through
The value of the first callback that does not return synapse.module_api.NOT_SPAM will
be used. If this happens, Synapse will not call any of the subsequent implementations of
this callback.
+
+First introduced in Synapse v1.132.0
+async def user_may_send_state_event(user_id: str, room_id: str, event_type: str, state_key: str, content: JsonDict) -> Union["synapse.module_api.NOT_SPAM", "synapse.module_api.errors.Codes"]
+
+
+Caution: This callback is currently experimental . The method signature or behaviour
+may change without notice.
+
+Called when processing a request to send state events to a room.
+The arguments passed to this callback are:
+
+user_id: The Matrix user ID of the user (e.g. @alice:example.com) sending the state event.
+room_id: The ID of the room that the requested state event is being sent to.
+event_type: The requested type of event.
+state_key: The requested state key.
+content: The requested event contents.
+
+The callback must return one of:
+
+synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still
+decide to reject it.
+synapse.module_api.errors.Codes to reject the operation with an error code. In case
+of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code.
+
+If multiple modules implement this callback, they will be considered in order. If a
+callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one.
+The value of the first callback that does not return synapse.module_api.NOT_SPAM will
+be used. If this happens, Synapse will not call any of the subsequent implementations of
+this callback.
First introduced in Synapse v1.37.0
async def check_username_for_spam(user_profile: synapse.module_api.UserProfile, requester_id: str) -> bool
@@ -11807,6 +11439,87 @@ be taken to ensure with respect to performance.
by Synapse itself.
If multiple such callbacks try to add the same field to an event's unsigned
section, the last-registered callback wins.
+
+Media repository callbacks allow module developers to customise the behaviour of the
+media repository on a per user basis. Media repository callbacks can be registered
+using the module API's register_media_repository_callbacks method.
+The available media repository callbacks are:
+
+First introduced in Synapse v1.132.0
+async def get_media_config_for_user(user_id: str) -> Optional[JsonDict]
+
+
+Caution: This callback is currently experimental . The method signature or behaviour
+may change without notice.
+
+Called when processing a request from a client for the
+media config endpoint.
+The arguments passed to this callback are:
+
+user_id: The Matrix user ID of the user (e.g. @alice:example.com) making the request.
+
+If the callback returns a dictionary then it will be used as the body of the response to the
+client.
+If multiple modules implement this callback, they will be considered in order. If a
+callback returns None, Synapse falls through to the next one. The value of the first
+callback that does not return None will be used. If this happens, Synapse will not call
+any of the subsequent implementations of this callback.
+If no module returns a non-None value then the default media config will be returned.
+
+First introduced in Synapse v1.132.0
+async def is_user_allowed_to_upload_media_of_size(user_id: str, size: int) -> bool
+
+
+Caution: This callback is currently experimental . The method signature or behaviour
+may change without notice.
+
+Called before media is accepted for upload from a user, in case the module needs to
+enforce a different limit for the particular user.
+The arguments passed to this callback are:
+
+user_id: The Matrix user ID of the user (e.g. @alice:example.com) making the request.
+size: The size in bytes of media that is being requested to upload.
+
+If the module returns False, the current request will be denied with the error code
+M_TOO_LARGE and the HTTP status code 413.
+If multiple modules implement this callback, they will be considered in order. If a callback
+returns True, Synapse falls through to the next one. The value of the first callback that
+returns False will be used. If this happens, Synapse will not call any of the subsequent
+implementations of this callback.
+
+Ratelimit callbacks allow module developers to override ratelimit settings dynamically whilst
+Synapse is running. Ratelimit callbacks can be registered using the module API's
+register_ratelimit_callbacks method.
+The available ratelimit callbacks are:
+
+First introduced in Synapse v1.132.0
+async def get_ratelimit_override_for_user(user: str, limiter_name: str) -> Optional[synapse.module_api.RatelimitOverride]
+
+
+Caution: This callback is currently experimental . The method signature or behaviour
+may change without notice.
+
+Called when constructing a ratelimiter of a particular type for a user. The module can
+return a messages_per_second and burst_count to be used, or None if
+the default settings are adequate. The user is represented by their Matrix user ID
+(e.g. @alice:example.com). The limiter name is usually taken from the RatelimitSettings key
+value.
+The limiters that are currently supported are:
+
+rc_invites.per_room
+rc_invites.per_user
+rc_invites.per_issuer
+
+The RatelimitOverride return type has the following fields:
+
+per_second: float. The number of actions that can be performed in a second. 0.0 means that ratelimiting is disabled.
+burst_count: int. The number of actions that can be performed before being limited.
+
+If multiple modules implement this callback, they will be considered in order. If a
+callback returns None, Synapse falls through to the next one. The value of the first
+callback that does not return None will be used. If this happens, Synapse will not call
+any of the subsequent implementations of this callback. If no module returns a non-None value
+then the default settings will be used.
In order to port a module that uses Synapse's old module interface, its author needs to:
@@ -14722,6 +14435,61 @@ that were deleted.
]
}
+
+This API returns information about scheduled tasks.
+To use it, you will need to authenticate by providing an access_token
+for a server admin: see Admin API.
+The api is:
+GET /_synapse/admin/v1/scheduled_tasks
+
+It returns a JSON body like the following:
+{
+ "scheduled_tasks": [
+ {
+ "id": "GSA124oegf1",
+ "action": "shutdown_room",
+ "status": "complete",
+ "timestamp_ms": 23423523,
+ "resource_id": "!roomid",
+ "result": "some result",
+ "error": null
+ }
+ ]
+}
+
+Query parameters:
+
+-
+
action_name: string - Is optional. Returns only the scheduled tasks with the given action name.
+
+-
+
resource_id: string - Is optional. Returns only the scheduled tasks with the given resource id.
+
+-
+
status: string - Is optional. Returns only the scheduled tasks matching the given status, one of
+
+- "scheduled" - Task is scheduled but not active
+- "active" - Task is active and probably running, and if not will be run on next scheduler loop run
+- "complete" - Task has completed successfully
+- "failed" - Task is over and either returned a failed status, or had an exception
+
+
+-
+
max_timestamp: int - Is optional. Returns only the scheduled tasks with a timestamp inferior to the specified one.
+
+
+Response
+The following fields are returned in the JSON response body along with a 200 HTTP status code:
+
+id: string - ID of scheduled task.
+action: string - The name of the scheduled task's action.
+status: string - The status of the scheduled task.
+timestamp_ms: integer - The timestamp (in milliseconds since the unix epoch) of the given task - If the status is "scheduled" then this represents when it should be launched.
+Otherwise it represents the last time this task got a change of state.
+resource_id: Optional string - The resource id of the scheduled task, if it possesses one
+result: Optional Json - Any result of the scheduled task, if given
+error: Optional string - If the task has the status "failed", the error associated with this failure
+
The API to send notices is as follows:
POST /_synapse/admin/v1/send_server_notice
@@ -15034,7 +14802,8 @@ deactivating and erasing users see configuration.
@@ -15700,7 +15469,8 @@ going through UIA.
"last_seen_ip": "1.2.3.4",
"last_seen_user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0",
"last_seen_ts": 1474491775024,
- "user_id": "<user_id>"
+ "user_id": "<user_id>",
+ "dehydrated": false
},
{
"device_id": "AUIECTSRND",
@@ -15708,7 +15478,8 @@ going through UIA.
"last_seen_ip": "1.2.3.5",
"last_seen_user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0",
"last_seen_ts": 1474491775025,
- "user_id": "<user_id>"
+ "user_id": "<user_id>",
+ "dehydrated": false
}
],
"total": 2
@@ -15736,6 +15507,7 @@ Absent if no name has been set.
last_seen_ts - The timestamp (in milliseconds since the unix epoch) when this
devices was last seen. (May be a few minutes out of date, for efficiency reasons).
user_id - Owner of device.
+dehydrated - Whether the device is a dehydrated device.
@@ -16855,7 +16627,7 @@ present this information through a series of pretty graphs.
The "Outgoing EDUs by type" chart shows the EDUs within outgoing federation requests by type: m.device_list_update, m.direct_to_device, m.presence, m.receipt, m.typing.
If you see a large number of m.presence EDUs and are having trouble with too much CPU load, you can disable presence in the Synapse config. See also #3971.
-
+


This is quite a useful graph. It shows how many times Synapse attempts to retrieve a piece of data from a cache which the cache did not contain, thus resulting in a call to the database. We can see here that the _get_joined_profile_from_event_id cache is being requested a lot, and often the data we're after is not cached.
@@ -17296,7 +17068,7 @@ can be done by installing the libjemalloc2 package and adding this
line to /etc/default/matrix-synapse:
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
-Note: You may need to set PYTHONMALLOC=malloc to ensure that jemalloc can accurately calculate memory usage. By default, Python uses its internal small-object allocator, which may interfere with jemalloc's ability to track memory consumption correctly. This could prevent the cache_autotuning feature from functioning as expected, as the Python allocator may not reach the memory threshold set by max_cache_memory_usage, thus not triggering the cache eviction process.
+Note: You may need to set PYTHONMALLOC=malloc to ensure that jemalloc can accurately calculate memory usage. By default, Python uses its internal small-object allocator, which may interfere with jemalloc's ability to track memory consumption correctly. This could prevent the cache_autotuning feature from functioning as expected, as the Python allocator may not reach the memory threshold set by max_cache_memory_usage, thus not triggering the cache eviction process.
This made a significant difference on Python 2.7 - it's unclear how
much of an improvement it provides on Python 3.x.
If you're encountering high CPU use by the Synapse process itself, you
diff --git a/latest/replication.html b/latest/replication.html
index 9aa924461f..da99c6243c 100644
--- a/latest/replication.html
+++ b/latest/replication.html
@@ -77,7 +77,7 @@
diff --git a/latest/reverse_proxy.html b/latest/reverse_proxy.html
index 5a66217988..3ac8433e1d 100644
--- a/latest/reverse_proxy.html
+++ b/latest/reverse_proxy.html
@@ -77,7 +77,7 @@
@@ -165,10 +165,10 @@
Apache,
Caddy,
HAProxy or
-relayd in front of Synapse. One advantage
-of doing so is that it means that you can expose the default https port
-(443) to Matrix clients without needing to run Synapse with root
-privileges.
+relayd in front of Synapse.
+This has the advantage of being able to expose the default HTTPS port (443) to Matrix
+clients without requiring Synapse to bind to a privileged port (port numbers less than
+1024), avoiding the need for CAP_NET_BIND_SERVICE or running as root.
You should configure your reverse proxy to forward requests to /_matrix or
/_synapse/client to Synapse, and have it set the X-Forwarded-For and
X-Forwarded-Proto request headers.
diff --git a/latest/room_and_user_statistics.html b/latest/room_and_user_statistics.html
index 94231f5766..596d4e4035 100644
--- a/latest/room_and_user_statistics.html
+++ b/latest/room_and_user_statistics.html
@@ -77,7 +77,7 @@
diff --git a/latest/schema/synapse-config.schema.json b/latest/schema/synapse-config.schema.json
new file mode 100644
index 0000000000..9970bbb907
--- /dev/null
+++ b/latest/schema/synapse-config.schema.json
@@ -0,0 +1,4812 @@
+{
+ "$schema": "https://element-hq.github.io/synapse/latest/schema/v1/meta.schema.json",
+ "$id": "https://element-hq.github.io/synapse/schema/synapse/v1.132/synapse-config.schema.json",
+ "type": "object",
+ "properties": {
+ "modules": {
+ "type": "array",
+ "description": "Use the `module` sub-option to add modules under this option to extend functionality. The `module` setting then has a sub-option, `config`, which can be used to define some configuration for the `module`.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "Path to the Python class of the module."
+ },
+ "config": {
+ "type": "object",
+ "description": "Configuration options for the module."
+ }
+ }
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "module": "my_super_module.MySuperClass",
+ "config": {
+ "do_thing": true
+ }
+ },
+ {
+ "module": "my_other_super_module.SomeClass",
+ "config": {}
+ }
+ ]
+ ]
+ },
+ "server_name": {
+ "type": "string",
+ "description": "This sets the public-facing domain of the server.\n\nThe `server_name` name will appear at the end of usernames and room addresses created on your server. For example if the `server_name` was example.com, usernames on your server would be in the format `@user:example.com`.\n\nIn most cases you should avoid using a matrix specific subdomain such as matrix.example.com or synapse.example.com as the `server_name` for the same reasons you wouldn't use user@email.example.com as your email address. See [here](../../delegate.md) for information on how to host Synapse on a subdomain while preserving a clean `server_name`.\n\nThe `server_name` cannot be changed later so it is important to configure this correctly before you start Synapse. It should be all lowercase and may contain an explicit port.",
+ "examples": [
+ "matrix.org",
+ "localhost:8080"
+ ]
+ },
+ "pid_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "When running Synapse as a daemon, the file to store the pid in.",
+ "default": null,
+ "examples": [
+ "DATADIR/homeserver.pid"
+ ]
+ },
+ "daemonize": {
+ "type": "boolean",
+ "description": "Specifies whether Synapse should be started as a daemon process. If Synapse is being managed by [systemd](../../systemd-with-workers/), this option must be omitted or set to `false`.\n\nThis can also be set by the `--daemonize` (`-D`) argument when starting Synapse.\n\nSee `worker_daemonize` for more information on daemonizing workers.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "print_pidfile": {
+ "type": "boolean",
+ "description": "Print the path to the pidfile just before daemonizing.\n\nThis can also be set by the `--print-pidfile` argument when starting Synapse.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "user_agent_suffix": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A suffix that is appended to the Synapse user-agent (ex. `Synapse/v1.123.0`).",
+ "default": null,
+ "examples": [
+ " (I'm a teapot; Linux x86_64)"
+ ]
+ },
+ "use_frozen_dicts": {
+ "type": "boolean",
+ "description": "Determines whether we should freeze the internal dict object in `FrozenEvent`. Freezing prevents bugs where we accidentally share e.g. signature dicts. However, freezing a dict is expensive.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "web_client_location": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The absolute URL to the web client which `/` will redirect to.",
+ "default": null,
+ "examples": [
+ "https://riot.example.com/"
+ ]
+ },
+ "public_baseurl": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The public-facing base URL that clients use to access this Homeserver (not including _matrix/...). This is the same URL a user might enter into the \"Custom Homeserver URL\" field on their client. If you use Synapse with a reverse proxy, this should be the URL to reach Synapse via the proxy. Otherwise, it should be the URL to reach Synapse's client HTTP listener (see [`listeners`](#listeners) below).\n\nIf unset or null, `https:///` is used.",
+ "default": null,
+ "examples": [
+ "https://example.com/"
+ ]
+ },
+ "serve_server_wellknown": {
+ "type": "boolean",
+ "description": "By default, other servers will try to reach our server on port 8448, which can be inconvenient in some environments.\n\nProvided `https:///` on port 443 is routed to Synapse, this option configures Synapse to serve a file at `https:///.well-known/matrix/server`. This will tell other servers to send traffic to port 443 instead.\n\nThis option currently defaults to false.\n\nSee [Delegation of incoming federation traffic](../../delegate.md) for more information.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "extra_well_known_client_content": {
+ "type": "object",
+ "description": "This option allows server runners to add arbitrary key-value pairs to the [client-facing `.well-known` response](https://spec.matrix.org/latest/client-server-api/#well-known-uri). Note that the `public_baseurl` config option must be provided for Synapse to serve a response to `/.well-known/matrix/client` at all.\n\nIf this option is provided, it parses the given yaml to json and serves it on `/.well-known/matrix/client` endpoint alongside the standard properties.\n\n*Added in Synapse 1.62.0.*",
+ "examples": [
+ {
+ "option1": "value1",
+ "option2": "value2"
+ }
+ ]
+ },
+ "soft_file_limit": {
+ "type": "integer",
+ "description": "Set the soft limit on the number of file descriptors synapse can use. Zero is used to indicate synapse should set the soft limit to the hard limit.",
+ "default": 0,
+ "examples": [
+ 3
+ ]
+ },
+ "presence": {
+ "type": "object",
+ "description": "Presence tracking allows users to see the state (e.g online/offline) of other local and remote users. This option replaces the previous top-level `use_presence` option.",
+ "properties": {
+ "enabled": {
+ "type": [
+ "boolean",
+ "string"
+ ],
+ "description": "Set to false to disable presence tracking on this homeserver.\n\nCan also be set to a special value of \"untracked\" which ignores updates received via clients and federation, while still accepting updates from the [module API](../../modules/index.md).\n\n*The \"untracked\" option was added in Synapse 1.96.0.*",
+ "oneOf": [
+ {
+ "type": "boolean"
+ },
+ {
+ "type": "string",
+ "const": "untracked"
+ }
+ ],
+ "default": true
+ },
+ "include_offline_users_on_sync": {
+ "type": "boolean",
+ "description": "When clients perform an initial or `full_state` sync, presence results for offline users are not included by default. Setting `include_offline_users_on_sync` to `true` will always include offline users in the results.",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "enabled": false,
+ "include_offline_users_on_sync": false
+ }
+ ]
+ },
+ "require_auth_for_profile_requests": {
+ "type": "boolean",
+ "description": "Whether to require authentication to retrieve profile data (avatars, display names) of other users through the client API. Note that profile data is also available via the federation API, unless `allow_profile_lookup_over_federation` is set to false.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "limit_profile_requests_to_users_who_share_rooms": {
+ "type": "boolean",
+ "description": "Use this option to require a user to share a room with another user in order to retrieve their profile information. Only checked on Client-Server requests. Profile requests from other servers should be checked by the requesting server.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "include_profile_data_on_invite": {
+ "type": "boolean",
+ "description": "Use this option to prevent a user's profile data from being retrieved and displayed in a room until they have joined it. By default, a user's profile data is included in an invite event, regardless of the values of the above two settings, and whether or not the users share a server.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "allow_public_rooms_without_auth": {
+ "type": "boolean",
+ "description": "If set to true, removes the need for authentication to access the server's public rooms directory through the client API, meaning that anyone can query the room directory.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "allow_public_rooms_over_federation": {
+ "type": "boolean",
+ "description": "If set to true, allows any other homeserver to fetch the server's public rooms directory via federation.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "default_room_version": {
+ "type": "string",
+ "description": "The default room version for newly created rooms on this server.\n\nKnown room versions are listed [here](https://spec.matrix.org/latest/rooms/#complete-list-of-room-versions)\n\nFor example, for room version 1, `default_room_version` should be set to \"1\".\n\n_Changed in Synapse 1.76:_ the default version room version was increased from [9](https://spec.matrix.org/v1.5/rooms/v9/) to [10](https://spec.matrix.org/v1.5/rooms/v10/).",
+ "default": "10",
+ "examples": [
+ "8"
+ ]
+ },
+ "gc_thresholds": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "The garbage collection threshold parameters to pass to `gc.set_threshold`, if defined.",
+ "default": null,
+ "examples": [
+ [
+ 700,
+ 10,
+ 10
+ ]
+ ]
+ },
+ "gc_min_interval": {
+ "type": "array",
+ "description": "The minimum time in seconds between each GC for a generation, regardless of the GC thresholds. This ensures that we don't do GC too frequently. A value of `[1s, 10s, 30s]` indicates that a second must pass between consecutive generation 0 GCs, etc.",
+ "default": [
+ "1s",
+ "10s",
+ "30s"
+ ],
+ "examples": [
+ [
+ "0.5s",
+ "30s",
+ "1m"
+ ]
+ ]
+ },
+ "filter_timeline_limit": {
+ "type": "integer",
+ "description": "Set the limit on the returned events in the timeline in the get and sync operations. A value of -1 means no upper limit.",
+ "default": 100,
+ "examples": [
+ 5000
+ ]
+ },
+ "block_non_admin_invites": {
+ "type": "boolean",
+ "description": "Whether room invites to users on this server should be blocked (except those sent by local server admins).",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "enable_search": {
+ "type": "boolean",
+ "description": "If set to false, new messages will not be indexed for searching and users will receive errors when searching for messages.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "ip_range_blacklist": {
+ "type": "array",
+ "description": "This option prevents outgoing requests from being sent to the specified blacklisted IP address CIDR ranges. If this option is not specified then it defaults to private IP address ranges (see the example below).\n\nThe blacklist applies to the outbound requests for federation, identity servers, push servers, and for checking key validity for third-party invite events.\n\n(0.0.0.0 and :: are always blacklisted, whether or not they are explicitly listed here, since they correspond to unroutable addresses.)\n\nThis option replaces `federation_ip_range_blacklist` in Synapse v1.25.0.\n\nNote: The value is ignored when an HTTP proxy is in use.",
+ "items": {
+ "type": "string"
+ },
+ "default": [
+ "127.0.0.0/8",
+ "10.0.0.0/8",
+ "172.16.0.0/12",
+ "192.168.0.0/16",
+ "100.64.0.0/10",
+ "192.0.0.0/24",
+ "169.254.0.0/16",
+ "192.88.99.0/24",
+ "198.18.0.0/15",
+ "192.0.2.0/24",
+ "198.51.100.0/24",
+ "203.0.113.0/24",
+ "224.0.0.0/4",
+ "::1/128",
+ "fe80::/10",
+ "fc00::/7",
+ "2001:db8::/32",
+ "ff00::/8",
+ "fec0::/10"
+ ]
+ },
+ "ip_range_whitelist": {
+ "type": "array",
+ "description": "List of IP address CIDR ranges that should be allowed for federation, identity servers, push servers, and for checking key validity for third-party invite events. This is useful for specifying exceptions to wide-ranging blacklisted target IP ranges – e.g. for communication with a push server only visible in your network.\n\nThis whitelist overrides `ip_range_blacklist`.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "192.168.1.1"
+ ]
+ ]
+ },
+ "listeners": {
+ "type": "array",
+ "description": "List of ports that Synapse should listen on, their purpose and their configuration.\n\nValid resource names are:\n\n* `client`: the client-server API (/_matrix/client). Also implies `media` and `static`. If configuring the main process, the Synapse Admin API (/_synapse/admin) is also implied.\n\n* `consent`: user consent forms (/_matrix/consent). See [here](../../consent_tracking.md) for more.\n\n* `federation`: the server-server API (/_matrix/federation). Also implies `media`, `keys`, `openid`\n\n* `keys`: the key discovery API (/_matrix/key).\n\n* `media`: the media API (/_matrix/media).\n\n* `metrics`: the metrics interface. See [here](../../metrics-howto.md). (Not compatible with Unix sockets)\n\n* `openid`: OpenID authentication. See [here](../../openid.md).\n\n* `replication`: the HTTP replication API (/_synapse/replication). See [here](../../workers.md).\n\n* `static`: static resources under synapse/static (/_matrix/static). (Mostly useful for \"fallback authentication\".)\n\n* `health`: the [health check endpoint](../../reverse_proxy.md#health-check-endpoint). This endpoint is by default active for all other resources and does not have to be activated separately. This is only useful if you want to use the health endpoint explicitly on a dedicated port or for [workers](../../workers.md) and containers without listener e.g. [application services](../../workers.md#notifying-application-services).",
+ "items": {
+ "type": "object",
+ "properties": {
+ "port": {
+ "type": "integer",
+ "description": "The TCP port to bind to."
+ },
+ "tag": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alias for the port in the logger name. If set the tag is logged instead of the port. Default to `None`, is optional and only valid for listener with `type: http`. See the docs [request log format](../administration/request_log.md)."
+ },
+ "bind_addresses": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "A list of local addresses to listen on. The default is \"all local interfaces\".",
+ "items": {
+ "type": "string"
+ }
+ },
+ "type": {
+ "type": "string",
+ "description": "The type of listener. Normally `http`, but other valid options are [`manhole`](../../manhole.md) and [`metrics`](../../metrics-howto.md).",
+ "enum": [
+ "http",
+ "manhole",
+ "metrics"
+ ]
+ },
+ "tls": {
+ "type": "boolean",
+ "description": "Set to true to enable TLS for this listener. Will use the TLS key/cert specified in tls_private_key_path/tls_certificate_path."
+ },
+ "x_forwarded": {
+ "type": "boolean",
+ "description": "Only valid for an `http` listener. Set to true to use the X-Forwarded-For header as the client IP. Useful when Synapse is behind a [reverse-proxy](../../reverse_proxy.md)."
+ },
+ "request_id_header": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The header extracted from each incoming request that is used as the basis for the request ID. The request ID is used in [logs](../administration/request_log.md#request-log-format) and tracing to correlate and match up requests. When unset, Synapse will automatically generate sequential request IDs. This option is useful when Synapse is behind a [reverse-proxy](../../reverse_proxy.md).\n\n_Added in Synapse 1.68.0._"
+ },
+ "resources": {
+ "type": "array",
+ "description": "Only valid for an `http` listener. A list of resources to host on this port.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "names": {
+ "type": "array",
+ "description": "A list of names of HTTP resources. See below for a list of valid resource names.",
+ "items": {
+ "type": "string",
+ "enum": [
+ "client",
+ "consent",
+ "federation",
+ "keys",
+ "media",
+ "metrics",
+ "openid",
+ "replication",
+ "static",
+ "health"
+ ]
+ }
+ },
+ "compress": {
+ "type": "boolean",
+ "description": "Set to true to enable gzip compression on HTTP bodies for this resource. This is currently only supported with the `client`, `consent`, `metrics` and `federation` resources."
+ }
+ }
+ }
+ },
+ "additional_resources": {
+ "type": "object",
+ "description": "Only valid for an `http` listener. A map of additional endpoints which should be loaded via dynamic modules.",
+ "additionalProperties": {
+ "type": "object",
+ "properties": {
+ "module": {
+ "type": "string"
+ },
+ "config": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "path": {
+ "type": "string",
+ "description": "A path and filename for a Unix socket. Make sure it is located in a directory with read and write permissions, and that it already exists (the directory will not be created). Defaults to `None`.\n* **Note**: The use of both `path` and `port` options for the same `listener` is not compatible.\n* The `x_forwarded` option defaults to true when using Unix sockets and can be omitted.\n* Other options that would not make sense to use with a UNIX socket, such as `bind_addresses` and `tls` will be ignored and can be removed.\n\n_Added in Synapse 1.89.0_: Unix socket support"
+ },
+ "mode": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "The file permissions to set on the UNIX socket. Defaults to `666` if unset or null.\n\n**Note:** Must be set as `type: http` (does not support `metrics` and `manhole`). Also make sure that `metrics` is not included in `resources` -> `names`\n\n_Added in Synapse 1.89.0_: Unix socket support"
+ }
+ }
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "port": 8448,
+ "type": "http",
+ "tls": true,
+ "resources": [
+ {
+ "names": [
+ "client",
+ "federation"
+ ]
+ }
+ ]
+ }
+ ],
+ [
+ {
+ "port": 8008,
+ "tls": false,
+ "type": "http",
+ "x_forwarded": true,
+ "bind_addresses": [
+ "::1",
+ "127.0.0.1"
+ ],
+ "resources": [
+ {
+ "names": [
+ "client",
+ "federation"
+ ],
+ "compress": false
+ }
+ ],
+ "additional_resources": {
+ "/_matrix/my/custom/endpoint": {
+ "module": "my_module.CustomRequestHandler",
+ "config": {}
+ }
+ }
+ },
+ {
+ "port": 9000,
+ "bind_addresses": [
+ "::1",
+ "127.0.0.1"
+ ],
+ "type": "manhole"
+ }
+ ],
+ [
+ {
+ "path": "/run/synapse/main_public.sock",
+ "type": "http",
+ "resources": [
+ {
+ "names": [
+ "client",
+ "federation"
+ ]
+ }
+ ]
+ }
+ ]
+ ]
+ },
+ "manhole": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "Turn on the Twisted telnet manhole service on the given port.\n\nThis can also be set by the `--manhole` argument when starting Synapse.",
+ "default": null,
+ "examples": [
+ 1234
+ ]
+ },
+ "manhole_settings": {
+ "type": "object",
+ "description": "Connection settings for the manhole. You can find more information on the manhole [here](../../manhole.md).",
+ "properties": {
+ "username": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The username for the manhole. This defaults to \"matrix\"."
+ },
+ "password": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The password for the manhole. This defaults to \"rabbithole\"."
+ },
+ "ssh_priv_key_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The private SSH key used to encrypt the manhole traffic. If left unset, then hardcoded and non-secret keys are used, which could allow traffic to be intercepted if sent over a public network."
+ },
+ "ssh_pub_key_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The public SSH key corresponsing to `ssh_priv_key_path`. If left unset, a hardcoded key is used."
+ }
+ },
+ "examples": [
+ {
+ "username": "manhole",
+ "password": "mypassword",
+ "ssh_priv_key_path": "CONFDIR/id_rsa",
+ "ssh_pub_key_path": "CONFDIR/id_rsa.pub"
+ }
+ ]
+ },
+ "dummy_events_threshold": {
+ "type": "integer",
+ "description": "Forward extremities can build up in a room due to networking delays between homeservers. Once this happens in a large room, calculation of the state of that room can become quite expensive. To mitigate this, once the number of forward extremities reaches a given threshold, Synapse will send an `org.matrix.dummy_event` event, which will reduce the forward extremities in the room.\n\nThis setting defines the threshold (i.e. number of forward extremities in the room) at which dummy events are sent.",
+ "default": 10,
+ "examples": [
+ 5
+ ]
+ },
+ "delete_stale_devices_after": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "An optional duration. If set, Synapse will run a daily background task to log out and delete any device that hasn't been accessed for more than the specified amount of time.\n\nA value of null means devices are never pruned.\n\n**Note:** This task will always run on the main process, regardless of the value of `run_background_tasks_on`. This is due to workers currently not having the ability to delete devices.",
+ "default": null,
+ "examples": [
+ "1y"
+ ]
+ },
+ "email": {
+ "type": "object",
+ "description": "Configuration for sending emails from Synapse.\n\nServer admins can configure custom templates for email content. See [here](../../templates.md) for more information.",
+ "properties": {
+ "smtp_host": {
+ "type": "string",
+ "description": "The hostname of the outgoing SMTP server to use.",
+ "default": "localhost"
+ },
+ "smtp_port": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The port on the mail server for outgoing SMTP. If null or unset, 465 is used if `force_tls` is true, else 25.\n\n_Changed in Synapse 1.64.0:_ the default port is now aware of `force_tls`.",
+ "default": null
+ },
+ "smtp_user": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Username for authentication to the SMTP server.",
+ "default": null
+ },
+ "smtp_pass": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Password for authentication to the SMTP server.",
+ "default": null
+ },
+ "force_tls": {
+ "type": "boolean",
+ "description": "By default, Synapse connects over plain text and then optionally upgrades to TLS via STARTTLS. If this option is set to true, TLS is used from the start (Implicit TLS), and the option `require_transport_security` is ignored. It is recommended to enable this if supported by your mail server.\n\n_New in Synapse 1.64.0._",
+ "default": false
+ },
+ "require_transport_security": {
+ "type": "boolean",
+ "description": "Set to true to require TLS transport security for SMTP. By default, Synapse will connect over plain text, and will then switch to TLS via STARTTLS *if the SMTP server supports it*. If this option is set, Synapse will refuse to connect unless the server supports STARTTLS.",
+ "default": false
+ },
+ "enable_tls": {
+ "type": "boolean",
+ "description": "By default, if the server supports TLS, it will be used, and the server must present a certificate that is valid for `tlsname`. If this option is set to false, TLS will not be used.",
+ "default": true
+ },
+ "tlsname": {
+ "type": "string",
+ "description": "The domain name the SMTP server's TLS certificate must be valid for, defaulting to `smtp_host`."
+ },
+ "notif_from": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Defines the \"From\" address to use when sending emails. It must be set if email sending is enabled. The placeholder `%(app)s` will be replaced by the application name, which is normally set in `app_name`, but may be overridden by the Matrix client application. Note that the placeholder must be written `%(app)s`, including the trailing 's'.",
+ "default": null
+ },
+ "app_name": {
+ "type": "string",
+ "description": "Defines the default value for `%(app)s` in `notif_from` and email subjects.",
+ "default": "Matrix"
+ },
+ "enable_notifs": {
+ "type": "boolean",
+ "description": "Set to true to allow users to receive e-mail notifications. If this is not set, users can configure e-mail notifications but will not receive them.",
+ "default": false
+ },
+ "notif_for_new_users": {
+ "type": "boolean",
+ "description": "Set to false to disable automatic subscription to email notifications for new users.",
+ "default": true
+ },
+ "notif_delay_before_mail": {
+ "$ref": "#/$defs/duration",
+ "description": "The time to wait before emailing about a notification. This gives the user a chance to view the message via push or an open client.\n\n_New in Synapse 1.99.0._",
+ "default": "10m"
+ },
+ "client_base_url": {
+ "type": "string",
+ "description": "Custom URL for client links within the email notifications. (This setting used to be called `riot_base_url`; the old name is still supported for backwards-compatibility but is now deprecated.)",
+ "default": "https://matrix.to"
+ },
+ "validation_token_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "Configures the time that a validation email will expire after sending.",
+ "default": "1h"
+ },
+ "invite_client_location": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The web client location to direct users to during an invite. This is passed to the identity server as the `org.matrix.web_client_location` key. If null or unset no guidance is given to the identity server.",
+ "default": null
+ },
+ "subjects": {
+ "type": "object",
+ "description": "Subjects to use when sending emails from Synapse. The placeholder `%(app)s` will be replaced with the value of the `app_name` setting, or by a value dictated by the Matrix client application. In addition, each subject can use the following placeholders: `%(person)s`, which will be replaced by the displayname of the user(s) that sent the message(s), e.g. \"Alice and Bob\", and `%(room)s`, which will be replaced by the name of the room the message(s) have been sent to, e.g. \"My super room\". In addition, emails related to account administration will can use the `%(server_name)s` placeholder, which will be replaced by the value of the `server_name` setting in your Synapse configuration.",
+ "properties": {
+ "message_from_person_in_room": {
+ "type": "string",
+ "description": "Subject to use to notify about one message from one or more user(s) in a room which has a name.",
+ "default": "[%(app)s] You have a message on %(app)s from %(person)s in the %(room)s room..."
+ },
+ "message_from_person": {
+ "type": "string",
+ "description": "Subject to use to notify about one message from one or more user(s) in a room which doesn't have a name.",
+ "default": "[%(app)s] You have a message on %(app)s from %(person)s..."
+ },
+ "messages_from_person": {
+ "type": "string",
+ "description": "Subject to use to notify about multiple messages from one or more users in a room which doesn't have a name.",
+ "default": "[%(app)s] You have messages on %(app)s from %(person)s..."
+ },
+ "messages_in_room": {
+ "type": "string",
+ "description": "Subject to use to notify about multiple messages in a room which has a name.",
+ "default": "[%(app)s] You have messages on %(app)s in the %(room)s room..."
+ },
+ "messages_in_room_and_others": {
+ "type": "string",
+ "description": "Subject to use to notify about multiple messages in multiple rooms.",
+ "default": "[%(app)s] You have messages on %(app)s in the %(room)s room and others..."
+ },
+ "messages_from_person_and_others": {
+ "type": "string",
+ "description": "Subject to use to notify about multiple messages from multiple persons in multiple rooms. This is similar to the setting above except it's used when the room in which the notification was triggered has no name.",
+ "default": "[%(app)s] You have messages on %(app)s from %(person)s and others..."
+ },
+ "invite_from_person_to_room": {
+ "type": "string",
+ "description": "Subject to use to notify about an invite to a room which has a name.",
+ "default": "[%(app)s] %(person)s has invited you to join the %(room)s room on %(app)s..."
+ },
+ "invite_from_person": {
+ "type": "string",
+ "description": "Subject to use to notify about an invite to a room which doesn't have a name.",
+ "default": "[%(app)s] %(person)s has invited you to chat on %(app)s..."
+ },
+ "password_reset": {
+ "type": "string",
+ "description": "Subject to use when sending a password reset email.",
+ "default": "[%(server_name)s] Password reset"
+ },
+ "email_validation": {
+ "type": "string",
+ "description": "Subject to use when sending a verification email to assert an address's ownership.",
+ "default": "[%(server_name)s] Validate your email"
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "smtp_host": "mail.server",
+ "smtp_port": 587,
+ "smtp_user": "exampleusername",
+ "smtp_pass": "examplepassword",
+ "force_tls": true,
+ "require_transport_security": true,
+ "enable_tls": false,
+ "tlsname": "mail.server.example.com",
+ "notif_from": "Your Friendly %(app)s homeserver ",
+ "app_name": "my_branded_matrix_server",
+ "enable_notifs": true,
+ "notif_for_new_users": false,
+ "client_base_url": "http://localhost/riot",
+ "validation_token_lifetime": "15m",
+ "invite_client_location": "https://app.element.io",
+ "subjects": {
+ "message_from_person_in_room": "[%(app)s] You have a message on %(app)s from %(person)s in the %(room)s room...",
+ "message_from_person": "[%(app)s] You have a message on %(app)s from %(person)s...",
+ "messages_from_person": "[%(app)s] You have messages on %(app)s from %(person)s...",
+ "messages_in_room": "[%(app)s] You have messages on %(app)s in the %(room)s room...",
+ "messages_in_room_and_others": "[%(app)s] You have messages on %(app)s in the %(room)s room and others...",
+ "messages_from_person_and_others": "[%(app)s] You have messages on %(app)s from %(person)s and others...",
+ "invite_from_person_to_room": "[%(app)s] %(person)s has invited you to join the %(room)s room on %(app)s...",
+ "invite_from_person": "[%(app)s] %(person)s has invited you to chat on %(app)s...",
+ "password_reset": "[%(server_name)s] Password reset",
+ "email_validation": "[%(server_name)s] Validate your email"
+ }
+ }
+ ]
+ },
+ "max_event_delay_duration": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "The maximum allowed duration by which sent events can be delayed, as per [MSC4140](https://github.com/matrix-org/matrix-spec-proposals/pull/4140). Must be a positive value if set.\n\nIf null or unset, sending of delayed events is disallowed.",
+ "default": null,
+ "examples": [
+ "24h"
+ ]
+ },
+ "user_types": {
+ "type": "object",
+ "description": "Configuration settings related to the user types feature.",
+ "properties": {
+ "default_user_type": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The default user type to use for registering new users when no value has been specified. Defaults to none.",
+ "default": null
+ },
+ "extra_user_types": {
+ "type": "array",
+ "description": "Array of additional user types to allow. These are treated as real users.",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ }
+ },
+ "examples": [
+ {
+ "default_user_type": "custom",
+ "extra_user_types": [
+ "custom",
+ "custom2"
+ ]
+ }
+ ]
+ },
+ "admin_contact": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "How to reach the server admin, used in `ResourceLimitError`.",
+ "default": null,
+ "examples": [
+ "mailto:admin@server.com"
+ ]
+ },
+ "hs_disabled": {
+ "type": "boolean",
+ "description": "Blocks users from connecting to the homeserver and provides the human-readable reason given in `hs_disabled_message`.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "hs_disabled_message": {
+ "type": "string",
+ "description": "Human-readable reason why the connection was blocked.",
+ "default": "Homeserver is currently blocked",
+ "examples": [
+ "Reason for why the HS is blocked"
+ ]
+ },
+ "limit_usage_by_mau": {
+ "type": "boolean",
+ "description": "This option disables/enables monthly active user blocking. Used in cases where the admin or server owner wants to limit to the number of monthly active users. When enabled and a limit is reached the server returns a `ResourceLimitError` with error type `Codes.RESOURCE_LIMIT_EXCEEDED`. If this is enabled, a value for `max_mau_value` must also be set.\n\nSee [Monthly Active Users](../administration/monthly_active_users.md) for details on how to configure MAU.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "max_mau_value": {
+ "type": "integer",
+ "description": "This option sets the hard limit of monthly active users above which the server will start blocking user actions if `limit_usage_by_mau` is enabled.",
+ "default": 0,
+ "examples": [
+ 50
+ ]
+ },
+ "mau_trial_days": {
+ "type": "integer",
+ "description": "The option `mau_trial_days` is a means to add a grace period for active users. It means that users must be active for the specified number of days before they can be considered active and guards against the case where lots of users sign up in a short space of time never to return after their initial session.",
+ "default": 0,
+ "examples": [
+ 5
+ ]
+ },
+ "mau_appservice_trial_days": {
+ "type": "object",
+ "description": "The option `mau_appservice_trial_days` is similar to `mau_trial_days`, but applies a different trial number if the user was registered by an appservice. A value of 0 means no trial days are applied. Appservices not listed in this dictionary use the value of `mau_trial_days` instead.",
+ "additionalProperties": {
+ "type": "integer"
+ },
+ "default": {},
+ "examples": [
+ {
+ "my_appservice_id": 3,
+ "another_appservice_id": 6
+ }
+ ]
+ },
+ "mau_limit_alerting": {
+ "type": "boolean",
+ "description": "Limit client-side alerting should the mau limit be reached. This is useful for small instances where the admin has 5 mau seats (say) for 5 specific people and no interest increasing the mau limit further.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "mau_stats_only": {
+ "type": "boolean",
+ "description": "If enabled, the metrics for the number of monthly active users will be populated, however no one will be limited based on these numbers. If `limit_usage_by_mau` is true, this is implied to be true.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "mau_limit_reserved_threepids": {
+ "type": "array",
+ "description": "Sometimes the server admin will want to ensure certain accounts are never blocked by mau checking. These accounts are specified by this option. Add accounts by specifying the `medium` and `address` of the reserved threepid (3rd party identifier).",
+ "items": {
+ "type": "object",
+ "properties": {
+ "medium": {
+ "type": "string",
+ "description": "Medium of the account threepid."
+ },
+ "address": {
+ "type": "string",
+ "description": "Address of the account threepid."
+ }
+ }
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "medium": "email",
+ "address": "reserved_user@example.com"
+ }
+ ]
+ ]
+ },
+ "server_context": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This option is used by phonehome stats to group together related servers.",
+ "default": null,
+ "examples": [
+ "context"
+ ]
+ },
+ "limit_remote_rooms": {
+ "type": "object",
+ "description": "When this option is enabled, the room \"complexity\" will be checked before a user joins a new remote room. If it is above the complexity limit, the server will disallow joining, or will instantly leave. This is useful for homeservers that are resource-constrained. Room complexity is an arbitrary measure based on factors such as the number of users in the room.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether this check is enabled.",
+ "default": false
+ },
+ "complexity": {
+ "type": "number",
+ "description": "The limit above which rooms cannot be joined.",
+ "default": 1.0
+ },
+ "complexity_error": {
+ "type": "string",
+ "description": "Override the error which is returned when the room is too complex with a custom message.",
+ "default": "Your homeserver is unable to join rooms this large or complex. Please speak to your server administrator, or upgrade your instance to join this room."
+ },
+ "admins_can_join": {
+ "type": "boolean",
+ "description": "Allow server admins to join complex rooms.",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "complexity": 0.5,
+ "complexity_error": "I can't let you do that, Dave.",
+ "admins_can_join": true
+ }
+ ]
+ },
+ "require_membership_for_aliases": {
+ "type": "boolean",
+ "description": "Whether to require a user to be in the room to add an alias to it.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "allow_per_room_profiles": {
+ "type": "boolean",
+ "description": "Whether to allow per-room membership profiles through the sending of membership events with profile information that differs from the target's global profile.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "max_avatar_size": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/bytes"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "The largest permissible file size in bytes for a user avatar. Defaults to no restriction. Use M for MB and K for KB.\n\nNote that user avatar changes will not work if this is set without using Synapse's media repository.",
+ "default": null,
+ "examples": [
+ "10M"
+ ]
+ },
+ "allowed_avatar_mimetypes": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "The MIME types allowed for user avatars. Defaults to no restriction.\n\nNote that user avatar changes will not work if this is set without using Synapse's media repository.",
+ "items": {
+ "type": "string"
+ },
+ "default": null,
+ "examples": [
+ [
+ "image/png",
+ "image/jpeg",
+ "image/gif"
+ ]
+ ]
+ },
+ "redaction_retention_period": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How long to keep redacted events in unredacted form in the database. After this period redacted events get replaced with their redacted form in the DB.\n\nSynapse will check whether the rentention period has concluded for redacted events every 5 minutes. Thus, even if this option is set to `0`, Synapse may still take up to 5 minutes to purge redacted events from the database. Set to `null` to disable.",
+ "default": "7d",
+ "examples": [
+ "28d"
+ ]
+ },
+ "forgotten_room_retention_period": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How long to keep locally forgotten rooms before purging them from the DB. A value of `null` means it's disabled.",
+ "default": null,
+ "examples": [
+ "28d"
+ ]
+ },
+ "user_ips_max_age": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "How long to track users' last seen time and IPs in the database. Set to `null` to disable clearing out of old rows.",
+ "default": "28d",
+ "examples": [
+ "14d"
+ ]
+ },
+ "request_token_inhibit_3pid_errors": {
+ "type": "boolean",
+ "description": "Inhibits the `/requestToken` endpoints from returning an error that might leak information about whether an e-mail address is in use or not on this homeserver. Note that for some endpoints the error situation is the e-mail already being used, and for others the error is entering the e-mail being unused. If this option is enabled, instead of returning an error, these endpoints will act as if no error happened and return a fake session ID (`sid`) to clients.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "next_link_domain_whitelist": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "A list of domains that the domain portion of `next_link` parameters must match.\n\nThis parameter is optionally provided by clients while requesting validation of an email or phone number, and maps to a link that users will be automatically redirected to after validation succeeds. Clients can make use this parameter to aid the validation process.\n\nThe whitelist is applied whether the homeserver or an identity server is handling validation.\n\nThe default value is no whitelist functionality; all domains are allowed. Setting this value to an empty list will instead disallow all domains.",
+ "default": null,
+ "examples": [
+ "matrix.org"
+ ]
+ },
+ "templates": {
+ "type": "object",
+ "description": "These options define templates to use when generating email or HTML page contents.\n\nSee [here](../../templates.md) for more information about using custom templates.",
+ "properties": {
+ "custom_template_directory": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Determines which directory Synapse will try to find template files in to use to generate email or HTML page contents. If not set, or a file is not found within the template directory, a default template from within the Synapse package will be used.",
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "custom_template_directory": "/path/to/custom/templates/"
+ }
+ ]
+ },
+ "retention": {
+ "type": "object",
+ "description": "This option and the associated options determine message retention policy at the server level.\n\nRoom admins and mods can define a retention period for their rooms using the `m.room.retention` state event, and server admins can cap this period by setting the `allowed_lifetime_min` and `allowed_lifetime_max` config options.\n\nIf this feature is enabled, Synapse will regularly look for and purge events which are older than the room's maximum retention period. Synapse will also filter events received over federation so that events that should have been purged are ignored and not stored again.\n\nThe message retention policies feature is disabled by default. You can read more about this feature [here](../../message_retention_policies.md).",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Enforce message retention policies",
+ "default": false
+ },
+ "default_policy": {
+ "type": "object",
+ "description": "Default message retention policy. If set, Synapse will apply it to rooms that lack the `m.room.retention` state event.",
+ "properties": {
+ "min_lifetime": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Minimum message retention time of the default message retention policy. Synapse doesn't take this option into account yet.",
+ "default": null
+ },
+ "max_lifetime": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Maximum message retention time of the default message retention policy.",
+ "default": null
+ }
+ }
+ },
+ "allowed_lifetime_min": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Retention policy limit. If set, and the state of a room contains a `m.room.retention` event in its state which contains a `min_lifetime` that's beyond this bound, Synapse will cap the room's policy to these limits when running purge jobs.",
+ "default": null
+ },
+ "allowed_lifetime_max": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Retention policy limit. If set, and the state of a room contains a `m.room.retention` event in its state which contains a `max_lifetime` that's beyond this bound, Synapse will cap the room's policy to these limits when running purge jobs.",
+ "default": null
+ },
+ "purge_jobs": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "Server admins can define the settings of the background jobs purging the events whose lifetime has expired under the `purge_jobs` section.\n\nIf no configuration is provided for this option, a single job will be set up to delete expired events in every room daily.\n\nEach job's configuration defines which range of message lifetimes the job takes care of. For example, if `shortest_max_lifetime` is \"2d\" and `longest_max_lifetime` is \"3d\", the job will handle purging expired events in rooms whose state defines a `max_lifetime` that's both higher than 2 days, and lower than or equal to 3 days. Both the minimum and the maximum value of a range are optional, e.g. a job with no `shortest_max_lifetime` and a `longest_max_lifetime` of \"3d\" will handle every room with a retention policy whose `max_lifetime` is lower than or equal to three days.\n\nThe rationale for this per-job configuration is that some rooms might have a retention policy with a low `max_lifetime`, where history needs to be purged of outdated messages on a more frequent basis than for the rest of the rooms (e.g. every 12h), but not want that purge to be performed by a job that's iterating over every room it knows, which could be heavy on the server.\n\nIf any purge job is configured, it is strongly recommended to have at least a single job with neither `shortest_max_lifetime` nor `longest_max_lifetime` set, or one job without `shortest_max_lifetime` and one job without `longest_max_lifetime` set. Otherwise some rooms might be ignored, even if `allowed_lifetime_min` and `allowed_lifetime_max` are set, because capping a room's policy to these values is done after the policies are retrieved from Synapse's database (which is done using the range specified in a purge job's configuration).",
+ "items": {
+ "type": "object",
+ "properties": {
+ "shortest_max_lifetime": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Apply job to rooms that have a `max_lifetime` higher than `shortest_max_lifetime`. A value of `null` never excludes any room."
+ },
+ "longest_max_lifetime": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Apply job to rooms that have a `max_lifetime` lower than or equal to `shortest_max_lifetime`. A value of `null` never excludes any room."
+ },
+ "interval": {
+ "$ref": "#/$defs/duration",
+ "description": "How often to run the job."
+ }
+ }
+ },
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "default_policy": {
+ "min_lifetime": "1d",
+ "max_lifetime": "1y"
+ },
+ "allowed_lifetime_min": "1d",
+ "allowed_lifetime_max": "1y",
+ "purge_jobs": [
+ {
+ "longest_max_lifetime": "3d",
+ "interval": "12h"
+ },
+ {
+ "shortest_max_lifetime": "3d",
+ "interval": "1d"
+ }
+ ]
+ }
+ ]
+ },
+ "tls_certificate_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This option specifies a PEM-encoded X509 certificate for TLS. This certificate, as of Synapse 1.0, will need to be a valid and verifiable certificate, signed by a recognised Certificate Authority.\n\nBe sure to use a `.pem` file that includes the full certificate chain including any intermediate certificates (for instance, if using certbot, use `fullchain.pem` as your certificate, not `cert.pem`).",
+ "default": null,
+ "examples": [
+ "CONFDIR/SERVERNAME.tls.crt"
+ ]
+ },
+ "tls_private_key_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "PEM-encoded private key for TLS.",
+ "default": null,
+ "examples": [
+ "CONFDIR/SERVERNAME.tls.key"
+ ]
+ },
+ "federation_verify_certificates": {
+ "type": "boolean",
+ "description": "Whether to verify TLS server certificates for outbound federation requests. To disable certificate verification, set the option to false.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "federation_client_minimum_tls_version": {
+ "type": "string",
+ "description": "The minimum TLS version that will be used for outbound federation requests.\n\nConfigurable to `\"1\"`, `\"1.1\"`, `\"1.2\"`, or `\"1.3\"`. Note that setting this value higher than `\"1.2\"` will prevent federation to most of the public Matrix network: only configure it to `\"1.3\"` if you have an entirely private federation setup and you can ensure TLS 1.3 support.",
+ "default": "1",
+ "examples": [
+ "1.2"
+ ]
+ },
+ "federation_certificate_verification_whitelist": {
+ "type": "array",
+ "description": "Skip federation certificate verification on a given whitelist of domains.\n\nThis setting should only be used in very specific cases, such as federation over Tor hidden services and similar. For private networks of homeservers, you likely want to use a private CA instead.\n\nOnly effective if `federation_verify_certificates` is `true`.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "lon.example.com",
+ "*.domain.com",
+ "*.onion"
+ ]
+ ]
+ },
+ "federation_custom_ca_list": {
+ "type": "array",
+ "description": "List of custom certificate authorities for federation traffic.\n\nThis setting should only normally be used within a private network of homeservers.\n\nNote that this list will replace those that are provided by your operating environment. Certificates must be in PEM format.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "myCA1.pem",
+ "myCA2.pem",
+ "myCA3.pem"
+ ]
+ ]
+ },
+ "federation_domain_whitelist": {
+ "type": "array",
+ "description": "Restrict federation to the given whitelist of domains. N.B. we recommend also firewalling your federation listener to limit inbound federation traffic as early as possible, rather than relying purely on this application-layer restriction. If not specified, the default is to whitelist everything.\n\nNote: this does not stop a server from joining rooms that servers not on the whitelist are in. As such, this option is really only useful to establish a \"private federation\", where a group of servers all whitelist each other and have the same whitelist.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "lon.example.com",
+ "nyc.example.com",
+ "syd.example.com"
+ ]
+ ]
+ },
+ "federation_whitelist_endpoint_enabled": {
+ "type": "boolean",
+ "description": "Enables an endpoint for fetching the federation whitelist config.\n\nThe request method and path is `GET /_synapse/client/v1/config/federation_whitelist`, and the response format is:\n\n```json\n{\n \"whitelist_enabled\": true, // Whether the federation whitelist is being enforced\n \"whitelist\": [ // Which server names are allowed by the whitelist\n \"example.com\"\n ]\n}\n```\n\nIf `whitelist_enabled` is `false` then the server is permitted to federate with all others.\n\nThe endpoint requires authentication.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "federation_metrics_domains": {
+ "type": "array",
+ "description": "Report prometheus metrics on the age of PDUs being sent to and received from the given domains. This can be used to give an idea of \"delay\" on inbound and outbound federation, though be aware that any delay can be due to problems at either end or with the intermediate network.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "matrix.org",
+ "example.com"
+ ]
+ ]
+ },
+ "allow_profile_lookup_over_federation": {
+ "type": "boolean",
+ "description": "Set to false to disable profile lookup over federation. By default, the Federation API allows other homeservers to obtain profile data of any user on this homeserver.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "allow_device_name_lookup_over_federation": {
+ "type": "boolean",
+ "description": "Set this option to true to allow device display name lookup over federation. By default, the Federation API prevents other homeservers from obtaining the display names of any user devices on this homeserver.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "federation": {
+ "type": "object",
+ "description": "The federation section defines some sub-options related to federation.\n\nThe following options are related to configuring timeout and retry logic for one request, independently of the others. Short retry algorithm is used when something or someone will wait for the request to have an answer, while long retry is used for requests that happen in the background, like sending a federation transaction.\n\n`destination_*` options control the retry logic when communicating with a specific homeserver destination. Unlike the previous configuration options, these values apply across all requests for a given destination and the state of the backoff is stored in the database.",
+ "properties": {
+ "client_timeout": {
+ "$ref": "#/$defs/duration",
+ "description": "Timeout for the federation requests.",
+ "default": "60s"
+ },
+ "max_short_retry_delay": {
+ "$ref": "#/$defs/duration",
+ "description": "Maximum delay to be used for the short retry algo.",
+ "default": "2s"
+ },
+ "max_long_retry_delay": {
+ "$ref": "#/$defs/duration",
+ "description": "Maximum delay to be used for the long retry algo.",
+ "default": "60s"
+ },
+ "max_short_retries": {
+ "type": "integer",
+ "description": "Maximum number of retries for the short retry algo.",
+ "default": 3
+ },
+ "max_long_retries": {
+ "type": "integer",
+ "description": "Maximum number of retries for the long retry algo.",
+ "default": 10
+ },
+ "destination_min_retry_interval": {
+ "$ref": "#/$defs/duration",
+ "description": "The initial backoff, after the first request fails.",
+ "default": "10m"
+ },
+ "destination_retry_multiplier": {
+ "type": "integer",
+ "description": "How much we multiply the backoff by after each subsequent fail.",
+ "default": 2
+ },
+ "destination_max_retry_interval": {
+ "$ref": "#/$defs/duration",
+ "description": "A cap on the backoff.",
+ "default": "1w"
+ }
+ },
+ "examples": [
+ {
+ "client_timeout": "180s",
+ "max_short_retry_delay": "7s",
+ "max_long_retry_delay": "100s",
+ "max_short_retries": 5,
+ "max_long_retries": 20,
+ "destination_min_retry_interval": "30s",
+ "destination_retry_multiplier": 5,
+ "destination_max_retry_interval": "12h"
+ }
+ ]
+ },
+ "event_cache_size": {
+ "$ref": "#/$defs/size",
+ "description": "The number of events to cache in memory. Defaults to 10K. Like other caches, this is affected by `caches.global_factor` (see below).\n\nFor example, the default is 10K and the global_factor default is 0.5.\n\nSince 10K * 0.5 is 5K then the event cache size will be 5K.\n\nThe cache affected by this configuration is named as \"\\*getEvent\\*\".\n\nNote that this option is not part of the `caches` section.",
+ "default": "10K",
+ "examples": [
+ "15K"
+ ]
+ },
+ "caches": {
+ "type": "object",
+ "description": "A cache \"factor\" is a multiplier that can be applied to each of Synapse's caches in order to increase or decrease the maximum number of entries that can be stored.",
+ "io.element.post_description": "### Reloading cache factors\n\nThe cache factors (i.e. `caches.global_factor` and `caches.per_cache_factors`) may be reloaded at any time by sending a [`SIGHUP`](https://en.wikipedia.org/wiki/SIGHUP) signal to Synapse using e.g.\n\n```commandline\nkill -HUP [PID_OF_SYNAPSE_PROCESS]\n```\n\nIf you are running multiple workers, you must individually update the worker config file and send this signal to each worker process.\n\nIf you're using the [example systemd service](https://github.com/element-hq/synapse/blob/develop/contrib/systemd/matrix-synapse.service) file in Synapse's `contrib` directory, you can send a `SIGHUP` signal by using `systemctl reload matrix-synapse`.",
+ "properties": {
+ "global_factor": {
+ "type": "number",
+ "description": "Controls the global cache factor, which is the default cache factor for all caches if a specific factor for that cache is not otherwise set.\n\nThis can also be set by the `SYNAPSE_CACHE_FACTOR` environment variable. Setting by environment variable takes priority over setting through the config file.\n\nDefaults to 0.5, which will halve the size of all caches.\n\nNote that changing this value also affects the HTTP connection pool.",
+ "default": 0.5
+ },
+ "per_cache_factors": {
+ "type": "object",
+ "description": "A dictionary of cache name to cache factor for that individual cache. Overrides the global cache factor for a given cache.\n\nThese can also be set through environment variables comprised of `SYNAPSE_CACHE_FACTOR_` + the name of the cache in capital letters and underscores. Setting by environment variable takes priority over setting through the config file. Ex. `SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0`\n\nSome caches have '*' and other characters that are not alphanumeric or underscores. These caches can be named with or without the special characters stripped. For example, to specify the cache factor for `*stateGroupCache*` via an environment variable would be `SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0`.",
+ "additionalProperties": {
+ "type": "number"
+ },
+ "default": {}
+ },
+ "expire_caches": {
+ "type": "boolean",
+ "description": "Controls whether cache entries are evicted after a specified time period. Set to false to disable this feature. Note that never expiring caches may result in excessive memory usage.",
+ "default": true
+ },
+ "cache_entry_ttl": {
+ "$ref": "#/$defs/duration",
+ "description": "If `expire_caches` is enabled, this flag controls how long an entry can be in a cache without having been accessed before being evicted.",
+ "default": "30m"
+ },
+ "sync_response_cache_duration": {
+ "$ref": "#/$defs/duration",
+ "description": "Controls how long the results of a /sync request are cached for after a successful response is returned. A higher duration can help clients with intermittent connections, at the cost of higher memory usage. A value of zero means that sync responses are not cached.\n\n*Changed in Synapse 1.62.0*: The default was changed from 0 to 2m.",
+ "default": "2m"
+ },
+ "cache_autotuning": {
+ "type": "object",
+ "description": "`cache_autotuning` and its sub-options `max_cache_memory_usage`, `target_cache_memory_usage`, and `min_cache_ttl` work in conjunction with each other to maintain a balance between cache memory usage and cache entry availability. You must be using [jemalloc](../administration/admin_faq.md#help-synapse-is-slow-and-eats-all-my-ramcpu) to utilize this option, and all three of the options must be specified for this feature to work. This option defaults to off, enable it by providing values for the sub-options listed below. Please note that the feature will not work and may cause unstable behavior (such as excessive emptying of caches or exceptions) if all of the values are not provided. Please see the [Config Conventions](#config-conventions) for information on how to specify memory size and cache expiry durations.",
+ "properties": {
+ "max_cache_memory_usage": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Sets a ceiling on how much memory the cache can use before caches begin to be continuously evicted. They will continue to be evicted until the memory usage drops below the `target_cache_memory_usage`, set in the setting below, or until the `min_cache_ttl` is hit.",
+ "default": null
+ },
+ "target_cache_memory_usage": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/bytes"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Sets a rough target for the desired memory usage of the caches.",
+ "default": null
+ },
+ "min_cache_ttl": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "description": "Sets a limit under which newer cache entries are not evicted and is only applied when caches are actively being evicted/`max_cache_memory_usage` has been exceeded. This is to protect hot caches from being emptied while Synapse is evicting due to memory.",
+ "default": null
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "global_factor": 1.0,
+ "per_cache_factors": {
+ "get_users_who_share_room_with_user": 2.0
+ },
+ "sync_response_cache_duration": "2m",
+ "cache_autotuning": {
+ "max_cache_memory_usage": "1024M",
+ "target_cache_memory_usage": "758M",
+ "min_cache_ttl": "5m"
+ }
+ }
+ ]
+ },
+ "database": {
+ "$ref": "#/$defs/database",
+ "examples": [
+ {
+ "name": "sqlite3",
+ "args": {
+ "database": "/path/to/homeserver.db"
+ }
+ },
+ {
+ "name": "psycopg2",
+ "txn_limit": 10000,
+ "args": {
+ "user": "synapse_user",
+ "password": "secretpassword",
+ "dbname": "synapse",
+ "host": "localhost",
+ "port": 5432,
+ "cp_min": 5,
+ "cp_max": 10
+ }
+ }
+ ]
+ },
+ "databases": {
+ "type": "object",
+ "description": "The `databases` option allows specifying a mapping between certain database tables and database host details, spreading the load of a single Synapse instance across multiple database backends. This is often referred to as \"database sharding\". This option is only supported for PostgreSQL database backends.\n\n**Important note:** This is a supported option, but is not currently used in production by the Matrix.org Foundation. Proceed with caution and always make backups.\n\n`databases` is a dictionary of arbitrarily-named database entries. Each entry is equivalent to the value of the `database` homeserver config option (see above), with the addition of a `data_stores` key. `data_stores` is an array of strings that specifies the data store(s) (a defined label for a set of tables) that should be stored on the associated database backend entry.\n\nThe currently defined values for `data_stores` are:\n\n* `\"state\"`: Database that relates to state groups will be stored in this database.\n\n Specifically, that means the following tables:\n * `state_groups`\n * `state_group_edges`\n * `state_groups_state`\n\n And the following sequences:\n * `state_groups_seq_id`\n\n* `\"main\"`: All other database tables and sequences.\n\nAll databases will end up with additional tables used for tracking database schema migrations and any pending background updates. Synapse will create these automatically on startup when checking for and/or performing database schema migrations.\n\nTo migrate an existing database configuration (e.g. all tables on a single database) to a different configuration (e.g. the \"main\" data store on one database, and \"state\" on another), do the following:\n\n1. Take a backup of your existing database. Things can and do go wrong and database corruption is no joke!\n2. Ensure all pending database migrations have been applied and background updates have run. The simplest way to do this is to use the `update_synapse_database` script supplied with your Synapse installation.\n\n ```sh\n update_synapse_database --database-config homeserver.yaml --run-background-updates\n ```\n\n3. Copy over the necessary tables and sequences from one database to the other. Tables relating to database migrations, schemas, schema versions and background updates should **not** be copied.\n\n As an example, say that you'd like to split out the \"state\" data store from an existing database which currently contains all data stores.\n\n Simply copy the tables and sequences defined above for the \"state\" datastore from the existing database to the secondary database. As noted above, additional tables will be created in the secondary database when Synapse is started.\n\n4. Modify/create the `databases` option in your `homeserver.yaml` to match the desired database configuration.\n5. Start Synapse. Check that it starts up successfully and that things generally seem to be working.\n6. Drop the old tables that were copied in step 3.\n\nOnly one of the options `database` or `databases` may be specified in your config, but not both.",
+ "additionalProperties": {
+ "$ref": "#/$defs/database",
+ "properties": {
+ "data_stores": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "state",
+ "main"
+ ]
+ }
+ }
+ }
+ },
+ "default": {},
+ "examples": [
+ {
+ "basement_box": {
+ "name": "psycopg2",
+ "txn_limit": 10000,
+ "data_stores": [
+ "main"
+ ],
+ "args": {
+ "user": "synapse_user",
+ "password": "secretpassword",
+ "dbname": "synapse_main",
+ "host": "localhost",
+ "port": 5432,
+ "cp_min": 5,
+ "cp_max": 10
+ }
+ },
+ "my_other_database": {
+ "name": "psycopg2",
+ "txn_limit": 10000,
+ "data_stores": [
+ "state"
+ ],
+ "args": {
+ "user": "synapse_user",
+ "password": "secretpassword",
+ "dbname": "synapse_state",
+ "host": "localhost",
+ "port": 5432,
+ "cp_min": 5,
+ "cp_max": 10
+ }
+ }
+ }
+ ]
+ },
+ "log_config": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This option specifies a yaml python logging config file as described [here](https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema).",
+ "default": null,
+ "examples": [
+ "CONFDIR/SERVERNAME.log.config"
+ ]
+ },
+ "rc_message": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimiting settings for client messaging.\n\nThis is a ratelimiting option for messages that ratelimits sending based on the account the client is using.",
+ "default": {
+ "per_second": 0.2,
+ "burst_count": 10.0
+ },
+ "examples": [
+ {
+ "per_second": 0.5,
+ "burst_count": 15.0
+ }
+ ]
+ },
+ "rc_registration": {
+ "$ref": "#/$defs/rc",
+ "description": "This option ratelimits registration requests based on the client's IP address.",
+ "default": {
+ "per_second": 0.17,
+ "burst_count": 3.0
+ },
+ "examples": [
+ {
+ "per_second": 0.15,
+ "burst_count": 2.0
+ }
+ ]
+ },
+ "rc_registration_token_validity": {
+ "$ref": "#/$defs/rc",
+ "description": "This option checks the validity of registration tokens that ratelimits requests based on the client's IP address.",
+ "default": {
+ "per_second": 0.1,
+ "burst_count": 5.0
+ },
+ "examples": [
+ {
+ "per_second": 0.3,
+ "burst_count": 6.0
+ }
+ ]
+ },
+ "rc_login": {
+ "type": "object",
+ "description": "This option specifies several limits for login.",
+ "properties": {
+ "address": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimits login requests based on the client's IP address.",
+ "default": {
+ "per_second": 0.003,
+ "burst_count": 5.0
+ }
+ },
+ "account": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimits login requests based on the account the client is attempting to log into.",
+ "default": {
+ "per_second": 0.003,
+ "burst_count": 5.0
+ }
+ },
+ "failed_attempts": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimits login requests based on the account the client is attempting to log into, based on the amount of failed login attempts for this account.",
+ "default": {
+ "per_second": 0.17,
+ "burst_count": 3.0
+ }
+ }
+ },
+ "examples": [
+ {
+ "address": {
+ "per_second": 0.15,
+ "burst_count": 5.0
+ },
+ "account": {
+ "per_second": 0.18,
+ "burst_count": 4.0
+ },
+ "failed_attempts": {
+ "per_second": 0.19,
+ "burst_count": 7.0
+ }
+ }
+ ]
+ },
+ "rc_admin_redaction": {
+ "$ref": "#/$defs/rc",
+ "description": "This option sets ratelimiting redactions by room admins. If this is not explicitly set then it uses the same ratelimiting as per `rc_message`. This is useful to allow room admins to deal with abuse quickly.",
+ "examples": [
+ {
+ "per_second": 1.0,
+ "burst_count": 50.0
+ }
+ ]
+ },
+ "rc_joins": {
+ "type": "object",
+ "description": "This option allows for ratelimiting number of rooms a user can join.",
+ "properties": {
+ "local": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimits when users are joining rooms the server is already in.",
+ "default": {
+ "per_second": 0.1,
+ "burst_count": 10.0
+ }
+ },
+ "remote": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimits when users are trying to join rooms not on the server (which can be more computationally expensive than restricting locally).",
+ "default": {
+ "per_second": 0.01,
+ "burst_count": 10.0
+ }
+ }
+ },
+ "examples": [
+ {
+ "local": {
+ "per_second": 0.2,
+ "burst_count": 15.0
+ },
+ "remote": {
+ "per_second": 0.03,
+ "burst_count": 12.0
+ }
+ }
+ ]
+ },
+ "rc_joins_per_room": {
+ "$ref": "#/$defs/rc",
+ "description": "This option allows admins to ratelimit joins to a room based on the number of recent joins (local or remote) to that room. It is intended to mitigate mass-join spam waves which target multiple homeservers.\n\n_Added in Synapse 1.64.0._",
+ "default": {
+ "per_second": 1.0,
+ "burst_count": 10.0
+ },
+ "examples": [
+ {
+ "per_second": 1.0,
+ "burst_count": 10.0
+ }
+ ]
+ },
+ "rc_3pid_validation": {
+ "$ref": "#/$defs/rc",
+ "description": "This option ratelimits how often a user or IP can attempt to validate a 3PID.",
+ "default": {
+ "per_second": 0.003,
+ "burst_count": 5.0
+ },
+ "examples": [
+ {
+ "per_second": 0.003,
+ "burst_count": 5.0
+ }
+ ]
+ },
+ "rc_invites": {
+ "type": "object",
+ "description": "This option sets ratelimiting how often invites can be sent in a room or to a specific user.\n\nClient requests that invite user(s) when [creating a room](https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3createroom) will count against the `rc_invites.per_room` limit, whereas client requests to [invite a single user to a room](https://spec.matrix.org/v1.2/client-server-api/#post_matrixclientv3roomsroomidinvite) will count against both the `rc_invites.per_user` and `rc_invites.per_room` limits.\n\nFederation requests to invite a user will count against the `rc_invites.per_user` limit only, as Synapse presumes ratelimiting by room will be done by the sending server.\n\n_Changed in version 1.63:_ added the `per_issuer` limit.",
+ "properties": {
+ "per_room": {
+ "$ref": "#/$defs/rc",
+ "description": "Applies to the room of the invitation.",
+ "default": {
+ "per_second": 0.3,
+ "burst_count": 10.0
+ }
+ },
+ "per_user": {
+ "$ref": "#/$defs/rc",
+ "description": "Applies to the *receiver* of the invite, rather than the sender, meaning that a `rc_invite.per_user.burst_count` of 5 mandates that a single user cannot *receive* more than a burst of 5 invites at a time.",
+ "default": {
+ "per_second": 0.003,
+ "burst_count": 5.0
+ }
+ },
+ "per_issuer": {
+ "$ref": "#/$defs/rc",
+ "description": "Applies to the *issuer* of the invite, meaning that a `rc_invite.per_issuer.burst_count` of 5 mandates that single user cannot *send* more than a burst of 5 invites at a time.",
+ "default": {
+ "per_second": 0.3,
+ "burst_count": 10.0
+ }
+ }
+ },
+ "examples": [
+ {
+ "per_room": {
+ "per_second": 0.5,
+ "burst_count": 5.0
+ },
+ "per_user": {
+ "per_second": 0.004,
+ "burst_count": 3.0
+ },
+ "per_issuer": {
+ "per_second": 0.5,
+ "burst_count": 5.0
+ }
+ }
+ ]
+ },
+ "rc_third_party_invite": {
+ "$ref": "#/$defs/rc",
+ "description": "This option ratelimits 3PID invites (i.e. invites sent to a third-party ID such as an email address or a phone number) based on the account that's sending the invite.",
+ "default": {
+ "per_second": 0.2,
+ "burst_count": 10.0
+ }
+ },
+ "rc_media_create": {
+ "$ref": "#/$defs/rc",
+ "description": "This option ratelimits creation of MXC URIs via the `/_matrix/media/v1/create` endpoint based on the account that's creating the media.",
+ "default": {
+ "per_second": 10.0,
+ "burst_count": 50.0
+ }
+ },
+ "rc_federation": {
+ "type": "object",
+ "description": "Defines limits on federation requests.",
+ "properties": {
+ "window_size": {
+ "type": "integer",
+ "description": "Window size in milliseconds.",
+ "default": 1000
+ },
+ "sleep_limit": {
+ "type": "integer",
+ "description": "Number of federation requests from a single server in a window before the server will delay processing the request.",
+ "default": 10
+ },
+ "sleep_delay": {
+ "type": "integer",
+ "description": "Duration in milliseconds to delay processing events from remote servers by if they go over the sleep limit.",
+ "default": 500
+ },
+ "reject_limit": {
+ "type": "integer",
+ "description": "Maximum number of concurrent federation requests allowed from a single server.",
+ "default": 50
+ },
+ "concurrent": {
+ "type": "integer",
+ "description": "Number of federation requests to concurrently process from a single server.",
+ "default": 3
+ }
+ },
+ "examples": [
+ {
+ "window_size": 750,
+ "sleep_limit": 15,
+ "sleep_delay": 400,
+ "reject_limit": 40,
+ "concurrent": 5
+ }
+ ]
+ },
+ "rc_presence": {
+ "type": "object",
+ "description": "This option sets ratelimiting for presence.",
+ "properties": {
+ "per_user": {
+ "$ref": "#/$defs/rc",
+ "description": "Sets rate limits on how often a specific users' presence updates are evaluated. Ratelimited presence updates sent via sync are ignored, and no error is returned to the client. This option also sets the rate limit for the [`PUT /_matrix/client/v3/presence/{userId}/status`] endpoint.\n\n[`PUT /_matrix/client/v3/presence/{userId}/status`]:\n "
+ }
+ },
+ "default": {
+ "per_user": {
+ "per_second": 0.1,
+ "burst_count": 1.0
+ }
+ },
+ "examples": [
+ {
+ "per_user": {
+ "per_second": 0.05,
+ "burst_count": 1.0
+ }
+ }
+ ]
+ },
+ "rc_delayed_event_mgmt": {
+ "$ref": "#/$defs/rc",
+ "description": "Ratelimiting settings for delayed event management.\n\nThis is a ratelimiting option that ratelimits attempts to restart, cancel, or view delayed events based on the sending client's account and device ID.\n\nAttempts to create or send delayed events are ratelimited not by this setting, but by `rc_message`.\n\nSetting this to a high value allows clients to make delayed event management requests often (such as repeatedly restarting a delayed event with a short timeout, or restarting several different delayed events all at once) without the risk of being ratelimited.",
+ "default": {
+ "per_user": {
+ "per_second": 1.0,
+ "burst_count": 5.0
+ }
+ },
+ "examples": [
+ {
+ "per_second": 2.0,
+ "burst_count": 20.0
+ }
+ ]
+ },
+ "federation_rr_transactions_per_room_per_second": {
+ "type": "integer",
+ "description": "Sets outgoing federation transaction frequency for sending read-receipts, per-room.\n\nIf we end up trying to send out more read-receipts, they will get buffered up into fewer transactions.",
+ "default": 50,
+ "examples": [
+ 40
+ ]
+ },
+ "enable_authenticated_media": {
+ "type": "boolean",
+ "description": "When set to true, all subsequent media uploads will be marked as authenticated, and will not be available over legacy unauthenticated media endpoints (`/_matrix/media/(r0|v3|v1)/download` and `/_matrix/media/(r0|v3|v1)/thumbnail`) – requests for authenticated media over these endpoints will result in a 404. All media, including authenticated media, will be available over the authenticated media endpoints `_matrix/client/v1/media/download` and `_matrix/client/v1/media/thumbnail`. Media uploaded prior to setting this option to true will still be available over the legacy endpoints. Note if the setting is switched to false after enabling, media marked as authenticated will be available over legacy endpoints. Defaults to true (previously false). In a future release of Synapse, this option will be removed and become always-on.\n\nIn all cases, authenticated requests to download media will succeed, but for unauthenticated requests, this case-by-case breakdown describes whether media downloads are permitted:\n\n* `enable_authenticated_media = False`:\n * unauthenticated client or homeserver requesting local media: allowed\n * unauthenticated client or homeserver requesting remote media: allowed as long as the media is in the cache, or as long as the remote homeserver does not require authentication to retrieve the media\n* `enable_authenticated_media = True`:\n * unauthenticated client or homeserver requesting local media: allowed if the media was stored on the server whilst `enable_authenticated_media` was `False` (or in a previous Synapse version where this option did not exist); otherwise denied.\n * unauthenticated client or homeserver requesting remote media: the same as for local media; allowed if the media was stored on the server whilst `enable_authenticated_media` was `False` (or in a previous Synapse version where this option did not exist); otherwise denied.\n\nIt is especially notable that media downloaded before this option existed (in older Synapse versions), or whilst this option was set to `False`, will perpetually be available over the legacy, unauthenticated endpoint, even after this option is set to `True`. This is for backwards compatibility with older clients and homeservers that do not yet support requesting authenticated media; those older clients or homeservers will not be cut off from media they can already see.\n\n_Changed in Synapse 1.120:_ This option now defaults to `True` when not set, whereas before this version it defaulted to `False`.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "enable_media_repo": {
+ "type": "boolean",
+ "description": "Enable the media store service in the Synapse master. Set to false if you are using a separate media store worker.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "media_store_path": {
+ "type": "string",
+ "description": "Directory where uploaded images and attachments are stored.",
+ "default": "media_store",
+ "examples": [
+ "DATADIR/media_store"
+ ]
+ },
+ "max_pending_media_uploads": {
+ "type": "integer",
+ "description": "How many *pending media uploads* can a given user have? A pending media upload is a created MXC URI that (a) is not expired (the `unused_expires_at` timestamp has not passed) and (b) the media has not yet been uploaded for.",
+ "default": 5,
+ "examples": [
+ 5
+ ]
+ },
+ "unused_expiration_time": {
+ "$ref": "#/$defs/duration",
+ "description": "How long to wait in milliseconds before expiring created media IDs.",
+ "default": "24h",
+ "examples": [
+ "1h"
+ ]
+ },
+ "media_storage_providers": {
+ "type": "array",
+ "description": "Media storage providers allow media to be stored in different locations.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "Type of resource, e.g. `file_system`."
+ },
+ "store_local": {
+ "type": "boolean",
+ "description": "Whether to store newly uploaded local files."
+ },
+ "store_remote": {
+ "type": "boolean",
+ "description": "Whether to store newly downloaded local files."
+ },
+ "store_synchronous": {
+ "type": "boolean",
+ "description": "Whether to wait for successful storage for local uploads."
+ },
+ "config": {
+ "type": "object",
+ "description": "Sets a path to the resource through the `directory` option.",
+ "properties": {
+ "directory": {
+ "type": "string",
+ "description": "Path to the resource."
+ }
+ }
+ }
+ }
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "module": "file_system",
+ "store_local": false,
+ "store_remote": false,
+ "store_synchronous": false,
+ "config": {
+ "directory": "/mnt/some/other/directory"
+ }
+ }
+ ]
+ ]
+ },
+ "max_upload_size": {
+ "$ref": "#/$defs/bytes",
+ "description": "The largest allowed upload size in bytes.\n\nIf you are using a reverse proxy you may also need to set this value in your reverse proxy's config. Notably Nginx has a small max body size by default. See [here](../../reverse_proxy.md) for more on using a reverse proxy with Synapse.",
+ "default": "50M",
+ "examples": [
+ "60M"
+ ]
+ },
+ "max_image_pixels": {
+ "$ref": "#/$defs/bytes",
+ "description": "Maximum number of pixels that will be thumbnailed.",
+ "default": "32M",
+ "examples": [
+ "35M"
+ ]
+ },
+ "remote_media_download_burst_count": {
+ "$ref": "#/$defs/bytes",
+ "description": "Remote media downloads are ratelimited using a [leaky bucket algorithm](https://en.wikipedia.org/wiki/Leaky_bucket), where a given \"bucket\" is keyed to the IP address of the requester when requesting remote media downloads. This configuration option sets the size of the bucket against which the size in bytes of downloads are penalized – if the bucket is full, i.e. a given number of bytes have already been downloaded, further downloads will be denied until the bucket drains. See also `remote_media_download_per_second` which determines the rate at which the \"bucket\" is emptied and thus has available space to authorize new requests.",
+ "default": "500MiB",
+ "examples": [
+ "200M"
+ ]
+ },
+ "remote_media_download_per_second": {
+ "$ref": "#/$defs/bytes",
+ "description": "Works in conjunction with `remote_media_download_burst_count` to ratelimit remote media downloads – this configuration option determines the rate at which the \"bucket\" (see above) leaks in bytes per second. As requests are made to download remote media, the size of those requests in bytes is added to the bucket, and once the bucket has reached it's capacity, no more requests will be allowed until a number of bytes has \"drained\" from the bucket. This setting determines the rate at which bytes drain from the bucket, with the practical effect that the larger the number, the faster the bucket leaks, allowing for more bytes downloaded over a shorter period of time. Defaults to 87KiB per second. See also `remote_media_download_burst_count`.",
+ "default": "87KiB",
+ "examples": [
+ "40K"
+ ]
+ },
+ "prevent_media_downloads_from": {
+ "type": "array",
+ "description": "A list of domains to never download media from. Media from these domains that is already downloaded will not be deleted, but will be inaccessible to users. This option does not affect admin APIs trying to download/operate on media.\n\nThis will not prevent the listed domains from accessing media themselves. It simply prevents users on this server from downloading media originating from the listed servers.\n\nThis will have no effect on media originating from the local server. This only affects media downloaded from other Matrix servers, to control URL previews see [`url_preview_ip_range_blacklist`](#url_preview_ip_range_blacklist) or [`url_preview_url_blacklist`](#url_preview_url_blacklist).",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "evil.example.org",
+ "evil2.example.org"
+ ]
+ ]
+ },
+ "dynamic_thumbnails": {
+ "type": "boolean",
+ "description": "Whether to generate new thumbnails on the fly to precisely match the resolution requested by the client. If true then whenever a new resolution is requested by the client the server will generate a new thumbnail. If false the server will pick a thumbnail from a precalculated list.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "thumbnail_sizes": {
+ "type": "array",
+ "description": "List of thumbnails to precalculate when an image is uploaded.",
+ "items": {
+ "type": "object",
+ "properties": {
+ "width": {
+ "type": "integer",
+ "description": "Width of the generated thumbnail."
+ },
+ "height": {
+ "type": "integer",
+ "description": "Height of the generated thumbnail."
+ },
+ "method": {
+ "type": "string",
+ "enum": [
+ "crop",
+ "scale"
+ ],
+ "description": "Method to fit the thumbnail dimensions. Current options are `crop` and `scale`."
+ }
+ }
+ },
+ "default": [
+ {
+ "width": 32,
+ "height": 32,
+ "method": "crop"
+ },
+ {
+ "width": 96,
+ "height": 96,
+ "method": "crop"
+ },
+ {
+ "width": 320,
+ "height": 240,
+ "method": "scale"
+ },
+ {
+ "width": 640,
+ "height": 480,
+ "method": "scale"
+ },
+ {
+ "width": 800,
+ "height": 600,
+ "method": "scale"
+ }
+ ]
+ },
+ "media_retention": {
+ "type": "object",
+ "description": "Controls whether local media and entries in the remote media cache (media that is downloaded from other homeservers) should be removed under certain conditions, typically for the purpose of saving space.\n\nPurging media files will be the carried out by the media worker (that is, the worker that has the `enable_media_repo` homeserver config option set to `true`). This may be the main process.\n\nThe `media_retention.local_media_lifetime` and `media_retention.remote_media_lifetime` config options control whether media will be purged if it has not been accessed in a given amount of time. Note that media is \"accessed\" when loaded in a room in a client, or otherwise downloaded by a local or remote user. If the media has never been accessed, the media's creation time is used instead. Both thumbnails and the original media will be removed. If either of these options are unset, then media of that type will not be purged.\n\nLocal or cached remote media that has been [quarantined](../../admin_api/media_admin_api.md#quarantining-media-in-a-room) will not be deleted. Similarly, local media that has been marked as [protected from quarantine](../../admin_api/media_admin_api.md#protecting-media-from-being-quarantined) will not be deleted.",
+ "properties": {
+ "local_media_lifetime": {
+ "description": "Duration without access to a local media resource after which it will be purged. If the media has never been accessed, the media's creation time is used instead. Both thumbnails and the original media will be removed. If unset or null, local media will not be purged.",
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ },
+ "remote_media_lifetime": {
+ "description": "Duration without access to a remote media resource after which it will be purged. If the media has never been accessed, the media's creation time is used instead. Both thumbnails and the original media will be removed. If unset or null, remote media will not be purged.",
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "null"
+ }
+ ],
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "local_media_lifetime": "90d",
+ "remote_media_lifetime": "14d"
+ }
+ ]
+ },
+ "url_preview_enabled": {
+ "type": "boolean",
+ "description": "This setting determines whether the preview URL API is enabled. Set to true to enable. If enabled you must specify a `url_preview_ip_range_blacklist` blacklist.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "url_preview_ip_range_blacklist": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "List of IP address CIDR ranges that the URL preview spider is denied from accessing. There are no defaults: you must explicitly specify a list for URL previewing to work. You should specify any internal services in your network that you do not want synapse to try to connect to, otherwise anyone in any Matrix room could cause your synapse to issue arbitrary GET requests to your internal services, causing serious security issues.\n\n(0.0.0.0 and :: are always blacklisted, whether or not they are explicitly listed here, since they correspond to unroutable addresses.)\n\nThis must be specified if `url_preview_enabled` is set. It is recommended that you use the following example list as a starting point.\n\nNote: The value is ignored when an HTTP proxy is in use.",
+ "items": {
+ "type": "string"
+ },
+ "default": null,
+ "examples": [
+ [
+ "127.0.0.0/8",
+ "10.0.0.0/8",
+ "172.16.0.0/12",
+ "192.168.0.0/16",
+ "100.64.0.0/10",
+ "192.0.0.0/24",
+ "169.254.0.0/16",
+ "192.88.99.0/24",
+ "198.18.0.0/15",
+ "192.0.2.0/24",
+ "198.51.100.0/24",
+ "203.0.113.0/24",
+ "224.0.0.0/4",
+ "::1/128",
+ "fe80::/10",
+ "fc00::/7",
+ "2001:db8::/32",
+ "ff00::/8",
+ "fec0::/10"
+ ]
+ ]
+ },
+ "url_preview_ip_range_whitelist": {
+ "type": "array",
+ "description": "This option sets a list of IP address CIDR ranges that the URL preview spider is allowed to access even if they are specified in `url_preview_ip_range_blacklist`. This is useful for specifying exceptions to wide-ranging blacklisted target IP ranges – e.g. for enabling URL previews for a specific private website only visible in your network.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "192.168.1.1"
+ ]
+ ]
+ },
+ "url_preview_url_blacklist": {
+ "type": "array",
+ "description": "Optional list of URL matches that the URL preview spider is denied from accessing. This is a usability feature, not a security one. You should use `url_preview_ip_range_blacklist` in preference to this, otherwise someone could define a public DNS entry that points to a private IP address and circumvent the blacklist. Applications that perform redirects or serve different content when detecting that Synapse is accessing them can also bypass the blacklist. This is more useful if you know there is an entire shape of URL that you know that you do not want Synapse to preview.\n\nEach list entry is a dictionary of url component attributes as returned by urlparse.urlsplit as applied to the absolute form of the URL. See [here](https://docs.python.org/2/library/urlparse.html#urlparse.urlsplit) for more information. Some examples are:\n\n* `username`\n* `netloc`\n* `scheme`\n* `path`\n\nThe values of the dictionary are treated as a filename match pattern applied to that component of URLs, unless they start with a ^ in which case they are treated as a regular expression match. If all the specified component matches for a given list item succeed, the URL is blacklisted.",
+ "items": {
+ "type": "object"
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "username": "*"
+ },
+ {
+ "netloc": "google.com"
+ },
+ {
+ "netloc": "*.google.com"
+ },
+ {
+ "scheme": "http"
+ },
+ {
+ "netloc": "www.acme.com",
+ "path": "/foo"
+ },
+ {
+ "netloc": "^[0-9]+.[0-9]+.[0-9]+.[0-9]+$"
+ }
+ ]
+ ]
+ },
+ "max_spider_size": {
+ "$ref": "#/$defs/bytes",
+ "description": "The largest allowed URL preview spidering size in bytes.",
+ "default": "10M",
+ "examples": [
+ "8M"
+ ]
+ },
+ "url_preview_accept_language": {
+ "type": "array",
+ "description": "A list of values for the Accept-Language HTTP header used when downloading webpages during URL preview generation. This allows Synapse to specify the preferred languages that URL previews should be in when communicating with remote servers.\n\nEach value is a IETF language tag; a 2-3 letter identifier for a language, optionally followed by subtags separated by `-`, specifying a country or region variant.\n\nMultiple values can be provided, and a weight can be added to each by using quality value syntax (;q=). `*` translates to any language.",
+ "items": {
+ "type": "string"
+ },
+ "default": [
+ "en"
+ ],
+ "examples": [
+ [
+ "en-UK",
+ "en-US;q=0.9",
+ "fr;q=0.8",
+ "*;q=0.7"
+ ]
+ ]
+ },
+ "oembed": {
+ "type": "object",
+ "description": "oEmbed allows for easier embedding content from a website. It can be used for generating URLs previews of services which support it. A default list of oEmbed providers is included with Synapse.",
+ "properties": {
+ "disable_default_providers": {
+ "type": "boolean",
+ "description": "Do not use Synapse's default list of oEmbed providers.",
+ "default": false
+ },
+ "additional_providers": {
+ "type": "array",
+ "description": "Additional files with oEmbed configuration (each should be in the form of providers.json).",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ }
+ },
+ "examples": [
+ {
+ "disable_default_providers": true,
+ "additional_providers": [
+ "oembed/my_providers.json"
+ ]
+ }
+ ]
+ },
+ "recaptcha_public_key": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This homeserver's ReCAPTCHA public key. Must be specified if [`enable_registration_captcha`](#enable_registration_captcha) is enabled.",
+ "default": null,
+ "examples": [
+ "YOUR_PUBLIC_KEY"
+ ]
+ },
+ "recaptcha_private_key": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This homeserver's ReCAPTCHA private key. Must be specified if [`enable_registration_captcha`](#enable_registration_captcha) is enabled.",
+ "default": null,
+ "examples": [
+ "YOUR_PRIVATE_KEY"
+ ]
+ },
+ "enable_registration_captcha": {
+ "type": "boolean",
+ "description": "Set to `true` to require users to complete a CAPTCHA test when registering an account. Requires a valid ReCaptcha public/private key.\n\nNote that [`enable_registration`](#enable_registration) must also be set to allow account registration.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "recaptcha_siteverify_api": {
+ "type": "string",
+ "description": "The API endpoint to use for verifying `m.login.recaptcha` responses.",
+ "default": "https://www.recaptcha.net/recaptcha/api/siteverify",
+ "examples": [
+ "https://my.recaptcha.site"
+ ]
+ },
+ "turn_uris": {
+ "type": "array",
+ "description": "The public URIs of the TURN server to give to clients.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "turn:example.org"
+ ]
+ ]
+ },
+ "turn_shared_secret": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The shared secret used to compute passwords for the TURN server.",
+ "default": null,
+ "examples": [
+ "YOUR_SHARED_SECRET"
+ ]
+ },
+ "turn_shared_secret_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alternative to [`turn_shared_secret`](#turn_shared_secret): allows the shared secret to be specified in an external file.\n\nThe file should be a plain text file, containing only the shared secret. Synapse reads the shared secret from the given file once at startup.\n\n_Added in Synapse 1.116.0._",
+ "default": null,
+ "examples": [
+ "/path/to/secrets/file"
+ ]
+ },
+ "turn_username": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "TURN server username if not using a token.",
+ "default": null,
+ "examples": [
+ "TURNSERVER_USERNAME"
+ ]
+ },
+ "turn_password": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "TURN server password if not using a token.",
+ "default": null,
+ "examples": [
+ "TURNSERVER_PASSWORD"
+ ]
+ },
+ "turn_user_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "How long generated TURN credentials last.",
+ "default": "1h",
+ "examples": [
+ "2h"
+ ]
+ },
+ "turn_allow_guests": {
+ "type": "boolean",
+ "description": "Whether guests should be allowed to use the TURN server. If false, VoIP will be unreliable for guests. However, it does introduce a slight security risk as it allows users to connect to arbitrary endpoints without having first signed up for a valid account (e.g. by passing a CAPTCHA).",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "enable_registration": {
+ "type": "boolean",
+ "description": "Enable registration for new users.\n\nIt is highly recommended that if you enable registration, you set one or more or the following options, to avoid abuse of your server by \"bots\":\n\n* [`enable_registration_captcha`](#enable_registration_captcha)\n* [`registrations_require_3pid`](#registrations_require_3pid)\n* [`registration_requires_token`](#registration_requires_token)\n\n(In order to enable registration without any verification, you must also set [`enable_registration_without_verification`](#enable_registration_without_verification).)\n\nNote that even if this setting is disabled, new accounts can still be created via the admin API if [`registration_shared_secret`](#registration_shared_secret) is set.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "enable_registration_without_verification": {
+ "type": "boolean",
+ "description": "Enable registration without email or captcha verification. Note: this option is *not* recommended, as registration without verification is a known vector for spam and abuse. Has no effect unless [`enable_registration`](#enable_registration) is also enabled.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "registrations_require_3pid": {
+ "type": "array",
+ "description": "If this is set, users must provide all of the specified types of [3PID](https://spec.matrix.org/latest/appendices/#3pid-types) when registering an account.\n\nNote that [`enable_registration`](#enable_registration) must also be set to allow account registration.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "email",
+ "msisdn"
+ ]
+ ]
+ },
+ "disable_msisdn_registration": {
+ "type": "boolean",
+ "description": "Explicitly disable asking for MSISDNs from the registration flow (overrides `registrations_require_3pid` if MSISDNs are set as required).",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "allowed_local_3pids": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "Mandate that users are only allowed to associate certain formats of 3PIDs with accounts on this server, as specified by the `medium` and `pattern` sub-options. `pattern` is a [Perl-like regular expression](https://docs.python.org/3/library/re.html#module-re).\n\nMore information about 3PIDs, allowed `medium` types and their `address` syntax can be found [in the Matrix spec](https://spec.matrix.org/latest/appendices/#3pid-types).",
+ "items": {
+ "type": "object",
+ "description": "Item allowing a given pattern for the specified 3PID medium.",
+ "properties": {
+ "medium": {
+ "$ref": "#/$defs/3pidmedium",
+ "description": "The medium for which to allow 3PID association."
+ },
+ "pattern": {
+ "type": "string",
+ "description": "A [Perl-like regular expression](https://docs.python.org/3/library/re.html#module-re) allowing association of a 3PID to a local account if it matches the given format."
+ }
+ }
+ },
+ "default": null,
+ "examples": [
+ [
+ {
+ "medium": "email",
+ "pattern": "^[^@]+@matrix\\.org$"
+ },
+ {
+ "medium": "email",
+ "pattern": "^[^@]+@vector\\.im$"
+ },
+ {
+ "medium": "msisdn",
+ "pattern": "^44\\d{10}$"
+ }
+ ]
+ ]
+ },
+ "enable_3pid_lookup": {
+ "type": "boolean",
+ "description": "Enable 3PIDs lookup requests to identity servers from this server.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "registration_requires_token": {
+ "type": "boolean",
+ "description": "Require users to submit a token during registration. Tokens can be managed using the admin [API](../administration/admin_api/registration_tokens.md). Disabling this option will not delete any tokens previously generated.\n\nNote that [`enable_registration`](#enable_registration) must also be set to allow account registration.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "registration_shared_secret": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "If set, allows registration of standard or admin accounts by anyone who has the shared secret, even if [`enable_registration`](#enable_registration) is not set.\n\nThis is primarily intended for use with the `register_new_matrix_user` script (see [Registering a user](../../setup/installation.md#registering-a-user)); however, the interface is [documented](../../admin_api/register_api.html).\n\nReplacing an existing `registration_shared_secret` with a new one requires users of the [Shared-Secret Registration API](../../admin_api/register_api.html) to start using the new secret for requesting any further one-time nonces.\n\n> ⚠️ **Warning** – The additional consequences of replacing [`macaroon_secret_key`](#macaroon_secret_key) will apply in case it delegates to `registration_shared_secret`.\n\nSee also [`registration_shared_secret_path`](#registration_shared_secret_path).",
+ "default": null,
+ "examples": [
+ ""
+ ]
+ },
+ "registration_shared_secret_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alternative to [`registration_shared_secret`](#registration_shared_secret): allows the shared secret to be specified in an external file.\n\nThe file should be a plain text file, containing only the shared secret.\n\nIf this file does not exist, Synapse will create a new shared secret on startup and store it in this file.\n\n_Added in Synapse 1.67.0._",
+ "default": null,
+ "examples": [
+ "/path/to/secrets/file"
+ ]
+ },
+ "bcrypt_rounds": {
+ "type": "integer",
+ "description": "Set the number of bcrypt rounds used to generate password hash. Larger numbers increase the work factor needed to generate the hash. The default number is 12 (which equates to 2^12 rounds). N.B. that increasing this will exponentially increase the time required to register or login - e.g. 24 => 2^24 rounds which will take >20 mins.",
+ "default": 12,
+ "examples": [
+ 14
+ ]
+ },
+ "allow_guest_access": {
+ "type": "boolean",
+ "description": "Allows users to register as guests without a password/email/etc, and participate in rooms hosted on this server which have been made accessible to anonymous users.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "default_identity_server": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The identity server which we suggest that clients should use when users log in on this server.\n\n(By default, no suggestion is made, so it is left up to the client. This setting is ignored unless `public_baseurl` is also explicitly set.)",
+ "default": null,
+ "examples": [
+ "https://matrix.org"
+ ]
+ },
+ "account_threepid_delegates": {
+ "type": "object",
+ "properties": {
+ "msisdn": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Identity server base URI for MSISDN (phone numbers). See above."
+ }
+ },
+ "description": "Delegate verification of phone numbers to an identity server.\n\nWhen a user wishes to add a phone number to their account, we need to verify that they actually own that phone number, which requires sending them a text message (SMS). Currently Synapse does not support sending those texts itself and instead delegates the task to an identity server. The base URI for the identity server to be used is specified by the `account_threepid_delegates.msisdn` option.\n\nIf this is left unspecified, Synapse will not allow users to add phone numbers to their account.\n\n(Servers handling the these requests must answer the `/requestToken` endpoints defined by the Matrix Identity Service API [specification](https://matrix.org/docs/spec/identity_service/latest).)\n\n*Deprecated in Synapse 1.64.0*: The `email` option is deprecated.\n\n*Removed in Synapse 1.66.0*: The `email` option has been removed. If present, Synapse will report a configuration error on startup.",
+ "default": {},
+ "examples": [
+ {
+ "msisdn": "http://localhost:8090"
+ }
+ ]
+ },
+ "enable_set_displayname": {
+ "type": "boolean",
+ "description": "Whether users are allowed to change their displayname after it has been initially set. Useful when provisioning users based on the contents of a third-party directory.\n\nDoes not apply to server administrators.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "enable_set_avatar_url": {
+ "type": "boolean",
+ "description": "Whether users are allowed to change their avatar after it has been initially set. Useful when provisioning users based on the contents of a third-party directory.\n\nDoes not apply to server administrators.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "enable_3pid_changes": {
+ "type": "boolean",
+ "description": "Whether users can change the third-party IDs associated with their accounts (email address and msisdn).",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "auto_join_rooms": {
+ "type": "array",
+ "description": "Users who register on this homeserver will automatically be joined to the rooms listed under this option.\n\nBy default, any room aliases included in this list will be created as a publicly joinable room when the first user registers for the homeserver. If the room already exists, make certain it is a publicly joinable room, i.e. the join rule of the room must be set to `public`. You can find more options relating to auto-joining rooms below.\n\nAs Spaces are just rooms under the hood, Space aliases may also be used.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "#exampleroom:example.com",
+ "#anotherexampleroom:example.com"
+ ]
+ ]
+ },
+ "autocreate_auto_join_rooms": {
+ "type": "boolean",
+ "description": "Where `auto_join_rooms` are specified, setting this flag ensures that the rooms exist by creating them when the first user on the homeserver registers. This option will not create Spaces.\n\nBy default the auto-created rooms are publicly joinable from any federated server. Use the `autocreate_auto_join_rooms_federated` and `autocreate_auto_join_room_preset` settings to customise this behaviour.\n\nSetting to false means that if the rooms are not manually created, users cannot be auto-joined since they do not exist.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "autocreate_auto_join_rooms_federated": {
+ "type": "boolean",
+ "description": "Whether the rooms listed in `auto_join_rooms` that are auto-created are available via federation. Only has an effect if `autocreate_auto_join_rooms` is true.\n\nNote that whether a room is federated cannot be modified after creation.\n\nIf true, the room will be joinable from other servers. If false, users from other homeservers are prevented from joining these rooms.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "autocreate_auto_join_room_preset": {
+ "type": "string",
+ "description": "The room preset to use when auto-creating one of `auto_join_rooms`. Only has an effect if `autocreate_auto_join_rooms` is true.\n\nPossible values for this option are:\n* \"public_chat\": the room is joinable by anyone, including federated servers if `autocreate_auto_join_rooms_federated` is true (the default).\n* \"private_chat\": an invitation is required to join these rooms.\n* \"trusted_private_chat\": an invitation is required to join this room and the invitee is assigned a power level of 100 upon joining the room.\n\nEach preset will set up a room in the same manner as if it were provided as the `preset` parameter when calling the [`POST /_matrix/client/v3/createRoom`](https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3createroom) Client-Server API endpoint.\n\nIf a value of \"private_chat\" or \"trusted_private_chat\" is used then `auto_join_mxid_localpart` must also be configured.",
+ "enum": [
+ "public_chat",
+ "private_chat",
+ "trusted_private_chat"
+ ],
+ "default": "public_chat",
+ "examples": [
+ "private_chat"
+ ]
+ },
+ "auto_join_mxid_localpart": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The local part of the user id which is used to create `auto_join_rooms` if `autocreate_auto_join_rooms` is true. If this is not provided then the initial user account that registers will be used to create the rooms.\n\nThe user id is also used to invite new users to any auto-join rooms which are set to invite-only.\n\nIt *must* be configured if `autocreate_auto_join_room_preset` is set to \"private_chat\" or \"trusted_private_chat\".\n\nNote that this must be specified in order for new users to be correctly invited to any auto-join rooms which have been set to invite-only (either at the time of creation or subsequently).\n\nNote that, if the room already exists, this user must be joined and have the appropriate permissions to invite new members.",
+ "default": null,
+ "examples": [
+ "system"
+ ]
+ },
+ "auto_join_rooms_for_guests": {
+ "type": "boolean",
+ "description": "When `auto_join_rooms` is specified, setting this flag to false prevents guest accounts from being automatically joined to the rooms.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "inhibit_user_in_use_error": {
+ "type": "boolean",
+ "description": "Whether to inhibit errors raised when registering a new account if the user ID already exists. If turned on, requests to `/register/available` will always show a user ID as available, and Synapse won't raise an error when starting a registration with a user ID that already exists. However, Synapse will still raise an error if the registration completes and the username conflicts.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "allow_underscore_prefixed_registration": {
+ "type": "boolean",
+ "description": "Whether users are allowed to register with a underscore-prefixed localpart. By default, AppServices use prefixes like `_example` to namespace their associated ghost users. If turned on, this may result in clashes or confusion. Useful when provisioning users from an external identity provider.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "session_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "Time that a user's session remains valid for, after they log in.\n\nNote that this is not currently compatible with guest logins.\n\nNote also that this is calculated at login time: changes are not applied retrospectively to users who have already logged in.",
+ "default": "infinity",
+ "examples": [
+ "24h"
+ ]
+ },
+ "refreshable_access_token_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "Time that an access token remains valid for, if the session is using refresh tokens.\n\nFor more information about refresh tokens, please see the [manual](user_authentication/refresh_tokens.md).\n\nNote that this only applies to clients which advertise support for refresh tokens.\n\nNote also that this is calculated at login time and refresh time: changes are not applied to existing sessions until they are refreshed.",
+ "default": "5m",
+ "examples": [
+ "10m"
+ ]
+ },
+ "refresh_token_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "Time that a refresh token remains valid for (provided that it is not exchanged for another one first). This option can be used to automatically log-out inactive sessions. Please see the manual for more information.\n\nNote also that this is calculated at login time and refresh time: changes are not applied to existing sessions until they are refreshed.",
+ "default": "infinity",
+ "examples": [
+ "24h"
+ ]
+ },
+ "nonrefreshable_access_token_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "Time that an access token remains valid for, if the session is NOT using refresh tokens.\n\nPlease note that not all clients support refresh tokens, so setting this to a short value may be inconvenient for some users who will then be logged out frequently.\n\nNote also that this is calculated at login time: changes are not applied retrospectively to existing sessions for users that have already logged in.",
+ "default": "infinity",
+ "examples": [
+ "24h"
+ ]
+ },
+ "ui_auth": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/duration"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "session_timeout": {
+ "$ref": "#/$defs/duration"
+ }
+ }
+ }
+ ],
+ "description": "The amount of time to allow a user-interactive authentication session to be active.\n\nThis defaults to 0, meaning the user is queried for their credentials before every action, but this can be overridden to allow a single validation to be re-used. This weakens the protections afforded by the user-interactive authentication process, by allowing for multiple (and potentially different) operations to use the same validation session.\n\nThis is ignored for potentially \"dangerous\" operations (including deactivating an account, modifying an account password, adding a 3PID, and minting additional login tokens).\n\nUse the `session_timeout` sub-option here to change the time allowed for credential validation.",
+ "default": 0,
+ "examples": [
+ {
+ "session_timeout": "15s"
+ }
+ ]
+ },
+ "login_via_existing_session": {
+ "type": "object",
+ "description": "Matrix supports the ability of an existing session to mint a login token for another client.\n\nSynapse disables this by default as it has security ramifications – a malicious client could use the mechanism to spawn more than one session.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Enable login via existing session.",
+ "default": false
+ },
+ "require_ui_auth": {
+ "type": "boolean",
+ "description": "Require user-interactive authentication.",
+ "default": true
+ },
+ "token_timeout": {
+ "$ref": "#/$defs/duration",
+ "description": "Duration of time the generated token is valid.",
+ "default": "5m"
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "require_ui_auth": false,
+ "token_timeout": "5m"
+ }
+ ]
+ },
+ "enable_metrics": {
+ "type": "boolean",
+ "description": "Set to true to enable collection and rendering of performance metrics.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "sentry": {
+ "type": "object",
+ "description": "Use this option to enable sentry integration. Provide the DSN assigned to you by sentry with the `dsn` setting.\n\nAn optional `environment` field can be used to specify an environment. This allows for log maintenance based on different environments, ensuring better organization and analysis.\n\nNOTE: While attempts are made to ensure that the logs don't contain any sensitive information, this cannot be guaranteed. By enabling this option the sentry server may therefore receive sensitive information, and it in turn may then disseminate sensitive information through insecure notification channels if so configured.",
+ "properties": {
+ "dsn": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The DSN assigned by sentry. If unset or null, sentry integration is disabled.",
+ "default": null
+ },
+ "environment": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Sentry environment.",
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "environment": "production",
+ "dsn": "..."
+ }
+ ]
+ },
+ "metrics_flags": {
+ "type": "object",
+ "description": "Flags to enable Prometheus metrics which are not suitable to be enabled by default, either for performance reasons or limited use. Currently the only option is `known_servers`.",
+ "properties": {
+ "known_servers": {
+ "type": "boolean",
+ "description": "Publishes `synapse_federation_known_servers`, a gauge of the number of servers this homeserver knows about, including itself. May cause performance problems on large homeservers.",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "known_servers": true
+ }
+ ]
+ },
+ "report_stats": {
+ "type": "boolean",
+ "description": "Whether or not to report homeserver usage statistics. This is originally set when generating the config. Set this option to true or false to change the current behavior. See [Reporting Homeserver Usage Statistics](../administration/monitoring/reporting_homeserver_usage_statistics.md) for information on what data is reported.\n\nStatistics will be reported 5 minutes after Synapse starts, and then every 3 hours after that.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "report_stats_endpoint": {
+ "type": "string",
+ "description": "The endpoint to report homeserver usage statistics to.",
+ "default": "https://matrix.org/report-usage-stats/push",
+ "examples": [
+ "https://example.com/report-usage-stats/push"
+ ]
+ },
+ "room_prejoin_state": {
+ "type": "object",
+ "description": "This setting controls the state that is shared with users upon receiving an invite to a room, or in reply to a knock on a room. By default, the following state events are shared with users:\n\n- `m.room.join_rules`\n- `m.room.canonical_alias`\n- `m.room.avatar`\n- `m.room.encryption`\n- `m.room.name`\n- `m.room.create`\n- `m.room.topic`\n\n*Changed in Synapse 1.74:* admins can filter the events in prejoin state based on their state key.",
+ "properties": {
+ "disable_default_event_types": {
+ "type": "boolean",
+ "description": "Set to `true` to disable the above defaults. If this is enabled, only the event types listed in `additional_event_types` are shared.",
+ "default": false
+ },
+ "additional_event_types": {
+ "type": "array",
+ "description": "A list of additional state events to include in the events to be shared. By default, this list is empty (so only the default event types are shared).\n\nEach entry in this list should be either a single string or a list of two strings.\n* A standalone string `t` represents all events with type `t` (i.e. with no restrictions on state keys).\n* A pair of strings `[t, s]` represents a single event with type `t` and state key `s`. The same type can appear in two entries with different state keys: in this situation, both state keys are included in prejoin state.",
+ "items": {
+ "type": [
+ "string",
+ "array"
+ ],
+ "items": {
+ "type": "string"
+ }
+ },
+ "default": []
+ }
+ },
+ "examples": [
+ {
+ "disable_default_event_types": false,
+ "additional_event_types": [
+ "org.example.custom.event.typeA",
+ [
+ "org.example.custom.event.typeB",
+ "foo"
+ ],
+ [
+ "org.example.custom.event.typeC",
+ "bar"
+ ],
+ [
+ "org.example.custom.event.typeC",
+ "baz"
+ ]
+ ]
+ }
+ ]
+ },
+ "track_puppeted_user_ips": {
+ "type": "boolean",
+ "description": "We record the IP address of clients used to access the API for various reasons, including displaying it to the user in the \"Where you're signed in\" dialog.\n\nBy default, when puppeting another user via the admin API, the client IP address is recorded against the user who created the access token (ie, the admin user), and *not* the puppeted user.\n\nSet this option to true to also record the IP address against the puppeted user. (This also means that the puppeted user will count as an \"active\" user for the purpose of monthly active user tracking – see `limit_usage_by_mau` etc above.)",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "app_service_config_files": {
+ "type": "array",
+ "description": "A list of application service config files to use.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "app_service_1.yaml",
+ "app_service_2.yaml"
+ ]
+ ]
+ },
+ "track_appservice_user_ips": {
+ "type": "boolean",
+ "description": "Set to true to enable tracking of application service IP addresses. Implicitly enables MAU tracking for application service users.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "use_appservice_legacy_authorization": {
+ "type": "boolean",
+ "description": "Whether to send the application service access tokens via the `access_token` query parameter per older versions of the Matrix specification. Defaults to false. Set to true to enable sending access tokens via a query parameter.\n\n**Enabling this option is considered insecure and is not recommended.**",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "macaroon_secret_key": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A secret which is used to sign\n- access token for guest users,\n- short-term login token used during SSO logins (OIDC or SAML2) and\n- token used for unsubscribing from email notifications.\n\nIf none is specified, the `registration_shared_secret` is used, if one is given; otherwise, a secret key is derived from the signing key.\n\n> ⚠️ **Warning** – Replacing an existing `macaroon_secret_key` with a new one will lead to invalidation of access tokens for all guest users. It will also break unsubscribe links in emails sent before the change. An unlucky user might encounter a broken SSO login flow and would have to start again.",
+ "default": null,
+ "examples": [
+ ""
+ ]
+ },
+ "macaroon_secret_key_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alternative to [`macaroon_secret_key`](#macaroon_secret_key): allows the secret key to be specified in an external file.\n\nThe file should be a plain text file, containing only the secret key. Synapse reads the secret key from the given file once at startup.\n\n_Added in Synapse 1.121.0._",
+ "default": null,
+ "examples": [
+ "/path/to/secrets/file"
+ ]
+ },
+ "form_secret": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A secret which is used to calculate HMACs for form values, to stop falsification of values. Must be specified for the User Consent forms to work.\n\nReplacing an existing `form_secret` with a new one might break the user consent page for an unlucky user and require them to reopen the page from a new link.",
+ "default": null,
+ "examples": [
+ ""
+ ]
+ },
+ "form_secret_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alternative to [`form_secret`](#form_secret): allows the secret to be specified in an external file.\n\nThe file should be a plain text file, containing only the secret. Synapse reads the secret from the given file once at startup.\n\n_Added in Synapse 1.126.0._",
+ "default": null,
+ "examples": [
+ "/path/to/secrets/file"
+ ]
+ },
+ "signing_key_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Path to the signing key to sign events and federation requests with.\n\n*New in Synapse 1.67*: If this file does not exist, Synapse will create a new signing key on startup and store it in this file.",
+ "default": null,
+ "examples": [
+ "CONFDIR/SERVERNAME.signing.key"
+ ]
+ },
+ "old_signing_keys": {
+ "type": "object",
+ "description": "The keys that the server used to sign messages with but won't use to sign new messages.\n\nIt is possible to build an entry from an old `signing.key` file using the `export_signing_key` script which is provided with synapse.\n\nIf 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:\n\n```\ncurl https://matrix-federation.matrix.org/_matrix/key/v2/query/myserver.example.com |\n jq '.server_keys | map(.verify_keys) | add'\n```",
+ "additionalProperties": {
+ "type": "object",
+ "properties": {
+ "key": {
+ "type": "string",
+ "description": "The base64-encoded public key."
+ },
+ "expired_ts": {
+ "type": "integer",
+ "description": "Time, in milliseconds since the unix epoch, that the key was last used."
+ }
+ }
+ },
+ "default": {},
+ "examples": [
+ {
+ "ed25519:id": {
+ "key": "base64string",
+ "expired_ts": 123456789123
+ }
+ }
+ ]
+ },
+ "key_refresh_interval": {
+ "$ref": "#/$defs/duration",
+ "description": "How long key response published by this server is valid for. Used to set the `valid_until_ts` in `/key/v2` APIs. Determines how quickly servers will query to check which keys are still valid.",
+ "default": "1d",
+ "examples": [
+ "2d"
+ ]
+ },
+ "trusted_key_servers": {
+ "type": "array",
+ "description": "The trusted servers to download signing keys from.\n\nWhen we need to fetch a signing key, each server is tried in parallel.\n\nNormally, the connection to the key server is validated via TLS certificates. Additional security can be provided by configuring a `verify key`, which will make synapse check that the response is signed by that key.\n\nThis setting supersedes an older setting named `perspectives`. The old format is still supported for backwards-compatibility, but it is deprecated.\n\n`trusted_key_servers` defaults to matrix.org, but using it will generate a warning on start-up. To suppress this warning, set `suppress_key_server_warning` to true.\n\nIf the use of a trusted key server has to be deactivated, e.g. in a private federation or for privacy reasons, this can be realised by setting an empty array (`trusted_key_servers: []`). Then Synapse will request the keys directly from the server that owns the keys. If Synapse does not get keys directly from the server, the events of this server will be rejected.",
+ "items": {
+ "server_name": {
+ "type": "string",
+ "description": "The name of the server. Required."
+ },
+ "verify_keys": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "An optional map from key id to base64-encoded public key. If specified, we will check that the response is signed by at least one of the given keys.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "accept_keys_insecurely": {
+ "type": "boolean",
+ "description": "Normally, if `verify_keys` is unset, and `federation_verify_certificates` is not `true`, synapse will refuse to start, because this would allow anyone who can spoof DNS responses to masquerade as the trusted key server. If you know what you are doing and are sure that your network environment provides a secure connection to the key server, you can set this to `true` to override this behaviour."
+ }
+ },
+ "default": [
+ {
+ "server_name": "matrix.org"
+ }
+ ],
+ "examples": [
+ [
+ {
+ "server_name": "my_trusted_server.example.com",
+ "verify_keys": {
+ "ed25519:auto": "abcdefghijklmnopqrstuvwxyzabcdefghijklmopqr"
+ }
+ },
+ {
+ "server_name": "my_other_trusted_server.example.com"
+ }
+ ],
+ [
+ {
+ "server_name": "matrix.org"
+ }
+ ]
+ ]
+ },
+ "suppress_key_server_warning": {
+ "type": "boolean",
+ "description": "Set the following to true to disable the warning that is emitted when the `trusted_key_servers` include \"matrix.org\". See above.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "key_server_signing_keys_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The signing keys to use when acting as a trusted key server. If not specified defaults to the server signing key.\n\nCan contain multiple keys, one per line.",
+ "default": null,
+ "examples": [
+ "key_server_signing_keys.key"
+ ]
+ },
+ "saml2_config": {
+ "type": "object",
+ "description": "Enable SAML2 for registration and login. Uses pysaml2. To learn more about pysaml and to find a full list options for configuring pysaml, read the docs [here](https://pysaml2.readthedocs.io/en/latest/).\n\nAt least one of `sp_config` or `config_path` must be set in this section to enable SAML login. You can either put your entire pysaml config inline using the `sp_config` option, or you can specify a path to a psyaml config file with the sub-option `config_path`.\n\nOnce SAML support is enabled, a metadata file will be exposed at `https://:/_synapse/client/saml2/metadata.xml`, which you may be able to use to configure your SAML IdP with. Alternatively, you can manually configure the IdP to use an ACS location of `https://:/_synapse/client/saml2/authn_response`.",
+ "properties": {
+ "idp_name": {
+ "type": "string",
+ "description": "A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms."
+ },
+ "idp_icon": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format `mxc:///`. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the URL from the source of the event.)"
+ },
+ "idp_brand": {
+ "description": "An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the [spec](https://spec.matrix.org/latest/) for possible options here."
+ },
+ "sp_config": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "Configuration for the pysaml2 Service Provider. See pysaml2 docs for format of config. Default values will be used for the `entityid` and `service` settings, so it is not normally necessary to specify them unless you need to override them. Here are a few useful sub-options for configuring pysaml:\n* `metadata`: Point this to the IdP's metadata. You must provide either a local file via the `local` attribute or (preferably) a URL via the `remote` attribute.\n* `accepted_time_diff: 3`: Allowed clock difference in seconds between the homeserver and IdP. Defaults to 0.\n* `service`: By default, the user has to go to our login page first. If you'd like to allow IdP-initiated login, set `allow_unsolicited` to true under `sp` in the `service` section.",
+ "default": null
+ },
+ "config_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Specify a separate pysaml2 configuration file.",
+ "default": null
+ },
+ "saml_session_lifetime": {
+ "$ref": "#/$defs/duration",
+ "description": "The lifetime of a SAML session. This defines how long a user has to complete the authentication process, if `allow_unsolicited` is unset.",
+ "default": "15m"
+ },
+ "user_mapping_provider": {
+ "type": "object",
+ "description": "Using this option, an external module can be provided as a custom solution to mapping attributes returned from a saml provider onto a matrix user.",
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "The custom module's class."
+ },
+ "config": {
+ "type": "object",
+ "description": "Custom configuration values for the module. Use the values provided in the example if you are using the built-in user_mapping_provider, or provide your own config values for a custom class if you are using one. This section will be passed as a Python dictionary to the module's `parse_config` method. The built-in provider takes the following two options:\n* `mxid_source_attribute`: The SAML attribute (after mapping via the attribute maps) to use to derive the Matrix ID from. It is \"uid\" by default. Note: This used to be configured by the `saml2_config.mxid_source_attribute option`. If that is still defined, its value will be used instead.\n* `mxid_mapping`: The mapping system to use for mapping the saml attribute onto a matrix ID. Options include: `hexencode` (which maps unpermitted characters to `=xx`) and `dotreplace` (which replaces unpermitted characters with `.`). The default is `hexencode`. Note: This used to be configured by the `saml2_config.mxid_mapping option`. If that is still defined, its value will be used instead."
+ }
+ }
+ },
+ "grandfathered_mxid_source_attribute": {
+ "type": "string",
+ "description": "In previous versions of synapse, the mapping from SAML attribute to MXID was always calculated dynamically rather than stored in a table. For backwards-compatibility, we will look for `user_ids` matching such a pattern before creating a new account. This setting controls the SAML attribute which will be used for this backwards-compatibility lookup. Typically it should be \"uid\", but if the attribute maps are changed, it may be necessary to change it.",
+ "default": "uid"
+ },
+ "attribute_requirements": {
+ "type": "array",
+ "description": "It is possible to configure Synapse to only allow logins if SAML attributes match particular values. The requirements can be listed under `attribute_requirements` as shown in the example. All of the listed attributes must match for the login to be permitted. Values can be specified in a `one_of` list to allow multiple values for an attribute.",
+ "items": {
+ "type": "object",
+ "description": "Item allowing a specific SAML attribute.",
+ "properties": {
+ "attribute": {
+ "type": "string",
+ "description": "SAML attribute for which to allow logins."
+ },
+ "value": {
+ "type": "string",
+ "description": "Value the SAML attribute must match."
+ },
+ "one_of": {
+ "type": "array",
+ "description": "List of values the SAML attribute must all match.",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "attribute"
+ ]
+ }
+ },
+ "idp_entityid": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "If the metadata XML contains multiple IdP entities then the `idp_entityid` option must be set to the entity to redirect users to. Most deployments only have a single IdP entity and so should omit this option.",
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "sp_config": {
+ "metadata": {
+ "local": [
+ "saml2/idp.xml"
+ ],
+ "remote": [
+ {
+ "url": "https://our_idp/metadata.xml"
+ }
+ ]
+ },
+ "accepted_time_diff": 3,
+ "service": {
+ "sp": {
+ "allow_unsolicited": true
+ }
+ },
+ "description": [
+ "My awesome SP",
+ "en"
+ ],
+ "name": [
+ "Test SP",
+ "en"
+ ],
+ "ui_info": {
+ "display_name": [
+ {
+ "lang": "en",
+ "text": "Display Name is the descriptive name of your service."
+ }
+ ],
+ "description": [
+ {
+ "lang": "en",
+ "text": "Description should be a short paragraph explaining the purpose of the service."
+ }
+ ],
+ "information_url": [
+ {
+ "lang": "en",
+ "text": "https://example.com/terms-of-service"
+ }
+ ],
+ "privacy_statement_url": [
+ {
+ "lang": "en",
+ "text": "https://example.com/privacy-policy"
+ }
+ ],
+ "keywords": [
+ {
+ "lang": "en",
+ "text": [
+ "Matrix",
+ "Element"
+ ]
+ }
+ ],
+ "logo": [
+ {
+ "lang": "en",
+ "text": "https://example.com/logo.svg",
+ "width": "200",
+ "height": "80"
+ }
+ ]
+ },
+ "organization": {
+ "name": "Example com",
+ "display_name": [
+ [
+ "Example co",
+ "en"
+ ]
+ ],
+ "url": "http://example.com"
+ },
+ "contact_person": [
+ {
+ "given_name": "Bob",
+ "sur_name": "the Sysadmin",
+ "email_address": [
+ "admin@example.com"
+ ],
+ "contact_type": "technical"
+ }
+ ]
+ },
+ "saml_session_lifetime": "5m",
+ "user_mapping_provider": {
+ "config": {
+ "mxid_source_attribute": "displayName",
+ "mxid_mapping": "dotreplace"
+ }
+ },
+ "grandfathered_mxid_source_attribute": "upn",
+ "attribute_requirements": [
+ {
+ "attribute": "userGroup",
+ "value": "staff"
+ },
+ {
+ "attribute": "department",
+ "one_of": [
+ "sales",
+ "admins"
+ ]
+ }
+ ],
+ "idp_entityid": "https://our_idp/entityid"
+ }
+ ]
+ },
+ "oidc_providers": {
+ "type": "array",
+ "description": "List of OpenID Connect (OIDC) / OAuth 2.0 identity providers, for registration and login. See [here](../../openid.md) for information on how to configure these options.\n\nFor backwards compatibility, it is also possible to configure a single OIDC provider via an `oidc_config` setting. This is now deprecated and admins are advised to migrate to the `oidc_providers` format. (When doing that migration, use `oidc` for the `idp_id` to ensure that existing users continue to be recognised.)\n\nIt is possible to configure Synapse to only allow logins if certain attributes match particular values in the OIDC userinfo. The requirements can be listed under `attribute_requirements` as shown here:\n```yaml\nattribute_requirements:\n - attribute: family_name\n one_of: [\"Stephensson\", \"Smith\"]\n - attribute: groups\n value: \"admin\"\n # If `value` or `one_of` are not specified, the attribute only needs\n # to exist, regardless of value.\n - attribute: picture\n```\n\n`attribute` is a required field, while `value` and `one_of` are optional.\n\nAll of the listed attributes must match for the login to be permitted. Additional attributes can be added to userinfo by expanding the `scopes` section of the OIDC config to retrieve additional information from the OIDC provider.\n\nIf the OIDC claim is a list, then the attribute must match any value in the list. Otherwise, it must exactly match the value of the claim. Using the example above, the `family_name` claim MUST be either \"Stephensson\" or \"Smith\", but the `groups` claim MUST contain \"admin\".",
+ "items": {
+ "type": "object",
+ "properties": {
+ "idp_id": {
+ "type": "string",
+ "description": "A unique identifier for this identity provider. Used internally by Synapse; should be a single word such as \"github\". Note that, if this is changed, users authenticating via that provider will no longer be recognised as the same user! (Use \"oidc\" here if you are migrating from an old `oidc_config` configuration.)"
+ },
+ "idp_name": {
+ "type": "string",
+ "description": "A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms."
+ },
+ "idp_icon": {
+ "type": "string",
+ "description": "An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format `mxc:///`. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the URL from the source of the event.)"
+ },
+ "idp_brand": {
+ "type": "string",
+ "description": "An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the [spec](https://spec.matrix.org/latest/) for possible options here."
+ },
+ "discover": {
+ "type": "boolean",
+ "description": "Set to false to disable the use of the OIDC discovery mechanism to discover endpoints. Defaults to true."
+ },
+ "issuer": {
+ "type": "string",
+ "description": "Required. The OIDC issuer. Used to validate tokens and (if discovery is enabled) to discover the provider's endpoints."
+ },
+ "client_id": {
+ "type": "string",
+ "description": "Required. OAuth2 client id to use."
+ },
+ "client_secret": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "OAuth2 client secret to use. May be omitted if `client_secret_jwt_key` is given, or if `client_auth_method` is `none`. Must be omitted if `client_secret_path` is specified."
+ },
+ "client_secret_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Path to the OAuth2 client secret to use. With that it's not necessary to leak secrets into the config file itself. Mutually exclusive with `client_secret`. Can be omitted if `client_secret_jwt_key` is specified.\n\n*Added in Synapse 1.91.0.*"
+ },
+ "client_secret_jwt_key": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "Alternative to client_secret: details of a key used to create a JSON Web Token to be used as an OAuth2 client secret.",
+ "properties": {
+ "key": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A pem-encoded signing key. Must be a suitable key for the algorithm specified. Required unless `key_file` is given."
+ },
+ "key_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Path to the file containing a pem-encoded signing key. Required unless `key` is given."
+ },
+ "jwt_header": {
+ "type": "object",
+ "description": "Dictionary giving properties to include in the JWT header. Must include the key `alg`.",
+ "properties": {
+ "alg": {
+ "type": "string",
+ "description": "Algorithm used to sign the JWT, such as ES256, using the JWA identifiers in RFC7518."
+ }
+ }
+ },
+ "jwt_payload": {
+ "type": "object",
+ "description": "Optional dictionary giving properties to include in the JWT payload. Normally this should include an `iss` key."
+ }
+ }
+ },
+ "client_auth_method": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "client_secret_basic",
+ "client_secret_post",
+ "none",
+ null
+ ],
+ "description": "Auth method to use when exchanging the token. Valid values are `client_secret_basic` (default), `client_secret_post` and `none`."
+ },
+ "pkce_method": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "auto",
+ "always",
+ "never",
+ null
+ ],
+ "description": "Whether to use proof key for code exchange when requesting and exchanging the token. Valid values are: `auto`, `always`, or `never`. Defaults to `auto`, which uses PKCE if supported during metadata discovery. Set to `always` to force enable PKCE or `never` to force disable PKCE."
+ },
+ "id_token_signing_alg_values_supported": {
+ "type": "array",
+ "description": "List of the JWS signing algorithms (`alg` values) that are supported for signing the `id_token`.\n\nThis is *not* required if `discovery` is disabled. We default to supporting `RS256` in the downstream usage if no algorithms are configured here or in the discovery document.\n\nAccording to the spec, the algorithm `\"RS256\"` MUST be included. The absolute rigid approach would be to reject this provider as non-compliant if it's not included but we simply allow whatever and see what happens (you're the one that configured the value and cooperating with the identity provider).\n\nThe `alg` value `\"none\"` MAY be supported but can only be used if the Authorization Endpoint does not include `id_token` in the `response_type` (ex. `/authorize?response_type=code` where `none` can apply, `/authorize?response_type=code%20id_token` where `none` can't apply) (such as when using the Authorization Code Flow).",
+ "items": {
+ "type": "string"
+ }
+ },
+ "scopes": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "List of scopes to request. This should normally include the \"openid\" scope. Defaults to `[\"openid\"]`.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "authorization_endpoint": {
+ "type": "string",
+ "description": "The OAuth2 authorization endpoint. Required if provider discovery is disabled."
+ },
+ "token_endpoint": {
+ "type": "string",
+ "description": "The OAuth2 token endpoint. Required if provider discovery is disabled."
+ },
+ "userinfo_endpoint": {
+ "type": "string",
+ "description": "The OIDC userinfo endpoint. Required if discovery is disabled and the \"openid\" scope is not requested."
+ },
+ "jwks_uri": {
+ "type": "string",
+ "description": "URI where to fetch the JWKS. Required if discovery is disabled and the \"openid\" scope is used."
+ },
+ "skip_verification": {
+ "type": "boolean",
+ "description": "Set to `true` to skip metadata verification. Use this if you are connecting to a provider that is not OpenID Connect compliant. Defaults to false. Avoid this in production."
+ },
+ "user_profile_method": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "auto",
+ "userinfo_endpoint",
+ null
+ ],
+ "description": "Whether to fetch the user profile from the userinfo endpoint, or to rely on the data returned in the id_token from the `token_endpoint`. Valid values are: `auto` or `userinfo_endpoint`. Defaults to `auto`, which uses the userinfo endpoint if `openid` is not included in `scopes`. Set to `userinfo_endpoint` to always use the userinfo endpoint."
+ },
+ "redirect_uri": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An optional string, that if set will override the `redirect_uri` parameter sent in the requests to the authorization and token endpoints. Useful if you want to redirect the client to another endpoint as part of the OIDC login. Be aware that the client must then call Synapse's OIDC callback URL (`/_synapse/client/oidc/callback`) manually afterwards. Must be a valid URL including scheme and path."
+ },
+ "additional_authorization_parameters": {
+ "type": "object",
+ "description": "String to string dictionary that will be passed as additional parameters to the authorization grant URL.",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "passthrough_authorization_parameters": {
+ "type": "array",
+ "description": "List of parameters that will be passed through from the redirect endpoint to the authorization grant URL.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "allow_existing_users": {
+ "type": "boolean",
+ "description": "Set to true to allow a user logging in via OIDC to match a pre-existing account instead of failing. This could be used if switching from password logins to OIDC. Defaults to false."
+ },
+ "enable_registration": {
+ "type": "boolean",
+ "description": "Set to `false` to disable automatic registration of new users. This allows the OIDC SSO flow to be limited to sign in only, rather than automatically registering users that have a valid SSO login but do not have a pre-registered account. Defaults to true."
+ },
+ "user_mapping_provider": {
+ "type": "object",
+ "description": "Configuration for how attributes returned from a OIDC provider are mapped onto a matrix user.\n\nWhen rendering, the Jinja2 templates are given a `user` variable, which is set to the claims returned by the UserInfo Endpoint and/or in the ID Token.",
+ "properties": {
+ "module": {
+ "type": "string",
+ "description": "The class name of a custom mapping module. Default is `synapse.handlers.oidc.JinjaOidcMappingProvider`. See [OpenID Mapping Providers](../../sso_mapping_providers.md#openid-mapping-providers) for information on implementing a custom mapping provider."
+ },
+ "config": {
+ "type": "object",
+ "description": "Configuration for the mapping provider module. This section will be passed as a Python dictionary to the user mapping provider module's `parse_config` method.\n\nFor the default provider, the following settings are available:\n\n* `subject_template`: Jinja2 template for a unique identifier for the user. Defaults to `{{ user.sub }}`, which OpenID Connect compliant providers should provide.\n\n This replaces and overrides `subject_claim`.\n\n* `subject_claim`: name of the claim containing a unique identifier for the user. Defaults to `sub`, which OpenID Connect compliant providers should provide.\n\n *Deprecated in Synapse v1.75.0.*\n\n* `picture_template`: Jinja2 template for an url for the user's profile picture. Defaults to `{{ user.picture }}`, which OpenID Connect compliant providers should provide and has to refer to a direct image file such as PNG, JPEG, or GIF image file.\n\n This replaces and overrides `picture_claim`.\n\n Currently only supported in monolithic (single-process) server configurations where the media repository runs within the Synapse process.\n\n* `picture_claim`: name of the claim containing an url for the user's profile picture. Defaults to \"picture\", which OpenID Connect compliant providers should provide and has to refer to a direct image file such as PNG, JPEG, or GIF image file.\n\n Currently only supported in monolithic (single-process) server configurations where the media repository runs within the Synapse process.\n\n *Deprecated in Synapse v1.75.0.*\n\n* `localpart_template`: Jinja2 template for the localpart of the MXID. If this is not set, the user will be prompted to choose their own username (see the documentation for the `sso_auth_account_details.html` template). This template can use the `localpart_from_email` filter.\n\n* `confirm_localpart`: Whether to prompt the user to validate (or change) the generated localpart (see the documentation for the \"sso_auth_account_details.html\" template), instead of registering the account right away.\n\n* `display_name_template`: Jinja2 template for the display name to set on first login. If unset, no displayname will be set.\n\n* `email_template`: Jinja2 template for the email address of the user. If unset, no email address will be added to the account.\n\n* `extra_attributes`: a map of Jinja2 templates for extra attributes to send back to the client during login. Note that these are non-standard and clients will ignore them without modifications."
+ }
+ }
+ },
+ "backchannel_logout_enabled": {
+ "type": "boolean",
+ "description": "Set to `true` to process OIDC Back-Channel Logout notifications. Those notifications are expected to be received on `/_synapse/client/oidc/backchannel_logout`. Defaults to `false`."
+ },
+ "backchannel_logout_ignore_sub": {
+ "type": "boolean",
+ "description": "By default, the OIDC Back-Channel Logout feature checks that the `sub` claim matches the subject claim received during login. This check can be disabled by setting this to `true`. Defaults to `false`.\n\nYou might want to disable this if the `subject_claim` returned by the mapping provider is not `sub`."
+ }
+ }
+ },
+ "default": [],
+ "examples": [
+ [
+ {
+ "idp_id": "my_idp",
+ "idp_name": "My OpenID provider",
+ "idp_icon": "mxc://example.com/mediaid",
+ "discover": false,
+ "issuer": "https://accounts.example.com/",
+ "client_id": "provided-by-your-issuer",
+ "client_secret": "provided-by-your-issuer",
+ "client_auth_method": "client_secret_post",
+ "scopes": [
+ "openid",
+ "profile"
+ ],
+ "authorization_endpoint": "https://accounts.example.com/oauth2/auth",
+ "token_endpoint": "https://accounts.example.com/oauth2/token",
+ "userinfo_endpoint": "https://accounts.example.com/userinfo",
+ "jwks_uri": "https://accounts.example.com/.well-known/jwks.json",
+ "additional_authorization_parameters": {
+ "acr_values": "2fa"
+ },
+ "passthrough_authorization_parameters": [
+ "login_hint"
+ ],
+ "skip_verification": true,
+ "enable_registration": true,
+ "user_mapping_provider": {
+ "config": {
+ "subject_claim": "id",
+ "localpart_template": "{{ user.login }}",
+ "display_name_template": "{{ user.name }}",
+ "email_template": "{{ user.email }}"
+ }
+ },
+ "attribute_requirements": [
+ {
+ "attribute": "userGroup",
+ "value": "synapseUsers"
+ }
+ ]
+ }
+ ]
+ ]
+ },
+ "cas_config": {
+ "type": "object",
+ "description": "Enable Central Authentication Service (CAS) for registration and login.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Set this to true to enable authorization against a CAS server.",
+ "default": false
+ },
+ "idp_name": {
+ "type": "string",
+ "description": "A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms."
+ },
+ "idp_icon": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format `mxc:///`. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the URL from the source of the event.)",
+ "default": null
+ },
+ "idp_brand": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the [spec](https://spec.matrix.org/latest/) for possible options here.",
+ "default": null
+ },
+ "server_url": {
+ "type": "string",
+ "description": "The URL of the CAS authorization endpoint."
+ },
+ "protocol_version": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "The CAS protocol version. (Version 3 is required if you want to use `required_attributes`).",
+ "default": null
+ },
+ "displayname_attribute": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The attribute of the CAS response to use as the display name. If no name is given here, no displayname will be set.",
+ "default": null
+ },
+ "required_attributes": {
+ "type": "object",
+ "description": "It is possible to configure Synapse to only allow logins if CAS attributes match particular values. All of the keys given below must exist and the values must match the given value. Alternately if the given value is `None` then any value is allowed (the attribute just must exist). All of the listed attributes must match for the login to be permitted.",
+ "additionalProperties": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "default": {}
+ },
+ "enable_registration": {
+ "type": "boolean",
+ "description": "Set to `false` to disable automatic registration of new users. This allows the CAS SSO flow to be limited to sign in only, rather than automatically registering users that have a valid SSO login but do not have a pre-registered account.",
+ "default": true
+ },
+ "allow_numeric_ids": {
+ "type": "boolean",
+ "description": "Set to `true` allow numeric user IDs. This allows CAS SSO flow to provide user IDs composed of numbers only. These identifiers will be prefixed by the letter \"u\" by default. The prefix can be configured using the `numeric_ids_prefix` option. Be careful to choose the prefix correctly to avoid any possible conflicts (e.g. user 1234 becomes u1234 when a user u1234 already exists).",
+ "default": false
+ },
+ "numeric_ids_prefix": {
+ "type": "string",
+ "description": "The prefix you wish to add in front of a numeric user ID when the `allow_numeric_ids` option is set to `true`. Only alphanumeric characters are allowed.\n\n*Added in Synapse 1.93.0.*",
+ "default": "u"
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "server_url": "https://cas-server.com",
+ "protocol_version": 3,
+ "displayname_attribute": "name",
+ "required_attributes": {
+ "userGroup": "staff",
+ "department": "None"
+ },
+ "enable_registration": true,
+ "allow_numeric_ids": true,
+ "numeric_ids_prefix": "numericuser"
+ }
+ ]
+ },
+ "sso": {
+ "type": "object",
+ "description": "Additional settings to use with single-sign on systems such as OpenID Connect, SAML2 and CAS.\n\nServer admins can configure custom templates for pages related to SSO. See [here](../../templates.md) for more information.",
+ "properties": {
+ "client_whitelist": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "A list of client URLs which are whitelisted so that the user does not have to confirm giving access to their account to the URL. Any client whose URL starts with an entry in the following list will not be subject to an additional confirmation step after the SSO login is completed.\n\nWARNING: An entry such as \"https://my.client\" is insecure, because it will also match \"https://my.client.evil.site\", exposing your users to phishing attacks from evil.site. To avoid this, include a slash after the hostname: \"https://my.client/\".\n\nThe login fallback page (used by clients that don't natively support the required login flows) is whitelisted in addition to any URLs in this list. By default, this list contains only the login fallback page.",
+ "items": {
+ "type": "string"
+ },
+ "default": null
+ },
+ "update_profile_information": {
+ "type": "boolean",
+ "description": "Use this setting to keep a user's profile fields in sync with information from the identity provider. Currently only syncing the displayname is supported. Fields are checked on every SSO login, and are updated if necessary. Note that enabling this option will override user profile information, regardless of whether users have opted-out of syncing that information when first signing in.",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "client_whitelist": [
+ "https://riot.im/develop",
+ "https://my.custom.client/"
+ ],
+ "update_profile_information": true
+ }
+ ]
+ },
+ "jwt_config": {
+ "type": "object",
+ "description": "JSON web token integration. The following settings can be used to make Synapse JSON web tokens for authentication, instead of its internal password database.\n\nEach JSON Web Token needs to contain a \"sub\" (subject) claim, which is used as the localpart of the mxid.\n\nAdditionally, the expiration time (\"exp\"), not before time (\"nbf\"), and issued at (\"iat\") claims are validated if present.\n\nNote that this is a non-standard login type and client support is expected to be non-existent.\n\nSee [here](../../jwt.md) for more.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Set to true to enable authorization using JSON web tokens.",
+ "default": false
+ },
+ "secret": {
+ "type": "string",
+ "description": "This is either the private shared secret or the public key used to decode the contents of the JSON web token. Required if `enabled` is set to true."
+ },
+ "algorithm": {
+ "type": "string",
+ "description": "The algorithm used to sign (or HMAC) the JSON web token. Supported algorithms are listed [here (section JWS)](https://docs.authlib.org/en/latest/specs/rfc7518.html). Required if `enabled` is set to true."
+ },
+ "subject_claim": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Name of the claim containing a unique identifier for the user.",
+ "default": "sub"
+ },
+ "display_name_claim": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Name of the claim containing the display name for the user. If provided, the display name will be set to the value of this claim upon first login.",
+ "default": null
+ },
+ "issuer": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The issuer to validate the \"iss\" claim against. If provided the \"iss\" claim will be required and validated for all JSON web tokens.",
+ "default": null
+ },
+ "audiences": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "A list of audiences to validate the \"aud\" claim against. If provided the \"aud\" claim will be required and validated for all JSON web tokens. Note that if the \"aud\" claim is included in a JSON web token then validation will fail without configuring audiences.",
+ "items": {
+ "type": "string"
+ },
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "secret": "provided-by-your-issuer",
+ "algorithm": "provided-by-your-issuer",
+ "subject_claim": "name_of_claim",
+ "display_name_claim": "name_of_claim",
+ "issuer": "provided-by-your-issuer",
+ "audiences": [
+ "provided-by-your-issuer"
+ ]
+ }
+ ]
+ },
+ "password_config": {
+ "type": "object",
+ "description": "Use this setting to enable password-based logins.",
+ "properties": {
+ "enabled": {
+ "type": [
+ "boolean",
+ "string"
+ ],
+ "enum": [
+ true,
+ false,
+ "only_for_reauth"
+ ],
+ "description": "Set to false to disable password authentication. Set to `only_for_reauth` to allow users with existing passwords to use them to reauthenticate (not log in), whilst preventing new users from setting passwords.",
+ "default": true
+ },
+ "localdb_enabled": {
+ "type": "boolean",
+ "description": "Set to false to disable authentication against the local password database. This is ignored if `enabled` is false, and is only useful if you have other `password_providers`.",
+ "default": true
+ },
+ "pepper": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Set the value here to a secret random string for extra security. DO NOT CHANGE THIS AFTER INITIAL SETUP!",
+ "default": null
+ },
+ "policy": {
+ "type": "object",
+ "description": "Define and enforce a password policy, such as minimum lengths for passwords, etc. This is an implementation of MSC2000.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Set to true to enable.",
+ "default": false
+ },
+ "minimum_length": {
+ "type": "integer",
+ "description": "Minimum accepted length for a password.",
+ "default": 0
+ },
+ "require_digit": {
+ "type": "boolean",
+ "description": "Whether a password must contain at least one digit.",
+ "default": false
+ },
+ "require_symbol": {
+ "type": "boolean",
+ "description": "Whether a password must contain at least one symbol. A symbol is any character that's not a number or a letter.",
+ "default": false
+ },
+ "require_lowercase": {
+ "type": "boolean",
+ "description": "Whether a password must contain at least one lowercase letter.",
+ "default": false
+ },
+ "require_uppercase": {
+ "type": "boolean",
+ "description": "Whether a password must contain at least one uppercase letter.",
+ "default": false
+ }
+ }
+ }
+ },
+ "examples": [
+ {
+ "enabled": false,
+ "localdb_enabled": false,
+ "pepper": "EVEN_MORE_SECRET",
+ "policy": {
+ "enabled": true,
+ "minimum_length": 15,
+ "require_digit": true,
+ "require_symbol": true,
+ "require_lowercase": true,
+ "require_uppercase": true
+ }
+ }
+ ]
+ },
+ "push": {
+ "type": "object",
+ "description": "This setting defines options for push notifications.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Enables or disables push notification calculation. Note, disabling this will also stop unread counts being calculated for rooms. This mode of operation is intended for homeservers which may only have bots or appservice users connected, or are otherwise not interested in push/unread counters.",
+ "default": true
+ },
+ "include_content": {
+ "type": "boolean",
+ "description": "Clients requesting push notifications can either have the body of the message sent in the notification poke along with other details like the sender, or just the event ID and room ID (`event_id_only`). If clients choose to have the body sent, this option controls whether the notification request includes the content of the event (other details like the sender are still included). If `event_id_only` is enabled, it has no effect. For modern Android devices the notification content will still appear because it is loaded by the app. iPhone, however will send a notification saying only that a message arrived and who it came from. Set to false to only include the event ID and room ID in push notification payloads.",
+ "default": true
+ },
+ "group_unread_count_by_room": {
+ "type": "boolean",
+ "description": "When a push notification is received, an unread count is also sent. This number can either be calculated as the number of unread messages for the user, or the number of *rooms* the user has unread messages in. If true, push clients will see the number of rooms with unread messages in them. Set to false to instead send the number of unread messages.",
+ "default": true
+ },
+ "jitter_delay": {
+ "$ref": "#/$defs/duration",
+ "description": "Delays push notifications by a random amount up to the given duration. Useful for mitigating timing attacks. Optional.\n\n_Added in Synapse 1.84.0._",
+ "default": "0s"
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "include_content": false,
+ "group_unread_count_by_room": false,
+ "jitter_delay": "10s"
+ }
+ ]
+ },
+ "encryption_enabled_by_default_for_room_type": {
+ "type": "string",
+ "description": "Controls whether locally-created rooms should be end-to-end encrypted by default.\n\nPossible options are \"all\", \"invite\", and \"off\". They are defined as:\n\n* \"all\": any locally-created room\n* \"invite\": any room created with the `private_chat` or `trusted_private_chat` room creation presets\n* \"off\": this option will take no effect\n\nNote that this option will only affect rooms created after it is set. It will also not affect rooms created by other servers.",
+ "enum": [
+ "all",
+ "invite",
+ "off"
+ ],
+ "default": "off",
+ "examples": [
+ "invite"
+ ]
+ },
+ "user_directory": {
+ "type": "object",
+ "description": "This setting defines options related to the user directory.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Defines whether users can search the user directory. If false then empty responses are returned to all queries.",
+ "default": true
+ },
+ "search_all_users": {
+ "type": "boolean",
+ "description": "Defines whether to search all users visible to your homeserver at the time the search is performed. If set to true, will return all users known to the homeserver matching the search query. If false, search results will only contain users visible in public rooms and users sharing a room with the requester.\n\nNB. If you set this to true, and the last time the user_directory search indexes were (re)built was before Synapse 1.44, you'll have to rebuild the indexes in order to search through all known users.\n\nThese indexes are built the first time Synapse starts; admins can manually trigger a rebuild via the API following the instructions [for running background updates](../administration/admin_api/background_updates.md#run), set to true to return search results containing all known users, even if that user does not share a room with the requester.",
+ "default": false
+ },
+ "prefer_local_users": {
+ "type": "boolean",
+ "description": "Defines whether to prefer local users in search query results. If set to true, local users are more likely to appear above remote users when searching the user directory.",
+ "default": false
+ },
+ "exclude_remote_users": {
+ "type": "boolean",
+ "description": "If set to true, the search will only return local users.",
+ "default": false
+ },
+ "show_locked_users": {
+ "type": "boolean",
+ "description": "Defines whether to show locked users in search query results.",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "enabled": false,
+ "search_all_users": true,
+ "prefer_local_users": true,
+ "exclude_remote_users": false,
+ "show_locked_users": true
+ }
+ ]
+ },
+ "user_consent": {
+ "type": "object",
+ "description": "For detailed instructions on user consent configuration, see [here](../../consent_tracking.md).\n\nParts of this section are required if enabling the `consent` resource under [`listeners`](#listeners), in particular `template_dir` and `version`.",
+ "properties": {
+ "template_dir": {
+ "type": "string",
+ "description": "Gives the location of the templates for the HTML forms. This directory should contain one subdirectory per language (eg, `en`, `fr`), and each language directory should contain the policy document (named as .html) and a success page (success.html)."
+ },
+ "version": {
+ "type": "number",
+ "description": "Specifies the \"current\" version of the policy document. It defines the version to be served by the consent resource if there is no `v` parameter."
+ },
+ "server_notice_content": {
+ "type": "object",
+ "description": "If enabled, will send a user a \"Server Notice\" asking them to consent to the privacy policy. The [`server_notices` section](#server_notices) must also be configured for this to work. Notices will *not* be sent to guest users unless `send_server_notice_to_guests` is set to true.",
+ "properties": {
+ "msgtype": {
+ "type": "string",
+ "description": "Message type of the notice event."
+ },
+ "body": {
+ "type": "string",
+ "description": "Message template for the server notice event body."
+ }
+ }
+ },
+ "send_server_notice_to_guests": {
+ "type": "boolean",
+ "description": "Send server notices to guest users, too.",
+ "default": false
+ },
+ "block_events_error": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "If set, will block any attempts to send events until the user consents to the privacy policy. The value of the setting is used as the text of the error.",
+ "default": null
+ },
+ "require_at_registration": {
+ "type": "boolean",
+ "description": "If enabled, will add a step to the registration process, similar to how captcha works. Users will be required to accept the policy before their account is created."
+ },
+ "policy_name": {
+ "type": "string",
+ "description": "Human-readable name of the privacy policy.",
+ "default": "Privacy Policy"
+ }
+ },
+ "examples": [
+ {
+ "template_dir": "res/templates/privacy",
+ "version": 1.0,
+ "server_notice_content": {
+ "msgtype": "m.text",
+ "body": "To continue using this homeserver you must review and agree to the terms and conditions at %(consent_uri)s"
+ },
+ "send_server_notice_to_guests": true,
+ "block_events_error": "To continue using this homeserver you must review and agree to the terms and conditions at %(consent_uri)s",
+ "require_at_registration": false,
+ "policy_name": "Privacy Policy"
+ }
+ ]
+ },
+ "stats": {
+ "type": "object",
+ "description": "Settings for local room and user statistics collection. See [here](../../room_and_user_statistics.md) for more.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Set to false to disable room and user statistics. Note that doing so may cause certain features (such as the room directory) not to work correctly.",
+ "default": true
+ }
+ },
+ "examples": [
+ {
+ "enabled": false
+ }
+ ]
+ },
+ "server_notices": {
+ "type": "object",
+ "description": "Use this setting to enable a room which can be used to send notices from the server to users. It is a special room which users cannot leave; notices in the room come from a special \"notices\" user id.\n\nIf you use this setting, you *must* define the `system_mxid_localpart` sub-setting, which defines the id of the user which will be used to send the notices.\n\nNote that the name, topic and avatar of existing server notice rooms will only be updated when a new notice event is sent.",
+ "properties": {
+ "system_mxid_display_name": {
+ "type": "string",
+ "description": "Display name of the \"notices\" user.",
+ "default": "Notices"
+ },
+ "system_mxid_avatar_url": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Avatar for the \"notices\" user.",
+ "default": null
+ },
+ "room_name": {
+ "type": "string",
+ "description": "Room name of the server notices room.",
+ "default": "Server Notices"
+ },
+ "room_avatar_url": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Room avatar to use for server notice rooms. If set to the empty string `\"\"`, notice rooms will not be given an avatar.\n\n_Added in Synapse 1.99.0._",
+ "default": null
+ },
+ "room_topic": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Topic to use for server notice rooms. If set to the empty string `\"\"`, notice rooms will not be given a topic. Defaults to the empty string.\n\n_Added in Synapse 1.99.0._",
+ "default": null
+ },
+ "auto_join": {
+ "type": "boolean",
+ "description": "If true, the user will be automatically joined to the room instead of being invited.\n\n_Added in Synapse 1.98.0._",
+ "default": false
+ }
+ },
+ "examples": [
+ {
+ "system_mxid_localpart": "notices",
+ "system_mxid_display_name": "Server Notices",
+ "system_mxid_avatar_url": "mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ",
+ "room_name": "Server Notices",
+ "room_avatar_url": "mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ",
+ "room_topic": "Room used by your server admin to notice you of important information",
+ "auto_join": true
+ }
+ ]
+ },
+ "enable_room_list_search": {
+ "type": "boolean",
+ "description": "Set to false to disable searching the public room list. When disabled blocks searching local and remote room lists for local and remote users by always returning an empty list for all queries.",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "alias_creation_rules": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "The `alias_creation_rules` option allows server admins to prevent unwanted alias creation on this server.\n\nThis setting is an optional list of 0 or more rules. By default, no list is provided, meaning that all alias creations are permitted.\n\nOtherwise, requests to create aliases are matched against each rule in order. The first rule that matches decides if the request is allowed or denied. If no rule matches, the request is denied. In particular, this means that configuring an empty list of rules will deny every alias creation request.\n\nEach of the glob patterns is optional, defaulting to `*` (\"match anything\"). Note that the patterns match against fully qualified IDs, e.g. against `@alice:example.com`, `#room:example.com` and `!abcdefghijk:example.com` instead of `alice`, `room` and `abcedgghijk`.\n\nEach rule is a YAML object containing four fields, each of which is an optional string",
+ "items": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against the creator of the alias."
+ },
+ "alias": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against the alias being created."
+ },
+ "room_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against the room ID the alias is being pointed at."
+ },
+ "action": {
+ "type": "string",
+ "enum": [
+ "allow",
+ "deny"
+ ],
+ "description": "Either `allow` or `deny`. What to do with the request if the rule matches. Defaults to `allow`."
+ }
+ }
+ },
+ "default": null,
+ "examples": [
+ null,
+ [
+ {
+ "action": "allow"
+ }
+ ],
+ [],
+ [
+ {
+ "action": "deny"
+ }
+ ],
+ [
+ {
+ "user_id": "@bad_user:example.com",
+ "action": "deny"
+ },
+ {
+ "action": "allow"
+ }
+ ],
+ [
+ {
+ "room_id": "!forbiddenRoom:example.com",
+ "action": "deny"
+ },
+ {
+ "action": "allow"
+ }
+ ]
+ ]
+ },
+ "room_list_publication_rules": {
+ "type": [
+ "array",
+ "null"
+ ],
+ "description": "The `room_list_publication_rules` option allows server admins to prevent unwanted entries from being published in the public room list.\n\nThe format of this option is the same as that for [`alias_creation_rules`](#alias_creation_rules): an optional list of 0 or more rules. By default, no list is provided, meaning that no one may publish to the room list (except server admins).\n\nOtherwise, requests to publish a room are matched against each rule in order. The first rule that matches decides if the request is allowed or denied. If no rule matches, the request is denied. In particular, this means that configuring an empty list of rules will deny every alias creation request.\n\nRequests to create a public (public as in published to the room directory) room which violates the configured rules will result in the room being created but not published to the room directory.\n\nEach of the glob patterns is optional, defaulting to `*` (\"match anything\"). Note that the patterns match against fully qualified IDs, e.g. against `@alice:example.com`, `#room:example.com` and `!abcdefghijk:example.com` instead of `alice`, `room` and `abcedgghijk`.\n\nEach rule is a YAML object containing four fields, each of which is an optional string.\n\n_Changed in Synapse 1.126.0: The default was changed to deny publishing to the room list by default_",
+ "items": {
+ "type": "object",
+ "properties": {
+ "user_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against the user publishing the room."
+ },
+ "alias": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against one of published room's aliases.\n- If the room has no aliases, the alias match fails unless `alias` is unspecified or `*`.\n- If the room has exactly one alias, the alias match succeeds if the `alias` pattern matches that alias.\n- If the room has two or more aliases, the alias match succeeds if the pattern matches at least one of the aliases."
+ },
+ "room_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Glob pattern that matches against the room ID of the room being published."
+ },
+ "action": {
+ "type": "string",
+ "enum": [
+ "allow",
+ "deny"
+ ],
+ "description": "Either `allow` or `deny`. What to do with the request if the rule matches. Defaults to `allow`."
+ }
+ }
+ },
+ "default": null,
+ "examples": [
+ null,
+ [
+ {
+ "action": "deny"
+ }
+ ],
+ [],
+ [
+ {
+ "action": "allow"
+ }
+ ],
+ [
+ {
+ "user_id": "@bad_user:example.com",
+ "action": "deny"
+ },
+ {
+ "action": "allow"
+ }
+ ],
+ [
+ {
+ "room_id": "!forbiddenRoom:example.com",
+ "action": "deny"
+ },
+ {
+ "action": "allow"
+ }
+ ],
+ [
+ {
+ "alias": "#*potato*:example.com",
+ "action": "deny"
+ },
+ {
+ "action": "allow"
+ }
+ ]
+ ]
+ },
+ "default_power_level_content_override": {
+ "type": "object",
+ "description": "The `default_power_level_content_override` option controls the default power levels for rooms.\n\nUseful if you know that your users need special permissions in rooms that they create (e.g. to send particular types of state events without needing an elevated power level). This takes the same shape as the `power_level_content_override` parameter in the /createRoom API, but is applied before that parameter.\n\nNote that each key provided inside a preset (for example `events` in the example below) will overwrite all existing defaults inside that key. So in Example #1, newly-created private_chat rooms will have no rules for any event types except `com.example.foo`.\n\nThe default power levels for each preset are:\n\n```yaml\n\"m.room.name\": 50\n\"m.room.power_levels\": 100\n\"m.room.history_visibility\": 100\n\"m.room.canonical_alias\": 50\n\"m.room.avatar\": 50\n\"m.room.tombstone\": 100\n\"m.room.server_acl\": 100\n\"m.room.encryption\": 100\n```\n\nIn Example #2 the default power-levels for a preset are maintained, but the power level for a new key is set.",
+ "default": {},
+ "examples": [
+ {
+ "private_chat": {
+ "events": {
+ "com.example.foo": 0
+ }
+ },
+ "trusted_private_chat": null,
+ "public_chat": null
+ },
+ {
+ "private_chat": {
+ "events": {
+ "com.example.foo": 0,
+ "m.room.name": 50,
+ "m.room.power_levels": 100,
+ "m.room.history_visibility": 100,
+ "m.room.canonical_alias": 50,
+ "m.room.avatar": 50,
+ "m.room.tombstone": 100,
+ "m.room.server_acl": 100,
+ "m.room.encryption": 100
+ }
+ },
+ "trusted_private_chat": null,
+ "public_chat": null
+ }
+ ]
+ },
+ "forget_rooms_on_leave": {
+ "type": "boolean",
+ "description": "Set to true to automatically forget rooms for users when they leave them, either normally or via a kick or ban.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "exclude_rooms_from_sync": {
+ "type": "array",
+ "description": "A list of rooms to exclude from sync responses. This is useful for server administrators wishing to group users into a room without these users being able to see it from their client.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "!foo:example.com"
+ ]
+ ]
+ },
+ "opentracing": {
+ "type": "object",
+ "description": "These settings enable and configure opentracing, which implements distributed tracing. This allows you to observe the causal chains of events across servers including requests, key lookups etc., across any server running synapse or any other services which support opentracing (specifically those implemented with Jaeger).",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether tracing is enabled. Set to true to enable.",
+ "default": false
+ },
+ "homeserver_whitelist": {
+ "type": "array",
+ "description": "The list of homeservers we wish to send and receive span contexts and span baggage. See [here](../../opentracing.md) for more. This is a list of regexes which are matched against the `server_name` of the homeserver. If the list is empty, no servers are matched.",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "force_tracing_for_users": {
+ "type": "array",
+ "description": "A list of the matrix IDs of users whose requests will always be traced, even if the tracing system would otherwise drop the traces due to probabilistic sampling.",
+ "items": {
+ "type": "string"
+ },
+ "default": []
+ },
+ "jaeger_config": {
+ "type": "object",
+ "description": "Jaeger can be configured to sample traces at different rates. All configuration options provided by Jaeger can be set here. Jaeger's configuration is mostly related to trace sampling which is documented [here](https://www.jaegertracing.io/docs/latest/sampling/).",
+ "default": {}
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "homeserver_whitelist": [
+ ".*"
+ ],
+ "force_tracing_for_users": [
+ "@user1:server_name",
+ "@user2:server_name"
+ ],
+ "jaeger_config": {
+ "sampler": {
+ "type": "const",
+ "param": 1
+ },
+ "logging": false
+ }
+ }
+ ]
+ },
+ "worker_replication_secret": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "A shared secret used by the replication APIs on the main process to authenticate HTTP requests from workers.\n\nIf unset or null, traffic between the workers and the main process is not authenticated.\n\nReplacing an existing `worker_replication_secret` with a new one will break communication with all workers that have not yet updated their secret.",
+ "default": null,
+ "examples": [
+ "secret_secret"
+ ]
+ },
+ "worker_replication_secret_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "An alternative to [`worker_replication_secret`](#worker_replication_secret): allows the secret to be specified in an external file.\n\nThe file should be a plain text file, containing only the secret. Synapse reads the secret from the given file once at startup.\n\n_Added in Synapse 1.126.0._",
+ "default": null,
+ "examples": [
+ "/path/to/secrets/file"
+ ]
+ },
+ "start_pushers": {
+ "type": "boolean",
+ "description": "Unnecessary to set if using [`pusher_instances`](#pusher_instances) with [`generic_workers`](../../workers.md#synapseappgeneric_worker).\n\nControls sending of push notifications on the main process. Set to `false` if using a [pusher worker](../../workers.md#synapseapppusher).",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "pusher_instances": {
+ "type": "array",
+ "description": "It is possible to scale the processes that handle sending push notifications to [sygnal](https://github.com/matrix-org/sygnal) and email by running a [`generic_worker`](../../workers.md#synapseappgeneric_worker) and adding it's [`worker_name`](#worker_name) to a `pusher_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. Ensure the main process and all pusher workers are restarted after changing this option.",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "pusher_worker1"
+ ],
+ [
+ "pusher_worker1",
+ "pusher_worker2"
+ ]
+ ]
+ },
+ "send_federation": {
+ "type": "boolean",
+ "description": "Unnecessary to set if using [`federation_sender_instances`](#federation_sender_instances) with [`generic_workers`](../../workers.md#synapseappgeneric_worker).\n\nControls sending of outbound federation transactions on the main process. Set to `false` if using a [federation sender worker](../../workers.md#synapseappfederation_sender).",
+ "default": true,
+ "examples": [
+ false
+ ]
+ },
+ "federation_sender_instances": {
+ "type": "array",
+ "description": "It is possible to scale the processes that handle sending outbound federation requests 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.\n\nThe 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 with multiple servers.\n\nThis configuration setting must be shared between all workers handling federation sending, and if changed all federation sender workers must be stopped at the same time and then started, to ensure that all instances are running with the same config (otherwise events may be dropped).",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "federation_sender1"
+ ],
+ [
+ "federation_sender1",
+ "federation_sender2"
+ ]
+ ]
+ },
+ "instance_map": {
+ "type": "object",
+ "description": "When using workers this should be a map from [`worker_name`](#worker_name) to the HTTP replication listener of the worker, if configured, and to the main process. Each worker declared under [`stream_writers`](../../workers.md#stream-writers) and [`outbound_federation_restricted_to`](#outbound_federation_restricted_to) needs a HTTP replication listener, and that listener should be included in the `instance_map`. The main process also needs an entry on the `instance_map`, and it should be listed under `main` **if even one other worker exists**. Ensure the port matches with what is declared inside the `listener` block for a `replication` listener.",
+ "additionalProperties": {
+ "type": "object"
+ },
+ "default": {},
+ "examples": [
+ {
+ "main": {
+ "host": "localhost",
+ "port": 8030
+ },
+ "worker1": {
+ "host": "localhost",
+ "port": 8034
+ },
+ "other": {
+ "host": "localhost",
+ "port": 8035,
+ "tls": true
+ }
+ },
+ {
+ "main": {
+ "path": "/run/synapse/main_replication.sock"
+ },
+ "worker1": {
+ "path": "/run/synapse/worker1_replication.sock"
+ }
+ }
+ ]
+ },
+ "stream_writers": {
+ "type": "object",
+ "description": "Experimental: When using workers you can define which workers should handle writing to streams such as event persistence and typing notifications. Any worker specified here must also be in the [`instance_map`](#instance_map).\n\nSee the list of available streams in the [worker documentation](../../workers.md#stream-writers).",
+ "properties": {
+ "events": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `events` stream."
+ },
+ "typing": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `typing` stream."
+ },
+ "to_device": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `to_device` stream."
+ },
+ "account_data": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `account_data` stream."
+ },
+ "receipts": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `receipts` stream."
+ },
+ "presence": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `presence` stream."
+ },
+ "push_rules": {
+ "type": "string",
+ "description": "Name of a worker assigned to the `push_rules` stream."
+ }
+ },
+ "default": {},
+ "examples": [
+ {
+ "events": "worker1",
+ "typing": "worker1"
+ }
+ ]
+ },
+ "outbound_federation_restricted_to": {
+ "type": "array",
+ "description": "When using workers, you can restrict outbound federation traffic to only go through a specific subset of workers. Any worker specified here must also be in the [`instance_map`](#instance_map). [`worker_replication_secret`](#worker_replication_secret) must also be configured to authorize inter-worker communication.\n\nAlso see the [worker documentation](../../workers.md#restrict-outbound-federation-traffic-to-a-specific-set-of-workers) for more info.\n\n_Added in Synapse 1.89.0._",
+ "items": {
+ "type": "string"
+ },
+ "default": [],
+ "examples": [
+ [
+ "federation_sender1",
+ "federation_sender2"
+ ]
+ ]
+ },
+ "run_background_tasks_on": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The [worker](../../workers.md#background-tasks) that is used to run background tasks (e.g. cleaning up expired data). If not provided this defaults to the main process.",
+ "default": null,
+ "examples": [
+ "worker1"
+ ]
+ },
+ "update_user_directory_from_worker": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The [worker](../../workers.md#updating-the-user-directory) that is used to update the user directory. If not provided this defaults to the main process.\n\n_Added in Synapse 1.59.0._",
+ "default": null,
+ "examples": [
+ "worker1"
+ ]
+ },
+ "notify_appservices_from_worker": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The [worker](../../workers.md#notifying-application-services) that is used to send output traffic to Application Services. If not provided this defaults to the main process.\n\n_Added in Synapse 1.59.0._",
+ "default": null,
+ "examples": [
+ "worker1"
+ ]
+ },
+ "media_instance_running_background_jobs": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "The [worker](../../workers.md#synapseappmedia_repository) that is used to run background tasks for media repository. If running multiple media repositories you must configure a single instance to run the background tasks. If not provided this defaults to the main process or your single `media_repository` worker.\n\n_Added in Synapse 1.16.0._",
+ "default": null,
+ "examples": [
+ "worker1"
+ ]
+ },
+ "redis": {
+ "type": "object",
+ "description": "Configuration for Redis when using workers. This *must* be enabled when using workers.\n\n_Added in Synapse 1.78.0._\n\n_Changed in Synapse 1.84.0: Added use\\_tls, certificate\\_file, private\\_key\\_file, ca\\_file and ca\\_path attributes_\n\n_Changed in Synapse 1.85.0: Added path option to use a local Unix socket_\n\n_Changed in Synapse 1.116.0: Added password\\_path_",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether to use Redis support.",
+ "default": false
+ },
+ "host": {
+ "type": "string",
+ "description": "Optional host to use to connect to Redis.",
+ "default": "localhost"
+ },
+ "port": {
+ "type": "integer",
+ "description": "Optional port to use to connect to Redis.",
+ "default": 6379
+ },
+ "path": {
+ "type": "string",
+ "description": "The full path to a local Unix socket file. **If this is used, `host` and `port` are ignored.**",
+ "default": "/tmp/redis.sock"
+ },
+ "password": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional password if configured on the Redis instance.",
+ "default": null
+ },
+ "password_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Alternative to `password`, reading the password from an external file. The file should be a plain text file, containing only the password. Synapse reads the password from the given file once at startup.",
+ "default": null
+ },
+ "dbid": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional redis dbid if needs to connect to specific redis logical db.",
+ "default": null
+ },
+ "use_tls": {
+ "type": "boolean",
+ "description": "Whether to use a TLS connection.",
+ "default": false
+ },
+ "certificate_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional path to the certificate file.",
+ "default": null
+ },
+ "private_key_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional path to the private key file.",
+ "default": null
+ },
+ "ca_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional path to the CA certificate file. Use this one or `ca_path`",
+ "default": null
+ },
+ "ca_path": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "Optional path to the folder containing the CA certificate file. Use this one or `ca_file`",
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "host": "localhost",
+ "port": 6379,
+ "password_path": "",
+ "dbid": ""
+ }
+ ]
+ },
+ "worker_app": {
+ "type": "string",
+ "description": "The type of worker. The currently available worker applications are listed in [worker documentation](../../workers.md#available-worker-applications).\n\nThe most common worker is the [`synapse.app.generic_worker`](../../workers.md#synapseappgeneric_worker).",
+ "examples": [
+ "synapse.app.generic_worker"
+ ]
+ },
+ "worker_name": {
+ "type": "string",
+ "description": "A unique name for the worker. The worker needs a name to be addressed in further parameters and identification in log files. We strongly recommend giving each worker a unique `worker_name`.",
+ "examples": [
+ "generic_worker1"
+ ]
+ },
+ "worker_listeners": {
+ "type": "array",
+ "description": "A worker can handle HTTP requests. To do so, a `worker_listeners` option must be declared, in the same way as the [`listeners` option](#listeners) in the shared config.\n\nWorkers declared in [`stream_writers`](#stream_writers) and [`instance_map`](#instance_map) will need to include a `replication` listener here, in order to accept internal HTTP requests from other workers.\n\nExample #2 is using UNIX sockets with a `replication` listener.",
+ "default": [],
+ "examples": [
+ [
+ {
+ "type": "http",
+ "port": 8083,
+ "resources": [
+ {
+ "names": [
+ "client",
+ "federation"
+ ]
+ }
+ ]
+ }
+ ],
+ [
+ {
+ "type": "http",
+ "path": "/run/synapse/worker_replication.sock",
+ "resources": [
+ {
+ "names": [
+ "replication"
+ ]
+ }
+ ]
+ },
+ {
+ "type": "http",
+ "path": "/run/synapse/worker_public.sock",
+ "resources": [
+ {
+ "names": [
+ "client",
+ "federation"
+ ]
+ }
+ ]
+ }
+ ]
+ ]
+ },
+ "worker_manhole": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "description": "A worker may have a listener for [`manhole`](../../manhole.md). It allows server administrators to access a Python shell on the worker.\n\nThe example below is a short form for\n```yaml\nworker_listeners:\n - port: 9000\n bind_addresses: ['127.0.0.1']\n type: manhole\n```\n\nIt needs also an additional [`manhole_settings`](#manhole_settings) configuration.",
+ "default": null,
+ "examples": [
+ 9000
+ ]
+ },
+ "worker_daemonize": {
+ "type": "boolean",
+ "description": "Specifies whether the worker should be started as a daemon process. If Synapse is being managed by [systemd](../../systemd-with-workers/), this option must be omitted or set to `false`.",
+ "default": false,
+ "examples": [
+ true
+ ]
+ },
+ "worker_pid_file": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "When running a worker as a daemon, we need a place to store the [PID](https://en.wikipedia.org/wiki/Process_identifier) of the worker. This option defines the location of that \"pid file\".\n\nThis option is required if `worker_daemonize` is `true` and ignored otherwise.\n\nSee also the [`pid_file` option](#pid_file) option for the main Synapse process.",
+ "default": null,
+ "examples": [
+ "DATADIR/generic_worker1.pid"
+ ]
+ },
+ "worker_log_config": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "This option specifies a yaml python logging config file as described [here](https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema). See also the [`log_config` option](#log_config) option for the main Synapse process.",
+ "default": null,
+ "examples": [
+ "/etc/matrix-synapse/generic-worker-log.yaml"
+ ]
+ },
+ "background_updates": {
+ "type": "object",
+ "description": "Background updates are database updates that are run in the background in batches. The duration, minimum batch size, default batch size, whether to sleep between batches and if so, how long to sleep can all be configured. This is helpful to speed up or slow down the updates.",
+ "properties": {
+ "background_update_duration_ms": {
+ "type": "integer",
+ "description": "How long in milliseconds to run a batch of background updates for.",
+ "default": 100
+ },
+ "sleep_enabled": {
+ "type": "boolean",
+ "description": "Whether to sleep between updates.",
+ "default": true
+ },
+ "sleep_duration_ms": {
+ "type": "integer",
+ "description": "If sleeping between updates, how long in milliseconds to sleep for.",
+ "default": 1000
+ },
+ "min_batch_size": {
+ "type": "integer",
+ "description": "Minimum size a batch of background updates can be. Must be greater than 0.",
+ "default": 1
+ },
+ "default_batch_size": {
+ "type": "integer",
+ "description": "The batch size to use for the first iteration of a new background update.",
+ "default": 100
+ }
+ },
+ "examples": [
+ {
+ "background_update_duration_ms": 500,
+ "sleep_enabled": false,
+ "sleep_duration_ms": 300,
+ "min_batch_size": 10,
+ "default_batch_size": 50
+ }
+ ]
+ },
+ "auto_accept_invites": {
+ "type": "object",
+ "description": "Automatically accepting invites controls whether users are presented with an invite request or if they are instead automatically joined to a room when receiving an invite. Set the `enabled` sub-option to true to enable auto-accepting invites.\n\nNOTE: Care should be taken not to enable this setting if the `synapse_auto_accept_invite` module is enabled and installed. The two modules will compete to perform the same task and may result in undesired behaviour. For example, multiple join events could be generated from a single invite.",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "description": "Whether to run the auto-accept invites logic.",
+ "default": false
+ },
+ "only_for_direct_messages": {
+ "type": "boolean",
+ "description": "Whether invites should be automatically accepted for all room types, or only for direct messages.",
+ "default": false
+ },
+ "only_from_local_users": {
+ "type": "boolean",
+ "description": "Whether to only automatically accept invites from users on this homeserver.",
+ "default": false
+ },
+ "worker_to_run_on": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "description": "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.",
+ "default": null
+ }
+ },
+ "examples": [
+ {
+ "enabled": true,
+ "only_for_direct_messages": true,
+ "only_from_local_users": true,
+ "worker_to_run_on": "worker_1"
+ }
+ ]
+ }
+ },
+ "$defs": {
+ "bytes": {
+ "type": [
+ "string",
+ "integer"
+ ],
+ "io.element.type_name": "byte size"
+ },
+ "duration": {
+ "type": [
+ "string",
+ "integer"
+ ],
+ "io.element.type_name": "duration"
+ },
+ "size": {
+ "type": [
+ "string",
+ "integer"
+ ],
+ "io.element.type_name": "size"
+ },
+ "3pidmedium": {
+ "type": "string",
+ "enum": [
+ "email",
+ "msisdn"
+ ]
+ },
+ "rc": {
+ "type": "object",
+ "properties": {
+ "per_second": {
+ "type": "number",
+ "description": "Maximum number of requests a client can send per second."
+ },
+ "burst_count": {
+ "type": "number",
+ "description": "Maximum number of requests a client can send before being throttled."
+ }
+ }
+ },
+ "database": {
+ "type": "object",
+ "description": "The `database` setting defines the database that synapse uses to store all of its data.\n\nFor more information on using Synapse with Postgres, see [here](../../postgres.md).",
+ "properties": {
+ "name": {
+ "type": "string",
+ "enum": [
+ "sqlite3",
+ "psycopg2"
+ ],
+ "description": "This option specifies the database engine to use: either `sqlite3` (for SQLite) or `psycopg2` (for PostgreSQL). If no name is specified Synapse will default to SQLite.",
+ "default": "sqlite3"
+ },
+ "txn_limit": {
+ "type": "integer",
+ "description": "Gives the maximum number of transactions to run per connection before reconnecting. 0 means no limit.",
+ "default": 0
+ },
+ "allow_unsafe_locale": {
+ "type": "boolean",
+ "description": "This option is specific to Postgres. Under the default behavior, Synapse will refuse to start if the postgres db is set to a non-C locale. You can override this behavior (which is *not* recommended) by setting `allow_unsafe_locale` to true. Note that doing so may corrupt your database. You can find more information [here](../../postgres.md#fixing-incorrect-collate-or-ctype) and [here](https://wiki.postgresql.org/wiki/Locale_data_changes).",
+ "default": false
+ },
+ "args": {
+ "type": "object",
+ "description": "Gives options which are passed through to the database engine, except for options starting with `cp_`, which are used to configure the Twisted connection pool. For a reference to valid arguments, see:\n* for [sqlite](https://docs.python.org/3/library/sqlite3.html#sqlite3.connect)\n* for [postgres](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS)\n* for [the connection pool](https://docs.twistedmatrix.com/en/stable/api/twisted.enterprise.adbapi.ConnectionPool.html#__init__)"
+ }
+ }
+ }
+ }
+}
diff --git a/latest/schema/v1/meta.schema.json b/latest/schema/v1/meta.schema.json
new file mode 100644
index 0000000000..0c2c46f1a9
--- /dev/null
+++ b/latest/schema/v1/meta.schema.json
@@ -0,0 +1,29 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://element-hq.github.io/synapse/latest/schema/v1/meta.schema.json",
+ "$vocabulary": {
+ "https://json-schema.org/draft/2020-12/vocab/core": true,
+ "https://json-schema.org/draft/2020-12/vocab/applicator": true,
+ "https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
+ "https://json-schema.org/draft/2020-12/vocab/validation": true,
+ "https://json-schema.org/draft/2020-12/vocab/meta-data": true,
+ "https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
+ "https://json-schema.org/draft/2020-12/vocab/content": true,
+ "https://element-hq.github.io/synapse/latest/schema/v1/vocab/documentation": false
+ },
+ "$ref": "https://json-schema.org/draft/2020-12/schema",
+ "properties": {
+ "io.element.type_name": {
+ "type": "string",
+ "description": "Human-readable type of a schema that is displayed instead of the standard JSON Schema types like `object` or `integer`. In case the JSON Schema type contains `null`, this information should be presented alongside the human-readable type name.",
+ "examples": ["duration", "byte size"]
+ },
+ "io.element.post_description": {
+ "type": "string",
+ "description": "Additional description of a schema, better suited to be placed less prominently in the generated documentation, e.g., at the end of a section after listings of items and properties.",
+ "examples": [
+ "### Advanced uses\n\nThe spent coffee grounds can be added to compost for improving soil and growing plants."
+ ]
+ }
+ }
+}
diff --git a/latest/schema/v1/vocab/documentation.html b/latest/schema/v1/vocab/documentation.html
new file mode 100644
index 0000000000..6a45f4beb3
--- /dev/null
+++ b/latest/schema/v1/vocab/documentation.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Redirecting to ../meta.schema.json…
+
+
+ Redirecting to ../meta.schema.json…
+
+
diff --git a/latest/searchindex.js b/latest/searchindex.js
index 1afa0b651d..d09e651496 100644
--- a/latest/searchindex.js
+++ b/latest/searchindex.js
@@ -1 +1 @@
-Object.assign(window.search, {"doc_urls":["welcome_and_overview.html#introduction","welcome_and_overview.html#installing-and-using-synapse","welcome_and_overview.html#developing-on-synapse","welcome_and_overview.html#reporting-a-security-vulnerability","setup/installation.html#installation-instructions","setup/installation.html#choosing-your-server-name","setup/installation.html#installing-synapse","setup/installation.html#prebuilt-packages","setup/installation.html#installing-as-a-python-module-from-pypi","setup/installation.html#setting-up-synapse","setup/installation.html#using-postgresql","setup/installation.html#tls-certificates","setup/installation.html#client-well-known-uri","setup/installation.html#email","setup/installation.html#registering-a-user","setup/installation.html#setting-up-a-turn-server","setup/installation.html#url-previews","setup/installation.html#backups","setup/installation.html#troubleshooting-installation","postgres.html#using-postgres","postgres.html#install-postgres-client-libraries","postgres.html#set-up-database","postgres.html#synapse-config","postgres.html#postgresql-major-version-upgrades","postgres.html#backups","postgres.html#tuning-postgres","postgres.html#porting-from-sqlite","postgres.html#overview","postgres.html#using-the-port-script","postgres.html#troubleshooting","postgres.html#alternative-auth-methods","postgres.html#fixing-incorrect-collate-or-ctype","reverse_proxy.html#using-a-reverse-proxy-with-synapse","reverse_proxy.html#homeserver-configuration","reverse_proxy.html#reverse-proxy-configuration-examples","reverse_proxy.html#nginx","reverse_proxy.html#caddy-v2","reverse_proxy.html#apache","reverse_proxy.html#haproxy","reverse_proxy.html#relayd","reverse_proxy.html#health-check-endpoint","reverse_proxy.html#synapse-administration-endpoints","setup/forward_proxy.html#using-a-forward-proxy-with-synapse","setup/forward_proxy.html#configure","setup/forward_proxy.html#connection-types","setup/forward_proxy.html#troubleshooting","turn-howto.html#overview","turn-howto.html#requirements","turn-howto.html#synapse-setup","turn-howto.html#troubleshooting","setup/turn/coturn.html#coturn-turn-server","setup/turn/coturn.html#coturn-setup","setup/turn/coturn.html#initial-installation","setup/turn/coturn.html#configuration","setup/turn/eturnal.html#eturnal-turn-server","setup/turn/eturnal.html#eturnal-setup","setup/turn/eturnal.html#initial-installation","setup/turn/eturnal.html#configuration","setup/turn/eturnal.html#eturnalctl-opterations-script","delegate.html#delegation-of-incoming-federation-traffic","delegate.html#well-known-delegation","delegate.html#external-server","delegate.html#serving-a-well-knownmatrixserver-file-with-synapse","delegate.html#srv-dns-record-delegation","delegate.html#delegation-faq","delegate.html#when-do-i-need-delegation","delegate.html#should-i-use-a-reverse-proxy-for-federation-traffic","upgrade.html#upgrading-synapse","upgrade.html#rolling-back-to-older-versions","upgrade.html#upgrading-from-a-very-old-version","upgrade.html#upgrading-to-v11300","upgrade.html#documented-endpoint-which-can-be-delegated-to-a-federation-worker","upgrade.html#upgrading-to-v11260","upgrade.html#room-list-publication-rules-change","upgrade.html#change-of-signing-key-expiry-date-for-the-debianubuntu-package-repository","upgrade.html#upgrading-to-v11220","upgrade.html#dropping-support-for-postgresql-11-and-12","upgrade.html#upgrading-to-v11200","upgrade.html#removal-of-experimental-msc3886-feature","upgrade.html#authenticated-media-is-now-enforced-by-default","upgrade.html#upgrading-to-v11190","upgrade.html#minimum-supported-python-version","upgrade.html#upgrading-to-v11110","upgrade.html#new-worker-endpoints-for-authenticated-client-and-federation-media","upgrade.html#upgrading-to-v11060","upgrade.html#minimum-supported-rust-version","upgrade.html#upgrading-to-v11000","upgrade.html#minimum-supported-rust-version-1","upgrade.html#upgrading-to-v1930","upgrade.html#minimum-supported-rust-version-2","upgrade.html#upgrading-to-v1900","upgrade.html#app-service-query-parameter-authorization-is-now-a-configuration-option","upgrade.html#upgrading-to-v1890","upgrade.html#removal-of-unspecced-user-property-for-register","upgrade.html#upgrading-to-v1880","upgrade.html#minimum-supported-python-version-1","upgrade.html#removal-of-worker_replication_-settings","upgrade.html#upgrading-to-v1860","upgrade.html#minimum-supported-rust-version-3","upgrade.html#upgrading-to-v1850","upgrade.html#application-service-registration-with-user-property-deprecation","upgrade.html#upgrading-to-v1840","upgrade.html#deprecation-of-worker_replication_-configuration-settings","upgrade.html#example-change","upgrade.html#upgrading-to-v1810","upgrade.html#application-service-path--authentication-deprecations","upgrade.html#upgrading-to-v1800","upgrade.html#reporting-events-error-code-change","upgrade.html#upgrading-to-v1790","upgrade.html#the-on_threepid_bind-module-callback-method-has-been-deprecated","upgrade.html#upgrading-to-v1780","upgrade.html#deprecate-the-_synapseadminv1mediadelete-admin-api","upgrade.html#upgrading-to-v1760","upgrade.html#faster-joins-are-enabled-by-default","upgrade.html#changes-to-the-account-data-replication-streams","upgrade.html#minimum-version-of-poetry-is-now-132","upgrade.html#upgrading-to-v1740","upgrade.html#unicode-support-in-user-search","upgrade.html#user-directory-rebuild","upgrade.html#upgrading-to-v1730","upgrade.html#legacy-prometheus-metric-names-have-now-been-removed","upgrade.html#upgrading-to-v1720","upgrade.html#dropping-support-for-postgresql-10","upgrade.html#upgrading-to-v1710","upgrade.html#removal-of-the-generate_short_term_login_token-module-api-method","upgrade.html#changes-to-the-events-received-by-application-services-interest","upgrade.html#legacy-prometheus-metric-names-are-now-disabled-by-default","upgrade.html#upgrading-to-v1690","upgrade.html#changes-to-the-receipts-replication-streams","upgrade.html#deprecation-of-legacy-prometheus-metric-names","upgrade.html#deprecation-of-the-generate_short_term_login_token-module-api-method","upgrade.html#upgrading-to-v1680","upgrade.html#sqlite-version-requirement","upgrade.html#rust-requirement-when-building-from-source","upgrade.html#upgrading-to-v1670","upgrade.html#direct-tcp-replication-is-no-longer-supported-migrate-to-redis","upgrade.html#minimum-version-of-poetry-is-now-v120","upgrade.html#rust-requirement-in-the-next-release","upgrade.html#sqlite-version-requirement-in-the-next-release","upgrade.html#upgrading-to-v1660","upgrade.html#delegation-of-email-validation-no-longer-supported","upgrade.html#upgrading-to-v1640","upgrade.html#deprecation-of-the-ability-to-delegate-e-mail-verification-to-identity-servers","upgrade.html#changes-to-the-event-replication-streams","upgrade.html#frozendict-release","upgrade.html#upgrading-to-v1620","upgrade.html#new-signatures-for-spam-checker-callbacks","upgrade.html#upgrading-to-v1610","upgrade.html#removal-of-deprecated-communitygroups","upgrade.html#worker-endpoints","upgrade.html#upgrading-to-v1600","upgrade.html#adding-a-new-unique-index-to-state_group_edges-could-fail-if-your-database-is-corrupted","upgrade.html#on-postgres","upgrade.html#on-sqlite","upgrade.html#for-more-details","upgrade.html#new-signature-for-the-spam-checker-callback-check_event_for_spam","upgrade.html#upgrading-to-v1590","upgrade.html#device-name-lookup-over-federation-has-been-disabled-by-default","upgrade.html#deprecation-of-the-synapseappappservice-and-synapseappuser_dir-worker-application-types","upgrade.html#upgrading-to-v1580","upgrade.html#groupscommunities-feature-has-been-disabled-by-default","upgrade.html#upgrading-to-v1570","upgrade.html#changes-to-database-schema-for-application-services","upgrade.html#upgrading-to-v1560","upgrade.html#open-registration-without-verification-is-now-disabled-by-default","upgrade.html#groupscommunities-feature-has-been-deprecated","upgrade.html#change-in-behaviour-for-postgresql-databases-with-unsafe-locale","upgrade.html#upgrading-to-v1550","upgrade.html#synctl-script-has-been-moved","upgrade.html#compatibility-dropped-for-mjolnir-131-and-earlier","upgrade.html#upgrading-to-v1540","upgrade.html#legacy-structured-logging-configuration-removal","upgrade.html#upgrading-to-v1530","upgrade.html#dropping-support-for-webclient-listeners-and-non-https-web_client_location","upgrade.html#stablisation-of-msc3231","upgrade.html#time-based-cache-expiry-is-now-enabled-by-default","upgrade.html#deprecation-of-capability-orgmatrixmsc3283","upgrade.html#removal-of-user_may_create_room_with_invites","upgrade.html#upgrading-to-v1520","upgrade.html#twisted-security-release","upgrade.html#upgrading-to-v1510","upgrade.html#deprecation-of-webclient-listeners-and-non-https-web_client_location","upgrade.html#upgrading-to-v1500","upgrade.html#dropping-support-for-old-python-and-postgres-versions","upgrade.html#upgrading-to-v1470","upgrade.html#removal-of-old-room-admin-api","upgrade.html#deprecation-of-the-user_may_create_room_with_invites-module-callback","upgrade.html#upgrading-to-v1450","upgrade.html#changes-required-to-media-storage-provider-modules-when-reading-from-the-synapse-configuration-object","upgrade.html#upgrading-to-v1440","upgrade.html#the-url-preview-cache-is-no-longer-mirrored-to-storage-providers","upgrade.html#upgrading-to-v1430","upgrade.html#the-spaces-summary-apis-can-now-be-handled-by-workers","upgrade.html#upgrading-to-v1420","upgrade.html#removal-of-old-room-admin-api-1","upgrade.html#user-interactive-authentication-fallback-templates-can-now-display-errors","upgrade.html#removal-of-out-of-date-email-pushers","upgrade.html#upgrading-to-v1410","upgrade.html#add-support-for-routing-outbound-http-requests-via-a-proxy-for-federation","upgrade.html#deprecation-of-template_dir","upgrade.html#_synapseadminv1usersuseridmedia-must-be-handled-by-media-workers","upgrade.html#upgrading-to-v1390","upgrade.html#deprecation-of-the-current-third-party-rules-module-interface","upgrade.html#upgrading-to-v1380","upgrade.html#re-indexing-of-events-table-on-postgres-databases","upgrade.html#upgrading-to-v1370","upgrade.html#deprecation-of-the-current-spam-checker-interface","upgrade.html#upgrading-to-v1340","upgrade.html#room_invite_state_types-configuration-setting","upgrade.html#upgrading-to-v1330","upgrade.html#account-validity-html-templates-can-now-display-a-users-expiration-date","upgrade.html#upgrading-to-v1320","upgrade.html#regression-causing-connected-prometheus-instances-to-become-overwhelmed","upgrade.html#dropping-support-for-old-python-postgres-and-sqlite-versions","upgrade.html#removal-of-old-list-accounts-admin-api","upgrade.html#application-services-must-use-type-mloginapplication_service-when-registering-users","upgrade.html#upgrading-to-v1290","upgrade.html#requirement-for-x-forwarded-proto-header","upgrade.html#upgrading-to-v1270","upgrade.html#changes-to-callback-uri-for-oauth2--openid-connect-and-saml2","upgrade.html#changes-to-html-templates","upgrade.html#upgrading-to-v1260","upgrade.html#rolling-back-to-v1250-after-a-failed-upgrade","upgrade.html#upgrading-to-v1250","upgrade.html#last-release-supporting-python-35","upgrade.html#blacklisting-ip-ranges","upgrade.html#upgrading-to-v1240","upgrade.html#custom-openid-connect-mapping-provider-breaking-change","upgrade.html#removal-historical-synapse-admin-api","upgrade.html#upgrading-to-v1230","upgrade.html#structured-logging-configuration-breaking-changes","upgrade.html#upgrading-to-v1220","upgrade.html#thirdpartyeventrules-breaking-changes","upgrade.html#upgrading-to-v1210","upgrade.html#forwarding-_synapseclient-through-your-reverse-proxy","upgrade.html#new-html-templates","upgrade.html#updated-single-sign-on-html-templates","upgrade.html#upgrading-to-v1180","upgrade.html#docker--py3-suffix-will-be-removed-in-future-versions","upgrade.html#redis-replication-is-now-recommended-in-lieu-of-tcp-replication","upgrade.html#upgrading-to-v1140","upgrade.html#upgrading-to-v1130","upgrade.html#incorrect-database-migration-in-old-synapse-versions","upgrade.html#new-single-sign-on-html-templates","upgrade.html#synapse-sso-plugins-method-deprecation","upgrade.html#rolling-back-to-v1124-after-a-failed-upgrade","upgrade.html#upgrading-to-v1120","upgrade.html#upgrading-to-v1100","upgrade.html#upgrading-to-v180","upgrade.html#upgrading-to-v170","upgrade.html#upgrading-to-v150","upgrade.html#upgrading-to-v140","upgrade.html#new-custom-templates","upgrade.html#3pid-verification-changes","upgrade.html#email","upgrade.html#phone-numbers","upgrade.html#rolling-back-to-v131","upgrade.html#upgrading-to-v120","upgrade.html#upgrading-to-v110","upgrade.html#minimum-python-version","upgrade.html#minimum-postgresql-version","upgrade.html#upgrading-to-v10","upgrade.html#validation-of-tls-certificates","upgrade.html#email-1","upgrade.html#new-email-templates","upgrade.html#upgrading-to-v0990","upgrade.html#upgrading-to-v0340","upgrade.html#upgrading-to-v0337","upgrade.html#upgrading-to-v0273","upgrade.html#upgrading-to-v0150","upgrade.html#upgrading-to-v0110","upgrade.html#upgrading-to-v090","upgrade.html#upgrading-to-v080","upgrade.html#upgrading-to-v070","upgrade.html#upgrading-to-v060","upgrade.html#upgrading-to-v051","upgrade.html#upgrading-to-v050","upgrade.html#upgrading-to-v040","upgrade.html#upgrading-to-v030","upgrade.html#web-client","upgrade.html#upgrading-to-v020","upgrade.html#upgrading-to-v001","federate.html#setting-up-federation","federate.html#troubleshooting","federate.html#known-issues","federate.html#running-a-demo-federation-of-synapses","usage/configuration/index.html#configuration","usage/configuration/config_documentation.html#configuring-synapse","usage/configuration/config_documentation.html#config-conventions","usage/configuration/config_documentation.html#config-validation","usage/configuration/config_documentation.html#yaml","usage/configuration/config_documentation.html#modules","usage/configuration/config_documentation.html#modules-1","usage/configuration/config_documentation.html#server","usage/configuration/config_documentation.html#server_name","usage/configuration/config_documentation.html#pid_file","usage/configuration/config_documentation.html#daemonize","usage/configuration/config_documentation.html#print_pidfile","usage/configuration/config_documentation.html#user_agent_suffix","usage/configuration/config_documentation.html#use_frozen_dicts","usage/configuration/config_documentation.html#web_client_location","usage/configuration/config_documentation.html#public_baseurl","usage/configuration/config_documentation.html#serve_server_wellknown","usage/configuration/config_documentation.html#extra_well_known_client_content","usage/configuration/config_documentation.html#soft_file_limit","usage/configuration/config_documentation.html#presence","usage/configuration/config_documentation.html#require_auth_for_profile_requests","usage/configuration/config_documentation.html#limit_profile_requests_to_users_who_share_rooms","usage/configuration/config_documentation.html#include_profile_data_on_invite","usage/configuration/config_documentation.html#allow_public_rooms_without_auth","usage/configuration/config_documentation.html#allow_public_rooms_over_federation","usage/configuration/config_documentation.html#default_room_version","usage/configuration/config_documentation.html#gc_thresholds","usage/configuration/config_documentation.html#gc_min_interval","usage/configuration/config_documentation.html#filter_timeline_limit","usage/configuration/config_documentation.html#block_non_admin_invites","usage/configuration/config_documentation.html#enable_search","usage/configuration/config_documentation.html#ip_range_blacklist","usage/configuration/config_documentation.html#ip_range_whitelist","usage/configuration/config_documentation.html#listeners","usage/configuration/config_documentation.html#manhole","usage/configuration/config_documentation.html#manhole_settings","usage/configuration/config_documentation.html#dummy_events_threshold","usage/configuration/config_documentation.html#delete_stale_devices_after","usage/configuration/config_documentation.html#email","usage/configuration/config_documentation.html#max_event_delay_duration","usage/configuration/config_documentation.html#homeserver-blocking","usage/configuration/config_documentation.html#admin_contact","usage/configuration/config_documentation.html#hs_disabled-and-hs_disabled_message","usage/configuration/config_documentation.html#limit_usage_by_mau","usage/configuration/config_documentation.html#max_mau_value","usage/configuration/config_documentation.html#mau_trial_days","usage/configuration/config_documentation.html#mau_appservice_trial_days","usage/configuration/config_documentation.html#mau_limit_alerting","usage/configuration/config_documentation.html#mau_stats_only","usage/configuration/config_documentation.html#mau_limit_reserved_threepids","usage/configuration/config_documentation.html#server_context","usage/configuration/config_documentation.html#limit_remote_rooms","usage/configuration/config_documentation.html#require_membership_for_aliases","usage/configuration/config_documentation.html#allow_per_room_profiles","usage/configuration/config_documentation.html#max_avatar_size","usage/configuration/config_documentation.html#allowed_avatar_mimetypes","usage/configuration/config_documentation.html#redaction_retention_period","usage/configuration/config_documentation.html#forgotten_room_retention_period","usage/configuration/config_documentation.html#user_ips_max_age","usage/configuration/config_documentation.html#request_token_inhibit_3pid_errors","usage/configuration/config_documentation.html#next_link_domain_whitelist","usage/configuration/config_documentation.html#templates-and-custom_template_directory","usage/configuration/config_documentation.html#retention","usage/configuration/config_documentation.html#tls","usage/configuration/config_documentation.html#tls_certificate_path","usage/configuration/config_documentation.html#tls_private_key_path","usage/configuration/config_documentation.html#federation_verify_certificates","usage/configuration/config_documentation.html#federation_client_minimum_tls_version","usage/configuration/config_documentation.html#federation_certificate_verification_whitelist","usage/configuration/config_documentation.html#federation_custom_ca_list","usage/configuration/config_documentation.html#federation","usage/configuration/config_documentation.html#federation_domain_whitelist","usage/configuration/config_documentation.html#federation_whitelist_endpoint_enabled","usage/configuration/config_documentation.html#federation_metrics_domains","usage/configuration/config_documentation.html#allow_profile_lookup_over_federation","usage/configuration/config_documentation.html#allow_device_name_lookup_over_federation","usage/configuration/config_documentation.html#federation-1","usage/configuration/config_documentation.html#caching","usage/configuration/config_documentation.html#event_cache_size","usage/configuration/config_documentation.html#caches-and-associated-values","usage/configuration/config_documentation.html#reloading-cache-factors","usage/configuration/config_documentation.html#database","usage/configuration/config_documentation.html#database-1","usage/configuration/config_documentation.html#databases","usage/configuration/config_documentation.html#logging","usage/configuration/config_documentation.html#log_config","usage/configuration/config_documentation.html#ratelimiting","usage/configuration/config_documentation.html#rc_message","usage/configuration/config_documentation.html#rc_registration","usage/configuration/config_documentation.html#rc_registration_token_validity","usage/configuration/config_documentation.html#rc_login","usage/configuration/config_documentation.html#rc_admin_redaction","usage/configuration/config_documentation.html#rc_joins","usage/configuration/config_documentation.html#rc_joins_per_room","usage/configuration/config_documentation.html#rc_3pid_validation","usage/configuration/config_documentation.html#rc_invites","usage/configuration/config_documentation.html#rc_third_party_invite","usage/configuration/config_documentation.html#rc_media_create","usage/configuration/config_documentation.html#rc_federation","usage/configuration/config_documentation.html#rc_presence","usage/configuration/config_documentation.html#rc_delayed_event_mgmt","usage/configuration/config_documentation.html#federation_rr_transactions_per_room_per_second","usage/configuration/config_documentation.html#media-store","usage/configuration/config_documentation.html#enable_authenticated_media","usage/configuration/config_documentation.html#enable_media_repo","usage/configuration/config_documentation.html#media_store_path","usage/configuration/config_documentation.html#max_pending_media_uploads","usage/configuration/config_documentation.html#unused_expiration_time","usage/configuration/config_documentation.html#media_storage_providers","usage/configuration/config_documentation.html#max_upload_size","usage/configuration/config_documentation.html#max_image_pixels","usage/configuration/config_documentation.html#remote_media_download_burst_count","usage/configuration/config_documentation.html#remote_media_download_per_second","usage/configuration/config_documentation.html#prevent_media_downloads_from","usage/configuration/config_documentation.html#dynamic_thumbnails","usage/configuration/config_documentation.html#thumbnail_sizes","usage/configuration/config_documentation.html#media_retention","usage/configuration/config_documentation.html#url_preview_enabled","usage/configuration/config_documentation.html#url_preview_ip_range_blacklist","usage/configuration/config_documentation.html#url_preview_ip_range_whitelist","usage/configuration/config_documentation.html#url_preview_url_blacklist","usage/configuration/config_documentation.html#max_spider_size","usage/configuration/config_documentation.html#url_preview_accept_language","usage/configuration/config_documentation.html#oembed","usage/configuration/config_documentation.html#captcha","usage/configuration/config_documentation.html#recaptcha_public_key","usage/configuration/config_documentation.html#recaptcha_private_key","usage/configuration/config_documentation.html#enable_registration_captcha","usage/configuration/config_documentation.html#recaptcha_siteverify_api","usage/configuration/config_documentation.html#turn","usage/configuration/config_documentation.html#turn_uris","usage/configuration/config_documentation.html#turn_shared_secret","usage/configuration/config_documentation.html#turn_shared_secret_path","usage/configuration/config_documentation.html#turn_username-and-turn_password","usage/configuration/config_documentation.html#turn_user_lifetime","usage/configuration/config_documentation.html#turn_allow_guests","usage/configuration/config_documentation.html#registration","usage/configuration/config_documentation.html#enable_registration","usage/configuration/config_documentation.html#enable_registration_without_verification","usage/configuration/config_documentation.html#registrations_require_3pid","usage/configuration/config_documentation.html#disable_msisdn_registration","usage/configuration/config_documentation.html#allowed_local_3pids","usage/configuration/config_documentation.html#enable_3pid_lookup","usage/configuration/config_documentation.html#registration_requires_token","usage/configuration/config_documentation.html#registration_shared_secret","usage/configuration/config_documentation.html#registration_shared_secret_path","usage/configuration/config_documentation.html#bcrypt_rounds","usage/configuration/config_documentation.html#allow_guest_access","usage/configuration/config_documentation.html#default_identity_server","usage/configuration/config_documentation.html#account_threepid_delegates","usage/configuration/config_documentation.html#enable_set_displayname","usage/configuration/config_documentation.html#enable_set_avatar_url","usage/configuration/config_documentation.html#enable_3pid_changes","usage/configuration/config_documentation.html#auto_join_rooms","usage/configuration/config_documentation.html#autocreate_auto_join_rooms","usage/configuration/config_documentation.html#autocreate_auto_join_rooms_federated","usage/configuration/config_documentation.html#autocreate_auto_join_room_preset","usage/configuration/config_documentation.html#auto_join_mxid_localpart","usage/configuration/config_documentation.html#auto_join_rooms_for_guests","usage/configuration/config_documentation.html#inhibit_user_in_use_error","usage/configuration/config_documentation.html#allow_underscore_prefixed_registration","usage/configuration/config_documentation.html#user-session-management","usage/configuration/config_documentation.html#session_lifetime","usage/configuration/config_documentation.html#refreshable_access_token_lifetime","usage/configuration/config_documentation.html#refresh_token_lifetime","usage/configuration/config_documentation.html#nonrefreshable_access_token_lifetime","usage/configuration/config_documentation.html#ui_auth","usage/configuration/config_documentation.html#login_via_existing_session","usage/configuration/config_documentation.html#metrics","usage/configuration/config_documentation.html#enable_metrics","usage/configuration/config_documentation.html#sentry","usage/configuration/config_documentation.html#metrics_flags","usage/configuration/config_documentation.html#report_stats","usage/configuration/config_documentation.html#report_stats_endpoint","usage/configuration/config_documentation.html#api-configuration","usage/configuration/config_documentation.html#room_prejoin_state","usage/configuration/config_documentation.html#track_puppeted_user_ips","usage/configuration/config_documentation.html#app_service_config_files","usage/configuration/config_documentation.html#track_appservice_user_ips","usage/configuration/config_documentation.html#use_appservice_legacy_authorization","usage/configuration/config_documentation.html#macaroon_secret_key","usage/configuration/config_documentation.html#macaroon_secret_key_path","usage/configuration/config_documentation.html#form_secret","usage/configuration/config_documentation.html#form_secret_path","usage/configuration/config_documentation.html#signing-keys","usage/configuration/config_documentation.html#signing_key_path","usage/configuration/config_documentation.html#old_signing_keys","usage/configuration/config_documentation.html#key_refresh_interval","usage/configuration/config_documentation.html#trusted_key_servers","usage/configuration/config_documentation.html#suppress_key_server_warning","usage/configuration/config_documentation.html#key_server_signing_keys_path","usage/configuration/config_documentation.html#single-sign-on-integration","usage/configuration/config_documentation.html#saml2_config","usage/configuration/config_documentation.html#oidc_providers","usage/configuration/config_documentation.html#cas_config","usage/configuration/config_documentation.html#sso","usage/configuration/config_documentation.html#jwt_config","usage/configuration/config_documentation.html#password_config","usage/configuration/config_documentation.html#push","usage/configuration/config_documentation.html#push-1","usage/configuration/config_documentation.html#rooms","usage/configuration/config_documentation.html#encryption_enabled_by_default_for_room_type","usage/configuration/config_documentation.html#user_directory","usage/configuration/config_documentation.html#user_consent","usage/configuration/config_documentation.html#stats","usage/configuration/config_documentation.html#server_notices","usage/configuration/config_documentation.html#enable_room_list_search","usage/configuration/config_documentation.html#alias_creation_rules","usage/configuration/config_documentation.html#room_list_publication_rules","usage/configuration/config_documentation.html#default_power_level_content_override","usage/configuration/config_documentation.html#forget_rooms_on_leave","usage/configuration/config_documentation.html#exclude_rooms_from_sync","usage/configuration/config_documentation.html#opentracing","usage/configuration/config_documentation.html#opentracing-1","usage/configuration/config_documentation.html#coordinating-workers","usage/configuration/config_documentation.html#worker_replication_secret","usage/configuration/config_documentation.html#worker_replication_secret_path","usage/configuration/config_documentation.html#start_pushers","usage/configuration/config_documentation.html#pusher_instances","usage/configuration/config_documentation.html#send_federation","usage/configuration/config_documentation.html#federation_sender_instances","usage/configuration/config_documentation.html#instance_map","usage/configuration/config_documentation.html#stream_writers","usage/configuration/config_documentation.html#outbound_federation_restricted_to","usage/configuration/config_documentation.html#run_background_tasks_on","usage/configuration/config_documentation.html#update_user_directory_from_worker","usage/configuration/config_documentation.html#notify_appservices_from_worker","usage/configuration/config_documentation.html#media_instance_running_background_jobs","usage/configuration/config_documentation.html#redis","usage/configuration/config_documentation.html#individual-worker-configuration","usage/configuration/config_documentation.html#worker_app","usage/configuration/config_documentation.html#worker_name","usage/configuration/config_documentation.html#worker_listeners","usage/configuration/config_documentation.html#worker_manhole","usage/configuration/config_documentation.html#worker_daemonize","usage/configuration/config_documentation.html#worker_pid_file","usage/configuration/config_documentation.html#worker_log_config","usage/configuration/config_documentation.html#background-updates","usage/configuration/config_documentation.html#background_updates","usage/configuration/config_documentation.html#auto-accept-invites","usage/configuration/config_documentation.html#auto_accept_invites","usage/configuration/homeserver_sample_config.html#homeserver-sample-configuration-file","usage/configuration/logging_sample_config.html#logging-sample-configuration-file","structured_logging.html#structured-logging","templates.html#templates","templates.html#email-templates","templates.html#html-page-templates-for-registration-and-password-reset","templates.html#html-page-templates-for-single-sign-on-sso","usage/configuration/user_authentication/index.html#user-authentication","usage/configuration/user_authentication/single_sign_on/index.html#single-sign-on","openid.html#configuring-synapse-to-authenticate-against-an-openid-connect-provider","openid.html#preparing-synapse","openid.html#oidc-back-channel-logout","openid.html#sample-configs","openid.html#microsoft-azure-active-directory","openid.html#apple","openid.html#auth0","openid.html#authentik","openid.html#dex","openid.html#django-oauth-toolkit","openid.html#facebook","openid.html#forgejo","openid.html#github","openid.html#gitlab","openid.html#gitea","openid.html#google","openid.html#keycloak","openid.html#lemonldap","openid.html#mastodon","openid.html#pocket-id","openid.html#shibboleth-with-oidc-plugin","openid.html#twitch","openid.html#twitter","openid.html#xwiki","usage/configuration/user_authentication/single_sign_on/saml.html#saml","usage/configuration/user_authentication/single_sign_on/cas.html#cas","sso_mapping_providers.html#sso-mapping-providers","sso_mapping_providers.html#openid-mapping-providers","sso_mapping_providers.html#building-a-custom-openid-mapping-provider","sso_mapping_providers.html#default-openid-mapping-provider","sso_mapping_providers.html#saml-mapping-providers","sso_mapping_providers.html#building-a-custom-saml-mapping-provider","sso_mapping_providers.html#default-saml-mapping-provider","password_auth_providers.html#password-auth-provider-modules","password_auth_providers.html#required-methods","password_auth_providers.html#optional-methods","jwt.html#jwt-login-type","jwt.html#preparing-synapse","jwt.html#how-to-test-jwt-as-a-developer","usage/configuration/user_authentication/refresh_tokens.html#refresh-tokens","usage/configuration/user_authentication/refresh_tokens.html#background-and-motivation","usage/configuration/user_authentication/refresh_tokens.html#caveats","usage/configuration/user_authentication/refresh_tokens.html#configuration-guide","usage/configuration/user_authentication/refresh_tokens.html#using-refresh-token-expiry-to-log-out-inactive-sessions","CAPTCHA_SETUP.html#overview","CAPTCHA_SETUP.html#getting-api-keys","CAPTCHA_SETUP.html#configuring-ip-used-for-auth","application_services.html#registering-an-application-service","server_notices.html#server-notices","server_notices.html#user-experience","server_notices.html#synapse-configuration","server_notices.html#sending-notices","consent_tracking.html#support-in-synapse-for-tracking-agreement-to-server-terms-and-conditions","consent_tracking.html#collecting-policy-agreement-from-a-user","consent_tracking.html#enabling-consent-tracking-at-registration","consent_tracking.html#constructing-the-consent-uri","consent_tracking.html#sending-users-a-server-notice-asking-them-to-agree-to-the-policy","consent_tracking.html#blocking-users-from-using-the-server-until-they-agree-to-the-policy","user_directory.html#user-directory-api-implementation","user_directory.html#data-model","user_directory.html#configuration-options","user_directory.html#search-algorithm","user_directory.html#postgresql","user_directory.html#sqlite","message_retention_policies.html#message-retention-policies","message_retention_policies.html#server-configuration","message_retention_policies.html#default-policy","message_retention_policies.html#purge-jobs","message_retention_policies.html#lifetime-limits","message_retention_policies.html#room-configuration","message_retention_policies.html#note-on-reclaiming-disk-space","modules/index.html#modules","modules/index.html#using-modules","modules/index.html#using-multiple-modules","modules/index.html#current-status","modules/writing_a_module.html#writing-a-module","modules/writing_a_module.html#when-synapse-runs-with-several-modules-configured","modules/writing_a_module.html#handling-the-modules-configuration","modules/writing_a_module.html#registering-a-web-resource","modules/writing_a_module.html#registering-a-callback","modules/writing_a_module.html#caching","modules/spam_checker_callbacks.html#spam-checker-callbacks","modules/spam_checker_callbacks.html#callbacks","modules/spam_checker_callbacks.html#check_event_for_spam","modules/spam_checker_callbacks.html#user_may_join_room","modules/spam_checker_callbacks.html#user_may_invite","modules/spam_checker_callbacks.html#user_may_send_3pid_invite","modules/spam_checker_callbacks.html#user_may_create_room","modules/spam_checker_callbacks.html#user_may_create_room_alias","modules/spam_checker_callbacks.html#user_may_publish_room","modules/spam_checker_callbacks.html#check_username_for_spam","modules/spam_checker_callbacks.html#check_registration_for_spam","modules/spam_checker_callbacks.html#check_media_file_for_spam","modules/spam_checker_callbacks.html#should_drop_federated_event","modules/spam_checker_callbacks.html#check_login_for_spam","modules/spam_checker_callbacks.html#example","modules/third_party_rules_callbacks.html#third-party-rules-callbacks","modules/third_party_rules_callbacks.html#callbacks","modules/third_party_rules_callbacks.html#check_event_allowed","modules/third_party_rules_callbacks.html#on_create_room","modules/third_party_rules_callbacks.html#check_threepid_can_be_invited","modules/third_party_rules_callbacks.html#check_visibility_can_be_modified","modules/third_party_rules_callbacks.html#on_new_event","modules/third_party_rules_callbacks.html#check_can_shutdown_room","modules/third_party_rules_callbacks.html#check_can_deactivate_user","modules/third_party_rules_callbacks.html#on_profile_update","modules/third_party_rules_callbacks.html#on_user_deactivation_status_changed","modules/third_party_rules_callbacks.html#on_threepid_bind","modules/third_party_rules_callbacks.html#on_add_user_third_party_identifier","modules/third_party_rules_callbacks.html#on_remove_user_third_party_identifier","modules/third_party_rules_callbacks.html#example","modules/presence_router_callbacks.html#presence-router-callbacks","modules/presence_router_callbacks.html#callbacks","modules/presence_router_callbacks.html#get_users_for_states","modules/presence_router_callbacks.html#get_interested_users","modules/presence_router_callbacks.html#example","modules/account_validity_callbacks.html#account-validity-callbacks","modules/account_validity_callbacks.html#is_user_expired","modules/account_validity_callbacks.html#on_user_registration","modules/account_validity_callbacks.html#on_user_login","modules/password_auth_provider_callbacks.html#password-auth-provider-callbacks","modules/password_auth_provider_callbacks.html#callbacks","modules/password_auth_provider_callbacks.html#auth_checkers","modules/password_auth_provider_callbacks.html#check_3pid_auth","modules/password_auth_provider_callbacks.html#on_logged_out","modules/password_auth_provider_callbacks.html#get_username_for_registration","modules/password_auth_provider_callbacks.html#get_displayname_for_registration","modules/password_auth_provider_callbacks.html#is_3pid_allowed","modules/password_auth_provider_callbacks.html#example","modules/background_update_controller_callbacks.html#background-update-controller-callbacks","modules/background_update_controller_callbacks.html#on_update","modules/background_update_controller_callbacks.html#default_batch_size","modules/background_update_controller_callbacks.html#min_batch_size","modules/account_data_callbacks.html#account-data-callbacks","modules/account_data_callbacks.html#callbacks","modules/account_data_callbacks.html#on_account_data_updated","modules/account_data_callbacks.html#example","modules/add_extra_fields_to_client_events_unsigned.html#add-extra-fields-to-client-events-unsigned-section-callbacks","modules/add_extra_fields_to_client_events_unsigned.html#api","modules/porting_legacy_module.html#porting-an-existing-module-that-uses-the-old-interface","workers.html#scaling-synapse-via-workers","workers.html#main-processworker-communication","workers.html#setting-up-workers","workers.html#shared-configuration","workers.html#worker-configuration","workers.html#running-synapse-with-workers","workers.html#start-synapse-with-poetry","workers.html#available-worker-applications","workers.html#synapseappgeneric_worker","workers.html#synapseapppusher","workers.html#synapseappappservice","workers.html#synapseappfederation_sender","workers.html#synapseappmedia_repository","workers.html#synapseappuser_dir","workers.html#historical-apps","workers.html#migration-from-old-config","workers.html#architectural-diagram","synctl_workers.html#using-synctl-with-workers","systemd-with-workers/index.html#setting-up-synapse-with-workers-and-systemd","systemd-with-workers/index.html#synapse-configuration-files","systemd-with-workers/index.html#set-up","systemd-with-workers/index.html#usage","systemd-with-workers/index.html#hardening","usage/administration/index.html#administration","usage/administration/backups.html#how-to-back-up-a-synapse-homeserver","usage/administration/backups.html#configuration-files","usage/administration/backups.html#server-signing-key","usage/administration/backups.html#database","usage/administration/backups.html#synapse-specfic-details","usage/administration/backups.html#quick-and-easy-database-backup-and-restore","usage/administration/backups.html#media-store","usage/administration/admin_api/index.html#the-admin-api","usage/administration/admin_api/index.html#authenticate-as-a-server-admin","usage/administration/admin_api/index.html#making-an-admin-api-request","admin_api/account_validity.html#account-validity-api","admin_api/account_validity.html#renew-account","usage/administration/admin_api/background_updates.html#background-updates-api","usage/administration/admin_api/background_updates.html#status","usage/administration/admin_api/background_updates.html#enabled","usage/administration/admin_api/background_updates.html#run","admin_api/event_reports.html#show-reported-events","admin_api/event_reports.html#show-details-of-a-specific-event-report","admin_api/event_reports.html#delete-a-specific-event-report","admin_api/experimental_features.html#experimental-features-api","admin_api/experimental_features.html#enablingdisabling-features","admin_api/experimental_features.html#listing-enabled-features","admin_api/media_admin_api.html#querying-media","admin_api/media_admin_api.html#list-all-media-in-a-room","admin_api/media_admin_api.html#list-all-media-uploaded-by-a-user","admin_api/media_admin_api.html#quarantine-media","admin_api/media_admin_api.html#quarantining-media-by-id","admin_api/media_admin_api.html#remove-media-from-quarantine-by-id","admin_api/media_admin_api.html#quarantining-media-in-a-room","admin_api/media_admin_api.html#quarantining-all-media-of-a-user","admin_api/media_admin_api.html#protecting-media-from-being-quarantined","admin_api/media_admin_api.html#unprotecting-media-from-being-quarantined","admin_api/media_admin_api.html#delete-local-media","admin_api/media_admin_api.html#delete-a-specific-local-media","admin_api/media_admin_api.html#delete-local-media-by-date-or-size","admin_api/media_admin_api.html#delete-media-uploaded-by-a-user","admin_api/media_admin_api.html#purge-remote-media-api","admin_api/purge_history_api.html#purge-history-api","admin_api/purge_history_api.html#purge-status-query","admin_api/purge_history_api.html#reclaim-disk-space-postgres","admin_api/register_api.html#shared-secret-registration","usage/administration/admin_api/registration_tokens.html#registration-tokens","usage/administration/admin_api/registration_tokens.html#registration-token-objects","usage/administration/admin_api/registration_tokens.html#list-all-tokens","usage/administration/admin_api/registration_tokens.html#get-one-token","usage/administration/admin_api/registration_tokens.html#create-token","usage/administration/admin_api/registration_tokens.html#update-token","usage/administration/admin_api/registration_tokens.html#delete-token","usage/administration/admin_api/registration_tokens.html#errors","admin_api/room_membership.html#edit-room-membership-api","admin_api/room_membership.html#parameters","admin_api/room_membership.html#usage","admin_api/rooms.html#list-room-api","admin_api/rooms.html#room-details-api","admin_api/rooms.html#room-members-api","admin_api/rooms.html#room-state-api","admin_api/rooms.html#room-messages-api","admin_api/rooms.html#room-timestamp-to-event-api","admin_api/rooms.html#block-room-api","admin_api/rooms.html#block-or-unblock-a-room","admin_api/rooms.html#get-block-status","admin_api/rooms.html#delete-room-api","admin_api/rooms.html#version-1-old-version","admin_api/rooms.html#version-2-new-version","admin_api/rooms.html#status-of-deleting-rooms","admin_api/rooms.html#query-by-room_id","admin_api/rooms.html#query-by-delete_id","admin_api/rooms.html#response","admin_api/rooms.html#undoing-room-deletions","admin_api/rooms.html#make-room-admin-api","admin_api/rooms.html#forward-extremities-admin-api","admin_api/rooms.html#check-for-forward-extremities","admin_api/rooms.html#deleting-forward-extremities","admin_api/rooms.html#event-context-api","admin_api/server_notices.html#server-notices","admin_api/statistics.html#users-media-usage-statistics","admin_api/statistics.html#get-largest-rooms-by-size-in-database","admin_api/user_admin_api.html#user-admin-api","admin_api/user_admin_api.html#query-user-account","admin_api/user_admin_api.html#create-or-modify-account","admin_api/user_admin_api.html#list-accounts","admin_api/user_admin_api.html#list-accounts-v2","admin_api/user_admin_api.html#list-accounts-v3","admin_api/user_admin_api.html#query-current-sessions-for-a-user","admin_api/user_admin_api.html#deactivate-account","admin_api/user_admin_api.html#suspendunsuspend-account","admin_api/user_admin_api.html#reset-password","admin_api/user_admin_api.html#get-whether-a-user-is-a-server-administrator-or-not","admin_api/user_admin_api.html#change-whether-a-user-is-a-server-administrator-or-not","admin_api/user_admin_api.html#list-joined-rooms-of-a-user","admin_api/user_admin_api.html#get-the-number-of-invites-sent-by-the-user","admin_api/user_admin_api.html#get-the-cumulative-number-of-rooms-a-user-has-joined-after-a-given-timestamp","admin_api/user_admin_api.html#account-data","admin_api/user_admin_api.html#user-media","admin_api/user_admin_api.html#list-media-uploaded-by-a-user","admin_api/user_admin_api.html#delete-media-uploaded-by-a-user","admin_api/user_admin_api.html#login-as-a-user","admin_api/user_admin_api.html#allow-replacing-master-cross-signing-key-without-user-interactive-auth","admin_api/user_admin_api.html#user-devices","admin_api/user_admin_api.html#list-all-devices","admin_api/user_admin_api.html#create-a-device","admin_api/user_admin_api.html#delete-multiple-devices","admin_api/user_admin_api.html#show-a-device","admin_api/user_admin_api.html#update-a-device","admin_api/user_admin_api.html#delete-a-device","admin_api/user_admin_api.html#list-all-pushers","admin_api/user_admin_api.html#controlling-whether-a-user-is-shadow-banned","admin_api/user_admin_api.html#override-ratelimiting-for-users","admin_api/user_admin_api.html#get-status-of-ratelimit","admin_api/user_admin_api.html#set-ratelimit","admin_api/user_admin_api.html#delete-ratelimit","admin_api/user_admin_api.html#check-username-availability","admin_api/user_admin_api.html#find-a-user-based-on-their-id-in-an-auth-provider","admin_api/user_admin_api.html#find-a-user-based-on-their-third-party-id-threepid-or-3pid","admin_api/user_admin_api.html#redact-all-the-events-of-a-user","admin_api/user_admin_api.html#check-the-status-of-a-redaction-process","admin_api/version_api.html#version-api","usage/administration/admin_api/federation.html#federation-api","usage/administration/admin_api/federation.html#list-of-destinations","usage/administration/admin_api/federation.html#destination-details-api","usage/administration/admin_api/federation.html#destination-rooms","usage/administration/admin_api/federation.html#reset-connection-timeout","manhole.html#using-the-synapse-manhole","manhole.html#configuring-the-manhole","manhole.html#security-settings","manhole.html#accessing-synapse-manhole","metrics-howto.html#how-to-monitor-synapse-metrics-using-prometheus","metrics-howto.html#monitoring-workers","metrics-howto.html#renaming-of-metrics--deprecation-of-old-names-in-12","metrics-howto.html#removal-of-deprecated-metrics--time-based-counters-becoming-histograms-in-0310","metrics-howto.html#block-and-response-metrics-renamed-for-0270","metrics-howto.html#standard-metric-names","usage/administration/monitoring/reporting_homeserver_usage_statistics.html#reporting-homeserver-usage-statistics","usage/administration/monitoring/reporting_homeserver_usage_statistics.html#available-statistics","usage/administration/monitoring/reporting_homeserver_usage_statistics.html#using-a-custom-statistics-collection-server","usage/administration/monthly_active_users.html#monthly-active-users","usage/administration/monthly_active_users.html#calculating-active-users","usage/administration/monthly_active_users.html#trial-days","usage/administration/monthly_active_users.html#limiting-usage-of-the-homeserver-when-the-maximum-mau-is-reached","usage/administration/monthly_active_users.html#metrics","usage/administration/understanding_synapse_through_grafana_graphs.html#understanding-synapse-through-grafana-graphs","usage/administration/understanding_synapse_through_grafana_graphs.html#message-event-send-time","usage/administration/understanding_synapse_through_grafana_graphs.html#transaction-count-and-transaction-duration","usage/administration/understanding_synapse_through_grafana_graphs.html#federation","usage/administration/understanding_synapse_through_grafana_graphs.html#caches","usage/administration/understanding_synapse_through_grafana_graphs.html#forward-extremities","usage/administration/understanding_synapse_through_grafana_graphs.html#garbage-collection","usage/administration/understanding_synapse_through_grafana_graphs.html#final-thoughts","usage/administration/useful_sql_for_admins.html#some-useful-sql-queries-for-synapse-admins","usage/administration/useful_sql_for_admins.html#size-of-full-matrix-db","usage/administration/useful_sql_for_admins.html#result-example","usage/administration/useful_sql_for_admins.html#show-top-20-larger-tables-by-row-count","usage/administration/useful_sql_for_admins.html#result-example-1","usage/administration/useful_sql_for_admins.html#show-top-20-larger-tables-by-storage-size","usage/administration/useful_sql_for_admins.html#result-example-2","usage/administration/useful_sql_for_admins.html#show-top-20-larger-rooms-by-state-events-count","usage/administration/useful_sql_for_admins.html#show-top-20-rooms-by-new-events-count-in-last-1-day","usage/administration/useful_sql_for_admins.html#show-top-20-users-on-homeserver-by-sent-events-messages-at-last-month","usage/administration/useful_sql_for_admins.html#show-last-100-messages-from-needed-user-with-room-names","usage/administration/useful_sql_for_admins.html#show-rooms-with-names-sorted-by-events-in-this-rooms","usage/administration/useful_sql_for_admins.html#result-example-3","usage/administration/useful_sql_for_admins.html#lookup-room-state-info-by-list-of-room_id","usage/administration/useful_sql_for_admins.html#show-users-and-devices-that-have-not-been-online-for-a-while","usage/administration/useful_sql_for_admins.html#clear-the-cache-of-a-remote-users-device-list","usage/administration/database_maintenance_tools.html#list-of-useful-tools-and-scripts-for-maintenance-synapse-database","usage/administration/database_maintenance_tools.html#purge-remote-media-api","usage/administration/database_maintenance_tools.html#purge-local-media-api","usage/administration/database_maintenance_tools.html#purge-history-api","usage/administration/database_maintenance_tools.html#synapse-compress-state","usage/administration/database_maintenance_tools.html#sql-for-analyzing-synapse-postgresql-database-stats","usage/administration/state_groups.html#how-do-state-groups-work","usage/administration/state_groups.html#known-bugs-with-state-groups","usage/administration/state_groups.html#compression-tool","usage/administration/request_log.html#request-log-format","usage/administration/admin_faq.html#admin-faq","usage/administration/admin_faq.html#how-do-i-become-a-server-admin","usage/administration/admin_faq.html#what-servers-are-my-server-talking-to","usage/administration/admin_faq.html#what-servers-are-currently-participating-in-this-room","usage/administration/admin_faq.html#what-users-are-registered-on-my-server","usage/administration/admin_faq.html#how-can-i-export-user-data","usage/administration/admin_faq.html#how-do-i-upgrade-from-a-very-old-version-of-synapse-to-the-latest","usage/administration/admin_faq.html#manually-resetting-passwords","usage/administration/admin_faq.html#i-have-a-problem-with-my-server-can-i-just-delete-my-database-and-start-again","usage/administration/admin_faq.html#ive-stuffed-up-access-to-my-room-how-can-i-delete-it-to-free-up-the-alias","usage/administration/admin_faq.html#how-can-i-find-the-lines-corresponding-to-a-given-http-request-in-my-homeserver-log","usage/administration/admin_faq.html#what-do-all-those-fields-in-the-processed-line-mean","usage/administration/admin_faq.html#what-are-the-biggest-rooms-on-my-server","usage/administration/admin_faq.html#people-cant-accept-room-invitations-from-me","usage/administration/admin_faq.html#help-synapse-is-slow-and-eats-all-my-ramcpu","usage/administration/admin_faq.html#running-out-of-file-handles","development/contributing_guide.html#contributing","development/contributing_guide.html#1-who-can-contribute-to-synapse","development/contributing_guide.html#2-what-do-i-need","development/contributing_guide.html#3-get-the-source","development/contributing_guide.html#4-install-the-dependencies","development/contributing_guide.html#running-synapse-via-poetry","development/contributing_guide.html#5-get-in-touch","development/contributing_guide.html#6-pick-an-issue","development/contributing_guide.html#7-turn-coffee-into-code-and-documentation","development/contributing_guide.html#8-test-test-test","development/contributing_guide.html#run-the-linters","development/contributing_guide.html#run-the-unit-tests-twisted-trial","development/contributing_guide.html#running-tests-under-postgresql","development/contributing_guide.html#run-the-integration-tests--sytest-","development/contributing_guide.html#run-the-integration-tests--complement-","development/contributing_guide.html#prettier-formatting-with-gotestfmt","development/contributing_guide.html#access-database-for-homeserver-after-complement-test-runs","development/contributing_guide.html#9-submit-your-patch","development/contributing_guide.html#changelog","development/contributing_guide.html#how-do-i-know-what-to-call-the-changelog-file-before-i-create-the-pr","development/contributing_guide.html#debian-changelog","development/contributing_guide.html#sign-off","development/contributing_guide.html#10-turn-feedback-into-better-code","development/contributing_guide.html#11-find-a-new-issue","development/contributing_guide.html#notes-for-maintainers-on-merging-prs-etc","development/contributing_guide.html#conclusion","code_style.html#code-style","code_style.html#formatting-tools","code_style.html#general-rules","code_style.html#configuration-code-and-documentation-format","code_style.html#modules","development/reviews.html#some-notes-on-how-we-do-reviews","development/reviews.html#performing-a-review","development/releases.html#synapse-release-cycle","development/releases.html#bugfix-releases","development/releases.html#security-releases","development/git.html#some-notes-on-how-we-use-git","development/git.html#on-keeping-the-commit-history-clean","development/git.html#merges-squashes-rebases-wtf","development/git.html#git-branching-model","development/demo.html#synapse-demo-setup","development/demo.html#using-the-demo-scripts","opentracing.html#opentracing","opentracing.html#background","opentracing.html#setting-up-opentracing","opentracing.html#enable-opentracing-in-synapse","opentracing.html#homeserver-whitelisting","opentracing.html#configuring-jaeger","development/database_schema.html#synapse-database-schema-files","development/database_schema.html#logical-databases","development/database_schema.html#synapse-schema-versions","development/database_schema.html#full-schema-dumps","development/database_schema.html#building-full-schema-dumps","development/database_schema.html#delta-files","development/database_schema.html#sql-delta-files","development/database_schema.html#python-delta-files","development/database_schema.html#background-updates","development/database_schema.html#boolean-columns","development/database_schema.html#event_id-global-uniqueness","development/database_schema.html#worked-examples-of-gradual-migrations","development/database_schema.html#transforming-a-column-into-another-one-with-not-null-constraints","development/experimental_features.html#implementing-experimental-features-in-synapse","development/dependencies.html#managing-dependencies-with-poetry","development/dependencies.html#installing","development/dependencies.html#background","development/dependencies.html#example-dependency","development/dependencies.html#tooling-recommendation-direnv","development/dependencies.html#how-do-i","development/dependencies.html#reset-my-venv-to-the-locked-environment","development/dependencies.html#delete-everything-and-start-over-from-scratch","development/dependencies.html#run-a-command-in-the-poetry-virtualenv","development/dependencies.html#inspect-the-poetry-virtualenv","development/dependencies.html#add-a-new-dependency","development/dependencies.html#remove-a-dependency","development/dependencies.html#update-the-version-range-for-an-existing-dependency","development/dependencies.html#update-a-dependency-in-the-locked-environment","development/dependencies.html#export-a-requirementstxt-file","development/dependencies.html#build-a-test-wheel","development/dependencies.html#handle-a-dependabot-pull-request","development/dependencies.html#troubleshooting","development/dependencies.html#check-the-version-of-poetry-with-poetry---version","development/dependencies.html#clear-caches-poetry-cache-clear---all-pypi","development/dependencies.html#remove-outdated-egg-info","development/dependencies.html#try---verbose-or---dry-run-arguments","development/synapse_architecture/cancellation.html#cancellation","development/synapse_architecture/cancellation.html#enabling-cancellation-for-an-endpoint","development/synapse_architecture/cancellation.html#mechanics","development/synapse_architecture/cancellation.html#deferredcancel","development/synapse_architecture/cancellation.html#cancellederror","development/synapse_architecture/cancellation.html#handling-cancellation-correctly","development/synapse_architecture/cancellation.html#async-function-calls","development/synapse_architecture/cancellation.html#cancellederrors","development/synapse_architecture/cancellation.html#creation-of-deferreds","development/synapse_architecture/cancellation.html#uncancelled-processing","log_contexts.html#log-contexts","log_contexts.html#logcontexts-without-asynchronous-code","log_contexts.html#using-logcontexts-with-awaitables","log_contexts.html#always-await-your-awaitables","log_contexts.html#where-you-create-a-new-awaitable-make-it-follow-the-rules","log_contexts.html#fire-and-forget","log_contexts.html#passing-synapse-deferreds-into-third-party-functions","log_contexts.html#a-note-on-garbage-collection-of-awaitable-chains","replication.html#replication-architecture","replication.html#motivation","replication.html#architecture","replication.html#the-replication-protocol","replication.html#the-tcp-replication-module","development/synapse_architecture/streams.html#streams","development/synapse_architecture/streams.html#definition","development/synapse_architecture/streams.html#current-stream-id","development/synapse_architecture/streams.html#multi-writer-streams","development/synapse_architecture/streams.html#writing-to-streams","development/synapse_architecture/streams.html#subscribing-to-streams","development/synapse_architecture/streams.html#summary","tcp_replication.html#tcp-replication","tcp_replication.html#motivation","tcp_replication.html#overview","tcp_replication.html#architecture","tcp_replication.html#keep-alives","tcp_replication.html#start-up","tcp_replication.html#error-handling","tcp_replication.html#congestion","tcp_replication.html#reliability","tcp_replication.html#example","tcp_replication.html#list-of-commands","tcp_replication.html#remote_server_up-s-c","tcp_replication.html#cache-invalidation-stream","development/synapse_architecture/faster_joins.html#how-do-faster-joins-work","development/synapse_architecture/faster_joins.html#overview-processing-events-in-a-partially-joined-room","development/synapse_architecture/faster_joins.html#partial-state","development/synapse_architecture/faster_joins.html#approximation-error","development/synapse_architecture/faster_joins.html#fixing-the-approximation-with-a-resync","development/synapse_architecture/faster_joins.html#faster-joins-on-workers","development/synapse_architecture/faster_joins.html#notes-on-specific-cases","development/synapse_architecture/faster_joins.html#creating-events-during-a-partial-join","development/synapse_architecture/faster_joins.html#joining-after-a-partial-join","development/synapse_architecture/faster_joins.html#leaving-and-kicks-and-bans-after-a-partial-join","development/internal_documentation/index.html#internal-documentation","development/saml.html#how-to-test-saml-as-a-developer-without-a-server","development/cas.html#how-to-test-cas-as-a-developer-without-a-server","development/cas.html#prerequisites","development/cas.html#configure-synapse-and-element-to-use-cas","development/cas.html#testing-the-configuration","development/room-dag-concepts.html#room-dag-concepts","development/room-dag-concepts.html#edges","development/room-dag-concepts.html#depth-and-stream-ordering","development/room-dag-concepts.html#outliers","development/room-dag-concepts.html#out-of-band-membership-events","development/room-dag-concepts.html#forward-extremity","development/room-dag-concepts.html#backward-extremity","development/room-dag-concepts.html#state-groups","development/room-dag-concepts.html#stage-group-edges","auth_chain_difference_algorithm.html#auth-chain-difference-algorithm","auth_chain_difference_algorithm.html#definitions","auth_chain_difference_algorithm.html#breadth-first-walk-algorithm","auth_chain_difference_algorithm.html#chain-cover-index","auth_chain_difference_algorithm.html#example","auth_chain_difference_algorithm.html#using-the-index","auth_chain_difference_algorithm.html#worked-example","media_repository.html#media-repository","media_repository.html#local-media","media_repository.html#paths","media_repository.html#remote-media","media_repository.html#paths-1","media_repository.html#url-previews","media_repository.html#paths-2","room_and_user_statistics.html#room-and-user-statistics","room_and_user_statistics.html#synapse-developer-documentation","room_and_user_statistics.html#high-level-concepts","room_and_user_statistics.html#definitions","room_and_user_statistics.html#overview","deprecation_policy.html#deprecation-policy-for-platform-dependencies","deprecation_policy.html#policy","deprecation_policy.html#context","other/running_synapse_on_single_board_computers.html#summary-of-performance-impact-of-running-on-resource-constrained-devices-such-as-sbcs","other/running_synapse_on_single_board_computers.html#presence","other/running_synapse_on_single_board_computers.html#joining","other/running_synapse_on_single_board_computers.html#sessions","other/running_synapse_on_single_board_computers.html#recommended-configuration"],"index":{"documentStore":{"docInfo":{"0":{"body":9,"breadcrumbs":3,"title":1},"1":{"body":55,"breadcrumbs":5,"title":3},"10":{"body":58,"breadcrumbs":3,"title":2},"100":{"body":26,"breadcrumbs":10,"title":6},"1000":{"body":143,"breadcrumbs":6,"title":3},"1001":{"body":80,"breadcrumbs":5,"title":2},"1002":{"body":54,"breadcrumbs":5,"title":2},"1003":{"body":80,"breadcrumbs":4,"title":1},"1004":{"body":0,"breadcrumbs":6,"title":2},"1005":{"body":23,"breadcrumbs":5,"title":1},"1006":{"body":171,"breadcrumbs":5,"title":1},"1007":{"body":34,"breadcrumbs":5,"title":1},"1008":{"body":57,"breadcrumbs":6,"title":2},"1009":{"body":56,"breadcrumbs":6,"title":2},"101":{"body":0,"breadcrumbs":6,"title":2},"1010":{"body":17,"breadcrumbs":6,"title":2},"1011":{"body":36,"breadcrumbs":5,"title":1},"1012":{"body":49,"breadcrumbs":5,"title":1},"1013":{"body":106,"breadcrumbs":5,"title":1},"1014":{"body":152,"breadcrumbs":6,"title":2},"1015":{"body":14,"breadcrumbs":7,"title":3},"1016":{"body":105,"breadcrumbs":7,"title":3},"1017":{"body":46,"breadcrumbs":8,"title":3},"1018":{"body":208,"breadcrumbs":11,"title":6},"1019":{"body":136,"breadcrumbs":7,"title":2},"102":{"body":32,"breadcrumbs":8,"title":4},"1020":{"body":192,"breadcrumbs":7,"title":2},"1021":{"body":147,"breadcrumbs":8,"title":3},"1022":{"body":28,"breadcrumbs":8,"title":3},"1023":{"body":11,"breadcrumbs":8,"title":3},"1024":{"body":292,"breadcrumbs":10,"title":5},"1025":{"body":108,"breadcrumbs":8,"title":3},"1026":{"body":300,"breadcrumbs":10,"title":5},"1027":{"body":46,"breadcrumbs":4,"title":2},"1028":{"body":142,"breadcrumbs":10,"title":5},"1029":{"body":11,"breadcrumbs":10,"title":5},"103":{"body":94,"breadcrumbs":6,"title":2},"1030":{"body":81,"breadcrumbs":6,"title":1},"1031":{"body":38,"breadcrumbs":10,"title":5},"1032":{"body":30,"breadcrumbs":7,"title":2},"1033":{"body":0,"breadcrumbs":8,"title":3},"1034":{"body":26,"breadcrumbs":6,"title":1},"1035":{"body":88,"breadcrumbs":8,"title":3},"1036":{"body":95,"breadcrumbs":6,"title":1},"1037":{"body":41,"breadcrumbs":9,"title":4},"1038":{"body":43,"breadcrumbs":7,"title":2},"1039":{"body":62,"breadcrumbs":7,"title":2},"104":{"body":0,"breadcrumbs":6,"title":2},"1040":{"body":37,"breadcrumbs":7,"title":2},"1041":{"body":7,"breadcrumbs":8,"title":3},"1042":{"body":15,"breadcrumbs":12,"title":4},"1043":{"body":63,"breadcrumbs":9,"title":1},"1044":{"body":61,"breadcrumbs":12,"title":4},"1045":{"body":289,"breadcrumbs":11,"title":3},"1046":{"body":53,"breadcrumbs":9,"title":1},"1047":{"body":80,"breadcrumbs":10,"title":2},"1048":{"body":111,"breadcrumbs":10,"title":2},"1049":{"body":44,"breadcrumbs":6,"title":2},"105":{"body":51,"breadcrumbs":9,"title":5},"1050":{"body":47,"breadcrumbs":6,"title":2},"1051":{"body":16,"breadcrumbs":5,"title":1},"1052":{"body":33,"breadcrumbs":6,"title":2},"1053":{"body":28,"breadcrumbs":5,"title":1},"1054":{"body":44,"breadcrumbs":6,"title":2},"1055":{"body":22,"breadcrumbs":5,"title":1},"1056":{"body":15,"breadcrumbs":8,"title":3},"1057":{"body":0,"breadcrumbs":8,"title":3},"1058":{"body":0,"breadcrumbs":8,"title":3},"1059":{"body":18,"breadcrumbs":6,"title":1},"106":{"body":0,"breadcrumbs":6,"title":2},"1060":{"body":15,"breadcrumbs":6,"title":1},"1061":{"body":19,"breadcrumbs":7,"title":4},"1062":{"body":64,"breadcrumbs":4,"title":1},"1063":{"body":115,"breadcrumbs":4,"title":1},"1064":{"body":54,"breadcrumbs":14,"title":9},"1065":{"body":86,"breadcrumbs":6,"title":1},"1066":{"body":114,"breadcrumbs":6,"title":1},"1067":{"body":43,"breadcrumbs":6,"title":1},"1068":{"body":153,"breadcrumbs":7,"title":2},"107":{"body":28,"breadcrumbs":9,"title":5},"108":{"body":0,"breadcrumbs":6,"title":2},"109":{"body":91,"breadcrumbs":9,"title":5},"11":{"body":113,"breadcrumbs":3,"title":2},"110":{"body":0,"breadcrumbs":6,"title":2},"111":{"body":20,"breadcrumbs":8,"title":4},"112":{"body":0,"breadcrumbs":6,"title":2},"113":{"body":32,"breadcrumbs":8,"title":4},"114":{"body":36,"breadcrumbs":9,"title":5},"115":{"body":26,"breadcrumbs":9,"title":5},"116":{"body":0,"breadcrumbs":6,"title":2},"117":{"body":50,"breadcrumbs":8,"title":4},"118":{"body":37,"breadcrumbs":7,"title":3},"119":{"body":0,"breadcrumbs":6,"title":2},"12":{"body":120,"breadcrumbs":5,"title":4},"120":{"body":77,"breadcrumbs":10,"title":6},"121":{"body":0,"breadcrumbs":6,"title":2},"122":{"body":16,"breadcrumbs":8,"title":4},"123":{"body":0,"breadcrumbs":6,"title":2},"124":{"body":15,"breadcrumbs":9,"title":5},"125":{"body":81,"breadcrumbs":10,"title":6},"126":{"body":56,"breadcrumbs":11,"title":7},"127":{"body":0,"breadcrumbs":6,"title":2},"128":{"body":33,"breadcrumbs":8,"title":4},"129":{"body":115,"breadcrumbs":9,"title":5},"13":{"body":55,"breadcrumbs":2,"title":1},"130":{"body":57,"breadcrumbs":9,"title":5},"131":{"body":9,"breadcrumbs":6,"title":2},"132":{"body":22,"breadcrumbs":7,"title":3},"133":{"body":35,"breadcrumbs":8,"title":4},"134":{"body":0,"breadcrumbs":6,"title":2},"135":{"body":63,"breadcrumbs":11,"title":7},"136":{"body":11,"breadcrumbs":9,"title":5},"137":{"body":26,"breadcrumbs":8,"title":4},"138":{"body":44,"breadcrumbs":9,"title":5},"139":{"body":0,"breadcrumbs":6,"title":2},"14":{"body":103,"breadcrumbs":3,"title":2},"140":{"body":63,"breadcrumbs":9,"title":5},"141":{"body":0,"breadcrumbs":6,"title":2},"142":{"body":44,"breadcrumbs":12,"title":8},"143":{"body":32,"breadcrumbs":8,"title":4},"144":{"body":34,"breadcrumbs":6,"title":2},"145":{"body":0,"breadcrumbs":6,"title":2},"146":{"body":82,"breadcrumbs":9,"title":5},"147":{"body":0,"breadcrumbs":6,"title":2},"148":{"body":6,"breadcrumbs":7,"title":3},"149":{"body":18,"breadcrumbs":6,"title":2},"15":{"body":13,"breadcrumbs":5,"title":4},"150":{"body":0,"breadcrumbs":6,"title":2},"151":{"body":102,"breadcrumbs":12,"title":8},"152":{"body":29,"breadcrumbs":5,"title":1},"153":{"body":32,"breadcrumbs":5,"title":1},"154":{"body":9,"breadcrumbs":6,"title":2},"155":{"body":62,"breadcrumbs":10,"title":6},"156":{"body":0,"breadcrumbs":6,"title":2},"157":{"body":25,"breadcrumbs":11,"title":7},"158":{"body":123,"breadcrumbs":10,"title":6},"159":{"body":0,"breadcrumbs":6,"title":2},"16":{"body":61,"breadcrumbs":3,"title":2},"160":{"body":10,"breadcrumbs":8,"title":4},"161":{"body":0,"breadcrumbs":6,"title":2},"162":{"body":136,"breadcrumbs":9,"title":5},"163":{"body":0,"breadcrumbs":6,"title":2},"164":{"body":18,"breadcrumbs":11,"title":7},"165":{"body":19,"breadcrumbs":7,"title":3},"166":{"body":32,"breadcrumbs":10,"title":6},"167":{"body":0,"breadcrumbs":6,"title":2},"168":{"body":60,"breadcrumbs":7,"title":3},"169":{"body":21,"breadcrumbs":9,"title":5},"17":{"body":6,"breadcrumbs":2,"title":1},"170":{"body":0,"breadcrumbs":6,"title":2},"171":{"body":20,"breadcrumbs":9,"title":5},"172":{"body":0,"breadcrumbs":6,"title":2},"173":{"body":36,"breadcrumbs":11,"title":7},"174":{"body":19,"breadcrumbs":6,"title":2},"175":{"body":46,"breadcrumbs":11,"title":7},"176":{"body":25,"breadcrumbs":7,"title":3},"177":{"body":31,"breadcrumbs":6,"title":2},"178":{"body":0,"breadcrumbs":6,"title":2},"179":{"body":42,"breadcrumbs":7,"title":3},"18":{"body":32,"breadcrumbs":3,"title":2},"180":{"body":0,"breadcrumbs":6,"title":2},"181":{"body":19,"breadcrumbs":10,"title":6},"182":{"body":0,"breadcrumbs":6,"title":2},"183":{"body":20,"breadcrumbs":10,"title":6},"184":{"body":0,"breadcrumbs":6,"title":2},"185":{"body":24,"breadcrumbs":9,"title":5},"186":{"body":29,"breadcrumbs":8,"title":4},"187":{"body":0,"breadcrumbs":6,"title":2},"188":{"body":28,"breadcrumbs":14,"title":10},"189":{"body":0,"breadcrumbs":6,"title":2},"19":{"body":8,"breadcrumbs":4,"title":2},"190":{"body":18,"breadcrumbs":11,"title":7},"191":{"body":0,"breadcrumbs":6,"title":2},"192":{"body":19,"breadcrumbs":10,"title":6},"193":{"body":0,"breadcrumbs":6,"title":2},"194":{"body":26,"breadcrumbs":9,"title":5},"195":{"body":26,"breadcrumbs":12,"title":8},"196":{"body":12,"breadcrumbs":9,"title":5},"197":{"body":0,"breadcrumbs":6,"title":2},"198":{"body":70,"breadcrumbs":13,"title":9},"199":{"body":43,"breadcrumbs":6,"title":2},"2":{"body":74,"breadcrumbs":4,"title":2},"20":{"body":63,"breadcrumbs":6,"title":4},"200":{"body":21,"breadcrumbs":8,"title":4},"201":{"body":0,"breadcrumbs":6,"title":2},"202":{"body":44,"breadcrumbs":11,"title":7},"203":{"body":0,"breadcrumbs":6,"title":2},"204":{"body":96,"breadcrumbs":10,"title":6},"205":{"body":0,"breadcrumbs":6,"title":2},"206":{"body":48,"breadcrumbs":9,"title":5},"207":{"body":0,"breadcrumbs":6,"title":2},"208":{"body":34,"breadcrumbs":7,"title":3},"209":{"body":0,"breadcrumbs":6,"title":2},"21":{"body":70,"breadcrumbs":5,"title":3},"210":{"body":75,"breadcrumbs":13,"title":9},"211":{"body":0,"breadcrumbs":6,"title":2},"212":{"body":27,"breadcrumbs":11,"title":7},"213":{"body":22,"breadcrumbs":11,"title":7},"214":{"body":32,"breadcrumbs":10,"title":6},"215":{"body":26,"breadcrumbs":11,"title":7},"216":{"body":0,"breadcrumbs":6,"title":2},"217":{"body":72,"breadcrumbs":9,"title":5},"218":{"body":0,"breadcrumbs":6,"title":2},"219":{"body":99,"breadcrumbs":11,"title":7},"22":{"body":104,"breadcrumbs":4,"title":2},"220":{"body":64,"breadcrumbs":7,"title":3},"221":{"body":0,"breadcrumbs":6,"title":2},"222":{"body":102,"breadcrumbs":9,"title":5},"223":{"body":0,"breadcrumbs":6,"title":2},"224":{"body":42,"breadcrumbs":9,"title":5},"225":{"body":57,"breadcrumbs":7,"title":3},"226":{"body":0,"breadcrumbs":6,"title":2},"227":{"body":66,"breadcrumbs":11,"title":7},"228":{"body":50,"breadcrumbs":9,"title":5},"229":{"body":0,"breadcrumbs":6,"title":2},"23":{"body":35,"breadcrumbs":6,"title":4},"230":{"body":39,"breadcrumbs":9,"title":5},"231":{"body":0,"breadcrumbs":6,"title":2},"232":{"body":61,"breadcrumbs":7,"title":3},"233":{"body":0,"breadcrumbs":6,"title":2},"234":{"body":50,"breadcrumbs":9,"title":5},"235":{"body":63,"breadcrumbs":7,"title":3},"236":{"body":46,"breadcrumbs":9,"title":5},"237":{"body":0,"breadcrumbs":6,"title":2},"238":{"body":46,"breadcrumbs":10,"title":6},"239":{"body":24,"breadcrumbs":11,"title":7},"24":{"body":5,"breadcrumbs":3,"title":1},"240":{"body":20,"breadcrumbs":6,"title":2},"241":{"body":0,"breadcrumbs":6,"title":2},"242":{"body":65,"breadcrumbs":10,"title":6},"243":{"body":19,"breadcrumbs":9,"title":5},"244":{"body":18,"breadcrumbs":9,"title":5},"245":{"body":57,"breadcrumbs":9,"title":5},"246":{"body":196,"breadcrumbs":6,"title":2},"247":{"body":16,"breadcrumbs":6,"title":2},"248":{"body":18,"breadcrumbs":6,"title":2},"249":{"body":51,"breadcrumbs":6,"title":2},"25":{"body":58,"breadcrumbs":4,"title":2},"250":{"body":19,"breadcrumbs":6,"title":2},"251":{"body":0,"breadcrumbs":6,"title":2},"252":{"body":40,"breadcrumbs":7,"title":3},"253":{"body":216,"breadcrumbs":7,"title":3},"254":{"body":191,"breadcrumbs":5,"title":1},"255":{"body":95,"breadcrumbs":6,"title":2},"256":{"body":67,"breadcrumbs":7,"title":3},"257":{"body":10,"breadcrumbs":6,"title":2},"258":{"body":11,"breadcrumbs":6,"title":2},"259":{"body":48,"breadcrumbs":7,"title":3},"26":{"body":0,"breadcrumbs":4,"title":2},"260":{"body":17,"breadcrumbs":7,"title":3},"261":{"body":0,"breadcrumbs":6,"title":2},"262":{"body":61,"breadcrumbs":7,"title":3},"263":{"body":88,"breadcrumbs":5,"title":1},"264":{"body":53,"breadcrumbs":7,"title":3},"265":{"body":22,"breadcrumbs":6,"title":2},"266":{"body":223,"breadcrumbs":6,"title":2},"267":{"body":40,"breadcrumbs":6,"title":2},"268":{"body":42,"breadcrumbs":6,"title":2},"269":{"body":16,"breadcrumbs":6,"title":2},"27":{"body":124,"breadcrumbs":3,"title":1},"270":{"body":49,"breadcrumbs":6,"title":2},"271":{"body":97,"breadcrumbs":6,"title":2},"272":{"body":20,"breadcrumbs":6,"title":2},"273":{"body":20,"breadcrumbs":6,"title":2},"274":{"body":49,"breadcrumbs":6,"title":2},"275":{"body":24,"breadcrumbs":6,"title":2},"276":{"body":136,"breadcrumbs":6,"title":2},"277":{"body":25,"breadcrumbs":6,"title":2},"278":{"body":79,"breadcrumbs":6,"title":2},"279":{"body":23,"breadcrumbs":6,"title":2},"28":{"body":144,"breadcrumbs":5,"title":3},"280":{"body":68,"breadcrumbs":6,"title":2},"281":{"body":94,"breadcrumbs":6,"title":2},"282":{"body":132,"breadcrumbs":4,"title":3},"283":{"body":77,"breadcrumbs":2,"title":1},"284":{"body":64,"breadcrumbs":3,"title":2},"285":{"body":18,"breadcrumbs":5,"title":4},"286":{"body":15,"breadcrumbs":2,"title":1},"287":{"body":55,"breadcrumbs":5,"title":2},"288":{"body":74,"breadcrumbs":5,"title":2},"289":{"body":39,"breadcrumbs":5,"title":2},"29":{"body":0,"breadcrumbs":3,"title":1},"290":{"body":142,"breadcrumbs":4,"title":1},"291":{"body":16,"breadcrumbs":4,"title":1},"292":{"body":32,"breadcrumbs":4,"title":1},"293":{"body":5,"breadcrumbs":4,"title":1},"294":{"body":72,"breadcrumbs":4,"title":1},"295":{"body":12,"breadcrumbs":4,"title":1},"296":{"body":30,"breadcrumbs":4,"title":1},"297":{"body":17,"breadcrumbs":4,"title":1},"298":{"body":16,"breadcrumbs":4,"title":1},"299":{"body":24,"breadcrumbs":4,"title":1},"3":{"body":14,"breadcrumbs":5,"title":3},"30":{"body":67,"breadcrumbs":5,"title":3},"300":{"body":11,"breadcrumbs":4,"title":1},"301":{"body":44,"breadcrumbs":4,"title":1},"302":{"body":44,"breadcrumbs":4,"title":1},"303":{"body":47,"breadcrumbs":4,"title":1},"304":{"body":23,"breadcrumbs":4,"title":1},"305":{"body":78,"breadcrumbs":4,"title":1},"306":{"body":30,"breadcrumbs":4,"title":1},"307":{"body":28,"breadcrumbs":4,"title":1},"308":{"body":34,"breadcrumbs":4,"title":1},"309":{"body":24,"breadcrumbs":4,"title":1},"31":{"body":79,"breadcrumbs":6,"title":4},"310":{"body":17,"breadcrumbs":4,"title":1},"311":{"body":36,"breadcrumbs":4,"title":1},"312":{"body":15,"breadcrumbs":4,"title":1},"313":{"body":37,"breadcrumbs":4,"title":1},"314":{"body":18,"breadcrumbs":4,"title":1},"315":{"body":18,"breadcrumbs":4,"title":1},"316":{"body":17,"breadcrumbs":4,"title":1},"317":{"body":81,"breadcrumbs":4,"title":1},"318":{"body":43,"breadcrumbs":4,"title":1},"319":{"body":491,"breadcrumbs":4,"title":1},"32":{"body":126,"breadcrumbs":7,"title":4},"320":{"body":18,"breadcrumbs":4,"title":1},"321":{"body":58,"breadcrumbs":4,"title":1},"322":{"body":54,"breadcrumbs":4,"title":1},"323":{"body":44,"breadcrumbs":4,"title":1},"324":{"body":601,"breadcrumbs":4,"title":1},"325":{"body":22,"breadcrumbs":4,"title":1},"326":{"body":4,"breadcrumbs":5,"title":2},"327":{"body":11,"breadcrumbs":4,"title":1},"328":{"body":20,"breadcrumbs":5,"title":2},"329":{"body":42,"breadcrumbs":4,"title":1},"33":{"body":55,"breadcrumbs":5,"title":2},"330":{"body":21,"breadcrumbs":4,"title":1},"331":{"body":37,"breadcrumbs":4,"title":1},"332":{"body":31,"breadcrumbs":4,"title":1},"333":{"body":34,"breadcrumbs":4,"title":1},"334":{"body":21,"breadcrumbs":4,"title":1},"335":{"body":33,"breadcrumbs":4,"title":1},"336":{"body":14,"breadcrumbs":4,"title":1},"337":{"body":78,"breadcrumbs":4,"title":1},"338":{"body":12,"breadcrumbs":4,"title":1},"339":{"body":22,"breadcrumbs":4,"title":1},"34":{"body":3,"breadcrumbs":7,"title":4},"340":{"body":29,"breadcrumbs":4,"title":1},"341":{"body":24,"breadcrumbs":4,"title":1},"342":{"body":48,"breadcrumbs":4,"title":1},"343":{"body":17,"breadcrumbs":4,"title":1},"344":{"body":21,"breadcrumbs":4,"title":1},"345":{"body":50,"breadcrumbs":4,"title":1},"346":{"body":55,"breadcrumbs":4,"title":1},"347":{"body":47,"breadcrumbs":5,"title":2},"348":{"body":306,"breadcrumbs":4,"title":1},"349":{"body":3,"breadcrumbs":4,"title":1},"35":{"body":73,"breadcrumbs":4,"title":1},"350":{"body":42,"breadcrumbs":4,"title":1},"351":{"body":11,"breadcrumbs":4,"title":1},"352":{"body":20,"breadcrumbs":4,"title":1},"353":{"body":38,"breadcrumbs":4,"title":1},"354":{"body":36,"breadcrumbs":4,"title":1},"355":{"body":29,"breadcrumbs":4,"title":1},"356":{"body":3,"breadcrumbs":4,"title":1},"357":{"body":51,"breadcrumbs":4,"title":1},"358":{"body":38,"breadcrumbs":4,"title":1},"359":{"body":34,"breadcrumbs":4,"title":1},"36":{"body":43,"breadcrumbs":5,"title":2},"360":{"body":21,"breadcrumbs":4,"title":1},"361":{"body":25,"breadcrumbs":4,"title":1},"362":{"body":143,"breadcrumbs":4,"title":1},"363":{"body":3,"breadcrumbs":4,"title":1},"364":{"body":38,"breadcrumbs":4,"title":1},"365":{"body":336,"breadcrumbs":6,"title":3},"366":{"body":46,"breadcrumbs":6,"title":3},"367":{"body":5,"breadcrumbs":4,"title":1},"368":{"body":134,"breadcrumbs":4,"title":1},"369":{"body":305,"breadcrumbs":4,"title":1},"37":{"body":93,"breadcrumbs":4,"title":1},"370":{"body":4,"breadcrumbs":4,"title":1},"371":{"body":13,"breadcrumbs":4,"title":1},"372":{"body":25,"breadcrumbs":4,"title":1},"373":{"body":25,"breadcrumbs":4,"title":1},"374":{"body":20,"breadcrumbs":4,"title":1},"375":{"body":23,"breadcrumbs":4,"title":1},"376":{"body":70,"breadcrumbs":4,"title":1},"377":{"body":27,"breadcrumbs":4,"title":1},"378":{"body":53,"breadcrumbs":4,"title":1},"379":{"body":46,"breadcrumbs":4,"title":1},"38":{"body":342,"breadcrumbs":4,"title":1},"380":{"body":19,"breadcrumbs":4,"title":1},"381":{"body":124,"breadcrumbs":4,"title":1},"382":{"body":32,"breadcrumbs":4,"title":1},"383":{"body":25,"breadcrumbs":4,"title":1},"384":{"body":77,"breadcrumbs":4,"title":1},"385":{"body":45,"breadcrumbs":4,"title":1},"386":{"body":67,"breadcrumbs":4,"title":1},"387":{"body":28,"breadcrumbs":4,"title":1},"388":{"body":6,"breadcrumbs":5,"title":2},"389":{"body":212,"breadcrumbs":4,"title":1},"39":{"body":142,"breadcrumbs":4,"title":1},"390":{"body":19,"breadcrumbs":4,"title":1},"391":{"body":9,"breadcrumbs":4,"title":1},"392":{"body":25,"breadcrumbs":4,"title":1},"393":{"body":14,"breadcrumbs":4,"title":1},"394":{"body":60,"breadcrumbs":4,"title":1},"395":{"body":34,"breadcrumbs":4,"title":1},"396":{"body":10,"breadcrumbs":4,"title":1},"397":{"body":60,"breadcrumbs":4,"title":1},"398":{"body":73,"breadcrumbs":4,"title":1},"399":{"body":60,"breadcrumbs":4,"title":1},"4":{"body":0,"breadcrumbs":3,"title":2},"40":{"body":20,"breadcrumbs":6,"title":3},"400":{"body":32,"breadcrumbs":4,"title":1},"401":{"body":48,"breadcrumbs":4,"title":1},"402":{"body":96,"breadcrumbs":4,"title":1},"403":{"body":20,"breadcrumbs":4,"title":1},"404":{"body":88,"breadcrumbs":4,"title":1},"405":{"body":39,"breadcrumbs":4,"title":1},"406":{"body":134,"breadcrumbs":4,"title":1},"407":{"body":13,"breadcrumbs":4,"title":1},"408":{"body":65,"breadcrumbs":4,"title":1},"409":{"body":46,"breadcrumbs":4,"title":1},"41":{"body":27,"breadcrumbs":6,"title":3},"410":{"body":7,"breadcrumbs":4,"title":1},"411":{"body":11,"breadcrumbs":4,"title":1},"412":{"body":11,"breadcrumbs":4,"title":1},"413":{"body":26,"breadcrumbs":4,"title":1},"414":{"body":12,"breadcrumbs":4,"title":1},"415":{"body":6,"breadcrumbs":4,"title":1},"416":{"body":10,"breadcrumbs":4,"title":1},"417":{"body":11,"breadcrumbs":4,"title":1},"418":{"body":30,"breadcrumbs":4,"title":1},"419":{"body":13,"breadcrumbs":5,"title":2},"42":{"body":27,"breadcrumbs":7,"title":4},"420":{"body":11,"breadcrumbs":4,"title":1},"421":{"body":35,"breadcrumbs":4,"title":1},"422":{"body":8,"breadcrumbs":4,"title":1},"423":{"body":46,"breadcrumbs":4,"title":1},"424":{"body":26,"breadcrumbs":4,"title":1},"425":{"body":19,"breadcrumbs":4,"title":1},"426":{"body":15,"breadcrumbs":4,"title":1},"427":{"body":44,"breadcrumbs":4,"title":1},"428":{"body":13,"breadcrumbs":4,"title":1},"429":{"body":32,"breadcrumbs":4,"title":1},"43":{"body":111,"breadcrumbs":4,"title":1},"430":{"body":58,"breadcrumbs":4,"title":1},"431":{"body":32,"breadcrumbs":4,"title":1},"432":{"body":41,"breadcrumbs":4,"title":1},"433":{"body":20,"breadcrumbs":4,"title":1},"434":{"body":24,"breadcrumbs":4,"title":1},"435":{"body":91,"breadcrumbs":4,"title":1},"436":{"body":24,"breadcrumbs":4,"title":1},"437":{"body":24,"breadcrumbs":4,"title":1},"438":{"body":17,"breadcrumbs":4,"title":1},"439":{"body":56,"breadcrumbs":4,"title":1},"44":{"body":42,"breadcrumbs":5,"title":2},"440":{"body":45,"breadcrumbs":4,"title":1},"441":{"body":34,"breadcrumbs":4,"title":1},"442":{"body":70,"breadcrumbs":4,"title":1},"443":{"body":63,"breadcrumbs":4,"title":1},"444":{"body":18,"breadcrumbs":4,"title":1},"445":{"body":43,"breadcrumbs":4,"title":1},"446":{"body":32,"breadcrumbs":4,"title":1},"447":{"body":0,"breadcrumbs":6,"title":3},"448":{"body":27,"breadcrumbs":4,"title":1},"449":{"body":42,"breadcrumbs":4,"title":1},"45":{"body":28,"breadcrumbs":4,"title":1},"450":{"body":40,"breadcrumbs":4,"title":1},"451":{"body":41,"breadcrumbs":4,"title":1},"452":{"body":69,"breadcrumbs":4,"title":1},"453":{"body":52,"breadcrumbs":4,"title":1},"454":{"body":4,"breadcrumbs":4,"title":1},"455":{"body":13,"breadcrumbs":4,"title":1},"456":{"body":60,"breadcrumbs":4,"title":1},"457":{"body":33,"breadcrumbs":4,"title":1},"458":{"body":36,"breadcrumbs":4,"title":1},"459":{"body":15,"breadcrumbs":4,"title":1},"46":{"body":44,"breadcrumbs":4,"title":1},"460":{"body":5,"breadcrumbs":5,"title":2},"461":{"body":151,"breadcrumbs":4,"title":1},"462":{"body":64,"breadcrumbs":4,"title":1},"463":{"body":11,"breadcrumbs":4,"title":1},"464":{"body":21,"breadcrumbs":4,"title":1},"465":{"body":35,"breadcrumbs":4,"title":1},"466":{"body":67,"breadcrumbs":4,"title":1},"467":{"body":30,"breadcrumbs":4,"title":1},"468":{"body":35,"breadcrumbs":4,"title":1},"469":{"body":27,"breadcrumbs":4,"title":1},"47":{"body":33,"breadcrumbs":4,"title":1},"470":{"body":5,"breadcrumbs":5,"title":2},"471":{"body":24,"breadcrumbs":4,"title":1},"472":{"body":68,"breadcrumbs":4,"title":1},"473":{"body":25,"breadcrumbs":4,"title":1},"474":{"body":163,"breadcrumbs":4,"title":1},"475":{"body":15,"breadcrumbs":4,"title":1},"476":{"body":22,"breadcrumbs":4,"title":1},"477":{"body":26,"breadcrumbs":6,"title":3},"478":{"body":568,"breadcrumbs":4,"title":1},"479":{"body":1035,"breadcrumbs":4,"title":1},"48":{"body":66,"breadcrumbs":5,"title":2},"480":{"body":258,"breadcrumbs":4,"title":1},"481":{"body":135,"breadcrumbs":4,"title":1},"482":{"body":195,"breadcrumbs":4,"title":1},"483":{"body":152,"breadcrumbs":4,"title":1},"484":{"body":5,"breadcrumbs":4,"title":1},"485":{"body":169,"breadcrumbs":4,"title":1},"486":{"body":4,"breadcrumbs":4,"title":1},"487":{"body":43,"breadcrumbs":4,"title":1},"488":{"body":163,"breadcrumbs":4,"title":1},"489":{"body":161,"breadcrumbs":4,"title":1},"49":{"body":348,"breadcrumbs":4,"title":1},"490":{"body":33,"breadcrumbs":4,"title":1},"491":{"body":150,"breadcrumbs":4,"title":1},"492":{"body":28,"breadcrumbs":4,"title":1},"493":{"body":191,"breadcrumbs":4,"title":1},"494":{"body":279,"breadcrumbs":4,"title":1},"495":{"body":131,"breadcrumbs":4,"title":1},"496":{"body":17,"breadcrumbs":4,"title":1},"497":{"body":24,"breadcrumbs":4,"title":1},"498":{"body":5,"breadcrumbs":4,"title":1},"499":{"body":122,"breadcrumbs":4,"title":1},"5":{"body":60,"breadcrumbs":4,"title":3},"50":{"body":9,"breadcrumbs":9,"title":3},"500":{"body":73,"breadcrumbs":5,"title":2},"501":{"body":37,"breadcrumbs":4,"title":1},"502":{"body":27,"breadcrumbs":4,"title":1},"503":{"body":22,"breadcrumbs":4,"title":1},"504":{"body":48,"breadcrumbs":4,"title":1},"505":{"body":24,"breadcrumbs":4,"title":1},"506":{"body":95,"breadcrumbs":4,"title":1},"507":{"body":75,"breadcrumbs":4,"title":1},"508":{"body":30,"breadcrumbs":4,"title":1},"509":{"body":32,"breadcrumbs":4,"title":1},"51":{"body":0,"breadcrumbs":8,"title":2},"510":{"body":18,"breadcrumbs":4,"title":1},"511":{"body":16,"breadcrumbs":4,"title":1},"512":{"body":18,"breadcrumbs":4,"title":1},"513":{"body":31,"breadcrumbs":4,"title":1},"514":{"body":163,"breadcrumbs":4,"title":1},"515":{"body":24,"breadcrumbs":6,"title":3},"516":{"body":16,"breadcrumbs":4,"title":1},"517":{"body":23,"breadcrumbs":4,"title":1},"518":{"body":62,"breadcrumbs":4,"title":1},"519":{"body":27,"breadcrumbs":4,"title":1},"52":{"body":61,"breadcrumbs":8,"title":2},"520":{"body":20,"breadcrumbs":4,"title":1},"521":{"body":31,"breadcrumbs":4,"title":1},"522":{"body":23,"breadcrumbs":4,"title":1},"523":{"body":5,"breadcrumbs":5,"title":2},"524":{"body":111,"breadcrumbs":4,"title":1},"525":{"body":6,"breadcrumbs":6,"title":3},"526":{"body":107,"breadcrumbs":4,"title":1},"527":{"body":154,"breadcrumbs":9,"title":4},"528":{"body":283,"breadcrumbs":9,"title":4},"529":{"body":196,"breadcrumbs":5,"title":2},"53":{"body":471,"breadcrumbs":7,"title":1},"530":{"body":118,"breadcrumbs":3,"title":1},"531":{"body":309,"breadcrumbs":4,"title":2},"532":{"body":129,"breadcrumbs":8,"title":6},"533":{"body":480,"breadcrumbs":8,"title":6},"534":{"body":52,"breadcrumbs":5,"title":2},"535":{"body":23,"breadcrumbs":7,"title":2},"536":{"body":76,"breadcrumbs":14,"title":7},"537":{"body":58,"breadcrumbs":9,"title":2},"538":{"body":44,"breadcrumbs":11,"title":4},"539":{"body":6,"breadcrumbs":9,"title":2},"54":{"body":9,"breadcrumbs":9,"title":3},"540":{"body":77,"breadcrumbs":11,"title":4},"541":{"body":104,"breadcrumbs":8,"title":1},"542":{"body":79,"breadcrumbs":8,"title":1},"543":{"body":96,"breadcrumbs":8,"title":1},"544":{"body":82,"breadcrumbs":8,"title":1},"545":{"body":105,"breadcrumbs":10,"title":3},"546":{"body":127,"breadcrumbs":8,"title":1},"547":{"body":64,"breadcrumbs":8,"title":1},"548":{"body":85,"breadcrumbs":8,"title":1},"549":{"body":49,"breadcrumbs":8,"title":1},"55":{"body":0,"breadcrumbs":8,"title":2},"550":{"body":82,"breadcrumbs":8,"title":1},"551":{"body":82,"breadcrumbs":8,"title":1},"552":{"body":142,"breadcrumbs":8,"title":1},"553":{"body":121,"breadcrumbs":8,"title":1},"554":{"body":125,"breadcrumbs":8,"title":1},"555":{"body":76,"breadcrumbs":9,"title":2},"556":{"body":85,"breadcrumbs":10,"title":3},"557":{"body":42,"breadcrumbs":8,"title":1},"558":{"body":111,"breadcrumbs":8,"title":1},"559":{"body":33,"breadcrumbs":8,"title":1},"56":{"body":27,"breadcrumbs":8,"title":2},"560":{"body":22,"breadcrumbs":7,"title":1},"561":{"body":20,"breadcrumbs":7,"title":1},"562":{"body":167,"breadcrumbs":11,"title":3},"563":{"body":39,"breadcrumbs":11,"title":3},"564":{"body":275,"breadcrumbs":13,"title":5},"565":{"body":12,"breadcrumbs":12,"title":4},"566":{"body":39,"breadcrumbs":11,"title":3},"567":{"body":272,"breadcrumbs":13,"title":5},"568":{"body":12,"breadcrumbs":12,"title":4},"569":{"body":76,"breadcrumbs":10,"title":4},"57":{"body":423,"breadcrumbs":7,"title":1},"570":{"body":50,"breadcrumbs":8,"title":2},"571":{"body":269,"breadcrumbs":8,"title":2},"572":{"body":114,"breadcrumbs":9,"title":3},"573":{"body":53,"breadcrumbs":8,"title":2},"574":{"body":116,"breadcrumbs":9,"title":3},"575":{"body":14,"breadcrumbs":7,"title":2},"576":{"body":172,"breadcrumbs":7,"title":2},"577":{"body":121,"breadcrumbs":6,"title":1},"578":{"body":143,"breadcrumbs":7,"title":2},"579":{"body":128,"breadcrumbs":13,"title":8},"58":{"body":41,"breadcrumbs":9,"title":3},"580":{"body":18,"breadcrumbs":4,"title":1},"581":{"body":80,"breadcrumbs":6,"title":3},"582":{"body":34,"breadcrumbs":7,"title":4},"583":{"body":98,"breadcrumbs":6,"title":3},"584":{"body":42,"breadcrumbs":5,"title":2},"585":{"body":56,"breadcrumbs":5,"title":2},"586":{"body":108,"breadcrumbs":5,"title":2},"587":{"body":6,"breadcrumbs":5,"title":2},"588":{"body":50,"breadcrumbs":10,"title":7},"589":{"body":182,"breadcrumbs":7,"title":4},"59":{"body":68,"breadcrumbs":5,"title":4},"590":{"body":77,"breadcrumbs":7,"title":4},"591":{"body":80,"breadcrumbs":6,"title":3},"592":{"body":65,"breadcrumbs":10,"title":7},"593":{"body":57,"breadcrumbs":10,"title":7},"594":{"body":52,"breadcrumbs":7,"title":4},"595":{"body":174,"breadcrumbs":5,"title":2},"596":{"body":17,"breadcrumbs":5,"title":2},"597":{"body":113,"breadcrumbs":5,"title":2},"598":{"body":125,"breadcrumbs":4,"title":1},"599":{"body":49,"breadcrumbs":4,"title":1},"6":{"body":0,"breadcrumbs":3,"title":2},"60":{"body":24,"breadcrumbs":4,"title":3},"600":{"body":214,"breadcrumbs":7,"title":3},"601":{"body":23,"breadcrumbs":6,"title":2},"602":{"body":71,"breadcrumbs":6,"title":2},"603":{"body":217,"breadcrumbs":6,"title":2},"604":{"body":105,"breadcrumbs":6,"title":2},"605":{"body":58,"breadcrumbs":6,"title":2},"606":{"body":53,"breadcrumbs":8,"title":4},"607":{"body":36,"breadcrumbs":4,"title":1},"608":{"body":31,"breadcrumbs":5,"title":2},"609":{"body":76,"breadcrumbs":6,"title":3},"61":{"body":60,"breadcrumbs":3,"title":2},"610":{"body":36,"breadcrumbs":5,"title":2},"611":{"body":51,"breadcrumbs":7,"title":2},"612":{"body":58,"breadcrumbs":10,"title":5},"613":{"body":36,"breadcrumbs":8,"title":3},"614":{"body":93,"breadcrumbs":8,"title":3},"615":{"body":69,"breadcrumbs":7,"title":2},"616":{"body":145,"breadcrumbs":6,"title":1},"617":{"body":21,"breadcrumbs":11,"title":3},"618":{"body":4,"breadcrumbs":9,"title":1},"619":{"body":105,"breadcrumbs":9,"title":1},"62":{"body":43,"breadcrumbs":6,"title":5},"620":{"body":121,"breadcrumbs":9,"title":1},"621":{"body":103,"breadcrumbs":9,"title":1},"622":{"body":186,"breadcrumbs":9,"title":1},"623":{"body":84,"breadcrumbs":9,"title":1},"624":{"body":87,"breadcrumbs":9,"title":1},"625":{"body":89,"breadcrumbs":9,"title":1},"626":{"body":119,"breadcrumbs":9,"title":1},"627":{"body":106,"breadcrumbs":9,"title":1},"628":{"body":87,"breadcrumbs":9,"title":1},"629":{"body":68,"breadcrumbs":9,"title":1},"63":{"body":101,"breadcrumbs":5,"title":4},"630":{"body":97,"breadcrumbs":9,"title":1},"631":{"body":99,"breadcrumbs":9,"title":1},"632":{"body":25,"breadcrumbs":13,"title":4},"633":{"body":5,"breadcrumbs":10,"title":1},"634":{"body":212,"breadcrumbs":10,"title":1},"635":{"body":86,"breadcrumbs":10,"title":1},"636":{"body":59,"breadcrumbs":10,"title":1},"637":{"body":61,"breadcrumbs":10,"title":1},"638":{"body":88,"breadcrumbs":10,"title":1},"639":{"body":61,"breadcrumbs":10,"title":1},"64":{"body":0,"breadcrumbs":3,"title":2},"640":{"body":88,"breadcrumbs":10,"title":1},"641":{"body":131,"breadcrumbs":10,"title":1},"642":{"body":76,"breadcrumbs":10,"title":1},"643":{"body":64,"breadcrumbs":10,"title":1},"644":{"body":65,"breadcrumbs":10,"title":1},"645":{"body":65,"breadcrumbs":10,"title":1},"646":{"body":64,"breadcrumbs":10,"title":1},"647":{"body":56,"breadcrumbs":11,"title":3},"648":{"body":4,"breadcrumbs":9,"title":1},"649":{"body":75,"breadcrumbs":9,"title":1},"65":{"body":60,"breadcrumbs":3,"title":2},"650":{"body":95,"breadcrumbs":9,"title":1},"651":{"body":76,"breadcrumbs":9,"title":1},"652":{"body":33,"breadcrumbs":11,"title":3},"653":{"body":83,"breadcrumbs":9,"title":1},"654":{"body":37,"breadcrumbs":9,"title":1},"655":{"body":36,"breadcrumbs":9,"title":1},"656":{"body":20,"breadcrumbs":13,"title":4},"657":{"body":0,"breadcrumbs":10,"title":1},"658":{"body":160,"breadcrumbs":10,"title":1},"659":{"body":96,"breadcrumbs":10,"title":1},"66":{"body":24,"breadcrumbs":6,"title":5},"660":{"body":54,"breadcrumbs":10,"title":1},"661":{"body":216,"breadcrumbs":10,"title":1},"662":{"body":103,"breadcrumbs":10,"title":1},"663":{"body":88,"breadcrumbs":10,"title":1},"664":{"body":112,"breadcrumbs":10,"title":1},"665":{"body":88,"breadcrumbs":13,"title":4},"666":{"body":103,"breadcrumbs":10,"title":1},"667":{"body":34,"breadcrumbs":10,"title":1},"668":{"body":44,"breadcrumbs":10,"title":1},"669":{"body":21,"breadcrumbs":11,"title":3},"67":{"body":159,"breadcrumbs":6,"title":2},"670":{"body":4,"breadcrumbs":9,"title":1},"671":{"body":94,"breadcrumbs":9,"title":1},"672":{"body":111,"breadcrumbs":9,"title":1},"673":{"body":26,"breadcrumbs":21,"title":8},"674":{"body":48,"breadcrumbs":14,"title":1},"675":{"body":84,"breadcrumbs":16,"title":6},"676":{"body":85,"breadcrumbs":6,"title":4},"677":{"body":80,"breadcrumbs":5,"title":3},"678":{"body":155,"breadcrumbs":5,"title":3},"679":{"body":139,"breadcrumbs":4,"title":2},"68":{"body":143,"breadcrumbs":8,"title":4},"680":{"body":96,"breadcrumbs":4,"title":2},"681":{"body":33,"breadcrumbs":5,"title":3},"682":{"body":36,"breadcrumbs":5,"title":3},"683":{"body":0,"breadcrumbs":5,"title":3},"684":{"body":1125,"breadcrumbs":3,"title":1},"685":{"body":61,"breadcrumbs":3,"title":1},"686":{"body":38,"breadcrumbs":3,"title":1},"687":{"body":66,"breadcrumbs":3,"title":1},"688":{"body":111,"breadcrumbs":3,"title":1},"689":{"body":75,"breadcrumbs":3,"title":1},"69":{"body":91,"breadcrumbs":8,"title":4},"690":{"body":16,"breadcrumbs":4,"title":2},"691":{"body":31,"breadcrumbs":5,"title":3},"692":{"body":36,"breadcrumbs":4,"title":2},"693":{"body":90,"breadcrumbs":8,"title":3},"694":{"body":42,"breadcrumbs":8,"title":5},"695":{"body":70,"breadcrumbs":6,"title":3},"696":{"body":68,"breadcrumbs":5,"title":2},"697":{"body":62,"breadcrumbs":4,"title":1},"698":{"body":103,"breadcrumbs":4,"title":1},"699":{"body":25,"breadcrumbs":2,"title":1},"7":{"body":481,"breadcrumbs":3,"title":2},"70":{"body":0,"breadcrumbs":6,"title":2},"700":{"body":26,"breadcrumbs":6,"title":4},"701":{"body":24,"breadcrumbs":4,"title":2},"702":{"body":30,"breadcrumbs":5,"title":3},"703":{"body":25,"breadcrumbs":3,"title":1},"704":{"body":58,"breadcrumbs":5,"title":3},"705":{"body":99,"breadcrumbs":7,"title":5},"706":{"body":116,"breadcrumbs":4,"title":2},"707":{"body":0,"breadcrumbs":5,"title":2},"708":{"body":79,"breadcrumbs":6,"title":3},"709":{"body":94,"breadcrumbs":7,"title":4},"71":{"body":21,"breadcrumbs":9,"title":5},"710":{"body":33,"breadcrumbs":8,"title":3},"711":{"body":57,"breadcrumbs":7,"title":2},"712":{"body":11,"breadcrumbs":8,"title":3},"713":{"body":70,"breadcrumbs":6,"title":1},"714":{"body":64,"breadcrumbs":6,"title":1},"715":{"body":40,"breadcrumbs":6,"title":1},"716":{"body":272,"breadcrumbs":8,"title":3},"717":{"body":174,"breadcrumbs":10,"title":5},"718":{"body":22,"breadcrumbs":9,"title":4},"719":{"body":43,"breadcrumbs":8,"title":3},"72":{"body":0,"breadcrumbs":6,"title":2},"720":{"body":34,"breadcrumbs":7,"title":2},"721":{"body":26,"breadcrumbs":8,"title":3},"722":{"body":27,"breadcrumbs":6,"title":2},"723":{"body":24,"breadcrumbs":7,"title":3},"724":{"body":14,"breadcrumbs":8,"title":4},"725":{"body":47,"breadcrumbs":6,"title":2},"726":{"body":17,"breadcrumbs":7,"title":3},"727":{"body":18,"breadcrumbs":8,"title":4},"728":{"body":39,"breadcrumbs":7,"title":3},"729":{"body":44,"breadcrumbs":7,"title":3},"73":{"body":35,"breadcrumbs":9,"title":5},"730":{"body":29,"breadcrumbs":8,"title":4},"731":{"body":11,"breadcrumbs":8,"title":4},"732":{"body":30,"breadcrumbs":7,"title":3},"733":{"body":44,"breadcrumbs":8,"title":4},"734":{"body":104,"breadcrumbs":9,"title":5},"735":{"body":10,"breadcrumbs":8,"title":4},"736":{"body":60,"breadcrumbs":8,"title":4},"737":{"body":136,"breadcrumbs":8,"title":3},"738":{"body":26,"breadcrumbs":8,"title":3},"739":{"body":13,"breadcrumbs":9,"title":4},"74":{"body":62,"breadcrumbs":12,"title":8},"740":{"body":186,"breadcrumbs":8,"title":3},"741":{"body":36,"breadcrumbs":7,"title":2},"742":{"body":91,"breadcrumbs":8,"title":3},"743":{"body":111,"breadcrumbs":7,"title":2},"744":{"body":32,"breadcrumbs":7,"title":2},"745":{"body":138,"breadcrumbs":7,"title":2},"746":{"body":102,"breadcrumbs":7,"title":2},"747":{"body":23,"breadcrumbs":7,"title":2},"748":{"body":32,"breadcrumbs":6,"title":1},"749":{"body":31,"breadcrumbs":10,"title":4},"75":{"body":0,"breadcrumbs":6,"title":2},"750":{"body":16,"breadcrumbs":7,"title":1},"751":{"body":7,"breadcrumbs":7,"title":1},"752":{"body":771,"breadcrumbs":7,"title":3},"753":{"body":196,"breadcrumbs":7,"title":3},"754":{"body":38,"breadcrumbs":7,"title":3},"755":{"body":64,"breadcrumbs":7,"title":3},"756":{"body":273,"breadcrumbs":7,"title":3},"757":{"body":77,"breadcrumbs":8,"title":4},"758":{"body":30,"breadcrumbs":7,"title":3},"759":{"body":46,"breadcrumbs":7,"title":3},"76":{"body":17,"breadcrumbs":9,"title":5},"760":{"body":47,"breadcrumbs":6,"title":2},"761":{"body":140,"breadcrumbs":7,"title":3},"762":{"body":82,"breadcrumbs":8,"title":4},"763":{"body":213,"breadcrumbs":8,"title":4},"764":{"body":26,"breadcrumbs":7,"title":3},"765":{"body":56,"breadcrumbs":6,"title":2},"766":{"body":35,"breadcrumbs":6,"title":2},"767":{"body":119,"breadcrumbs":5,"title":1},"768":{"body":160,"breadcrumbs":7,"title":3},"769":{"body":30,"breadcrumbs":8,"title":4},"77":{"body":0,"breadcrumbs":6,"title":2},"770":{"body":17,"breadcrumbs":8,"title":4},"771":{"body":20,"breadcrumbs":7,"title":3},"772":{"body":36,"breadcrumbs":7,"title":3},"773":{"body":167,"breadcrumbs":7,"title":3},"774":{"body":78,"breadcrumbs":7,"title":2},"775":{"body":268,"breadcrumbs":8,"title":4},"776":{"body":82,"breadcrumbs":8,"title":4},"777":{"body":10,"breadcrumbs":7,"title":3},"778":{"body":85,"breadcrumbs":7,"title":3},"779":{"body":350,"breadcrumbs":7,"title":3},"78":{"body":14,"breadcrumbs":8,"title":4},"780":{"body":0,"breadcrumbs":6,"title":2},"781":{"body":504,"breadcrumbs":7,"title":3},"782":{"body":38,"breadcrumbs":7,"title":3},"783":{"body":41,"breadcrumbs":8,"title":4},"784":{"body":175,"breadcrumbs":6,"title":2},"785":{"body":35,"breadcrumbs":6,"title":2},"786":{"body":32,"breadcrumbs":6,"title":2},"787":{"body":15,"breadcrumbs":8,"title":4},"788":{"body":16,"breadcrumbs":9,"title":5},"789":{"body":55,"breadcrumbs":8,"title":4},"79":{"body":59,"breadcrumbs":9,"title":5},"790":{"body":64,"breadcrumbs":8,"title":4},"791":{"body":67,"breadcrumbs":11,"title":7},"792":{"body":92,"breadcrumbs":6,"title":2},"793":{"body":0,"breadcrumbs":6,"title":2},"794":{"body":399,"breadcrumbs":8,"title":4},"795":{"body":111,"breadcrumbs":8,"title":4},"796":{"body":83,"breadcrumbs":6,"title":2},"797":{"body":85,"breadcrumbs":14,"title":10},"798":{"body":0,"breadcrumbs":6,"title":2},"799":{"body":137,"breadcrumbs":6,"title":2},"8":{"body":798,"breadcrumbs":5,"title":4},"80":{"body":0,"breadcrumbs":6,"title":2},"800":{"body":39,"breadcrumbs":6,"title":2},"801":{"body":40,"breadcrumbs":7,"title":3},"802":{"body":104,"breadcrumbs":6,"title":2},"803":{"body":43,"breadcrumbs":6,"title":2},"804":{"body":29,"breadcrumbs":6,"title":2},"805":{"body":158,"breadcrumbs":6,"title":2},"806":{"body":98,"breadcrumbs":9,"title":5},"807":{"body":12,"breadcrumbs":7,"title":3},"808":{"body":56,"breadcrumbs":6,"title":2},"809":{"body":76,"breadcrumbs":6,"title":2},"81":{"body":37,"breadcrumbs":8,"title":4},"810":{"body":20,"breadcrumbs":6,"title":2},"811":{"body":28,"breadcrumbs":7,"title":3},"812":{"body":73,"breadcrumbs":10,"title":6},"813":{"body":59,"breadcrumbs":12,"title":8},"814":{"body":148,"breadcrumbs":7,"title":3},"815":{"body":76,"breadcrumbs":8,"title":4},"816":{"body":35,"breadcrumbs":7,"title":2},"817":{"body":14,"breadcrumbs":6,"title":2},"818":{"body":277,"breadcrumbs":6,"title":2},"819":{"body":42,"breadcrumbs":7,"title":3},"82":{"body":0,"breadcrumbs":6,"title":2},"820":{"body":127,"breadcrumbs":6,"title":2},"821":{"body":84,"breadcrumbs":7,"title":3},"822":{"body":33,"breadcrumbs":5,"title":3},"823":{"body":95,"breadcrumbs":4,"title":2},"824":{"body":40,"breadcrumbs":4,"title":2},"825":{"body":64,"breadcrumbs":5,"title":3},"826":{"body":200,"breadcrumbs":7,"title":5},"827":{"body":117,"breadcrumbs":4,"title":2},"828":{"body":142,"breadcrumbs":8,"title":6},"829":{"body":44,"breadcrumbs":11,"title":9},"83":{"body":18,"breadcrumbs":11,"title":7},"830":{"body":101,"breadcrumbs":7,"title":5},"831":{"body":62,"breadcrumbs":5,"title":3},"832":{"body":58,"breadcrumbs":10,"title":4},"833":{"body":413,"breadcrumbs":8,"title":2},"834":{"body":37,"breadcrumbs":11,"title":5},"835":{"body":47,"breadcrumbs":7,"title":3},"836":{"body":136,"breadcrumbs":7,"title":3},"837":{"body":57,"breadcrumbs":6,"title":2},"838":{"body":75,"breadcrumbs":10,"title":6},"839":{"body":56,"breadcrumbs":5,"title":1},"84":{"body":0,"breadcrumbs":6,"title":2},"840":{"body":59,"breadcrumbs":11,"title":5},"841":{"body":19,"breadcrumbs":10,"title":4},"842":{"body":87,"breadcrumbs":10,"title":4},"843":{"body":74,"breadcrumbs":7,"title":1},"844":{"body":85,"breadcrumbs":7,"title":1},"845":{"body":54,"breadcrumbs":8,"title":2},"846":{"body":29,"breadcrumbs":8,"title":2},"847":{"body":30,"breadcrumbs":8,"title":2},"848":{"body":0,"breadcrumbs":9,"title":5},"849":{"body":4,"breadcrumbs":8,"title":4},"85":{"body":16,"breadcrumbs":8,"title":4},"850":{"body":5,"breadcrumbs":6,"title":2},"851":{"body":21,"breadcrumbs":11,"title":7},"852":{"body":40,"breadcrumbs":6,"title":2},"853":{"body":25,"breadcrumbs":11,"title":7},"854":{"body":60,"breadcrumbs":6,"title":2},"855":{"body":65,"breadcrumbs":12,"title":8},"856":{"body":28,"breadcrumbs":14,"title":10},"857":{"body":30,"breadcrumbs":14,"title":10},"858":{"body":30,"breadcrumbs":12,"title":8},"859":{"body":50,"breadcrumbs":10,"title":6},"86":{"body":0,"breadcrumbs":6,"title":2},"860":{"body":31,"breadcrumbs":6,"title":2},"861":{"body":25,"breadcrumbs":10,"title":6},"862":{"body":15,"breadcrumbs":8,"title":4},"863":{"body":24,"breadcrumbs":10,"title":6},"864":{"body":21,"breadcrumbs":11,"title":7},"865":{"body":12,"breadcrumbs":8,"title":4},"866":{"body":6,"breadcrumbs":8,"title":4},"867":{"body":13,"breadcrumbs":7,"title":3},"868":{"body":5,"breadcrumbs":7,"title":3},"869":{"body":7,"breadcrumbs":10,"title":6},"87":{"body":16,"breadcrumbs":8,"title":4},"870":{"body":172,"breadcrumbs":6,"title":3},"871":{"body":15,"breadcrumbs":7,"title":4},"872":{"body":22,"breadcrumbs":5,"title":2},"873":{"body":252,"breadcrumbs":7,"title":3},"874":{"body":0,"breadcrumbs":5,"title":2},"875":{"body":44,"breadcrumbs":6,"title":3},"876":{"body":6,"breadcrumbs":6,"title":3},"877":{"body":13,"breadcrumbs":7,"title":4},"878":{"body":3,"breadcrumbs":6,"title":3},"879":{"body":193,"breadcrumbs":6,"title":3},"88":{"body":0,"breadcrumbs":6,"title":2},"880":{"body":4,"breadcrumbs":9,"title":6},"881":{"body":14,"breadcrumbs":6,"title":3},"882":{"body":95,"breadcrumbs":9,"title":6},"883":{"body":39,"breadcrumbs":12,"title":9},"884":{"body":91,"breadcrumbs":11,"title":8},"885":{"body":4,"breadcrumbs":8,"title":5},"886":{"body":25,"breadcrumbs":6,"title":3},"887":{"body":57,"breadcrumbs":8,"title":5},"888":{"body":224,"breadcrumbs":8,"title":5},"889":{"body":136,"breadcrumbs":7,"title":4},"89":{"body":16,"breadcrumbs":8,"title":4},"890":{"body":5,"breadcrumbs":3,"title":1},"891":{"body":39,"breadcrumbs":5,"title":3},"892":{"body":131,"breadcrumbs":4,"title":2},"893":{"body":41,"breadcrumbs":4,"title":2},"894":{"body":100,"breadcrumbs":5,"title":3},"895":{"body":75,"breadcrumbs":6,"title":4},"896":{"body":6,"breadcrumbs":4,"title":2},"897":{"body":9,"breadcrumbs":5,"title":3},"898":{"body":99,"breadcrumbs":7,"title":5},"899":{"body":9,"breadcrumbs":6,"title":4},"9":{"body":6,"breadcrumbs":4,"title":3},"90":{"body":0,"breadcrumbs":6,"title":2},"900":{"body":69,"breadcrumbs":4,"title":2},"901":{"body":165,"breadcrumbs":7,"title":5},"902":{"body":195,"breadcrumbs":6,"title":4},"903":{"body":82,"breadcrumbs":6,"title":4},"904":{"body":184,"breadcrumbs":6,"title":4},"905":{"body":32,"breadcrumbs":5,"title":3},"906":{"body":72,"breadcrumbs":8,"title":6},"907":{"body":56,"breadcrumbs":5,"title":3},"908":{"body":119,"breadcrumbs":3,"title":1},"909":{"body":61,"breadcrumbs":9,"title":7},"91":{"body":50,"breadcrumbs":12,"title":8},"910":{"body":74,"breadcrumbs":4,"title":2},"911":{"body":49,"breadcrumbs":3,"title":1},"912":{"body":106,"breadcrumbs":7,"title":5},"913":{"body":3,"breadcrumbs":6,"title":4},"914":{"body":8,"breadcrumbs":7,"title":5},"915":{"body":31,"breadcrumbs":3,"title":1},"916":{"body":0,"breadcrumbs":4,"title":2},"917":{"body":66,"breadcrumbs":4,"title":2},"918":{"body":70,"breadcrumbs":4,"title":2},"919":{"body":114,"breadcrumbs":6,"title":4},"92":{"body":0,"breadcrumbs":6,"title":2},"920":{"body":52,"breadcrumbs":3,"title":1},"921":{"body":116,"breadcrumbs":4,"title":2},"922":{"body":63,"breadcrumbs":4,"title":2},"923":{"body":61,"breadcrumbs":5,"title":3},"924":{"body":18,"breadcrumbs":4,"title":2},"925":{"body":67,"breadcrumbs":4,"title":2},"926":{"body":0,"breadcrumbs":5,"title":3},"927":{"body":195,"breadcrumbs":6,"title":4},"928":{"body":157,"breadcrumbs":6,"title":4},"929":{"body":200,"breadcrumbs":5,"title":3},"93":{"body":21,"breadcrumbs":9,"title":5},"930":{"body":91,"breadcrumbs":6,"title":3},"931":{"body":46,"breadcrumbs":6,"title":3},"932":{"body":0,"breadcrumbs":2,"title":1},"933":{"body":144,"breadcrumbs":2,"title":1},"934":{"body":55,"breadcrumbs":4,"title":3},"935":{"body":29,"breadcrumbs":4,"title":3},"936":{"body":76,"breadcrumbs":3,"title":2},"937":{"body":5,"breadcrumbs":3,"title":2},"938":{"body":6,"breadcrumbs":6,"title":4},"939":{"body":48,"breadcrumbs":4,"title":2},"94":{"body":0,"breadcrumbs":6,"title":2},"940":{"body":189,"breadcrumbs":5,"title":3},"941":{"body":16,"breadcrumbs":5,"title":3},"942":{"body":40,"breadcrumbs":6,"title":4},"943":{"body":54,"breadcrumbs":4,"title":2},"944":{"body":38,"breadcrumbs":5,"title":3},"945":{"body":62,"breadcrumbs":5,"title":3},"946":{"body":160,"breadcrumbs":4,"title":2},"947":{"body":30,"breadcrumbs":4,"title":2},"948":{"body":97,"breadcrumbs":5,"title":3},"949":{"body":73,"breadcrumbs":6,"title":4},"95":{"body":29,"breadcrumbs":8,"title":4},"950":{"body":550,"breadcrumbs":8,"title":6},"951":{"body":154,"breadcrumbs":6,"title":4},"952":{"body":6,"breadcrumbs":5,"title":3},"953":{"body":17,"breadcrumbs":3,"title":1},"954":{"body":102,"breadcrumbs":3,"title":1},"955":{"body":155,"breadcrumbs":4,"title":2},"956":{"body":90,"breadcrumbs":5,"title":3},"957":{"body":0,"breadcrumbs":2,"title":0},"958":{"body":4,"breadcrumbs":6,"title":4},"959":{"body":120,"breadcrumbs":7,"title":5},"96":{"body":42,"breadcrumbs":7,"title":3},"960":{"body":64,"breadcrumbs":6,"title":4},"961":{"body":40,"breadcrumbs":5,"title":3},"962":{"body":24,"breadcrumbs":5,"title":3},"963":{"body":19,"breadcrumbs":4,"title":2},"964":{"body":12,"breadcrumbs":7,"title":5},"965":{"body":58,"breadcrumbs":6,"title":4},"966":{"body":11,"breadcrumbs":5,"title":3},"967":{"body":24,"breadcrumbs":5,"title":3},"968":{"body":53,"breadcrumbs":6,"title":4},"969":{"body":0,"breadcrumbs":3,"title":1},"97":{"body":0,"breadcrumbs":6,"title":2},"970":{"body":24,"breadcrumbs":7,"title":5},"971":{"body":29,"breadcrumbs":8,"title":6},"972":{"body":16,"breadcrumbs":6,"title":4},"973":{"body":6,"breadcrumbs":7,"title":5},"974":{"body":46,"breadcrumbs":4,"title":1},"975":{"body":37,"breadcrumbs":6,"title":3},"976":{"body":31,"breadcrumbs":4,"title":1},"977":{"body":74,"breadcrumbs":4,"title":1},"978":{"body":12,"breadcrumbs":4,"title":1},"979":{"body":62,"breadcrumbs":6,"title":3},"98":{"body":16,"breadcrumbs":8,"title":4},"980":{"body":65,"breadcrumbs":6,"title":3},"981":{"body":121,"breadcrumbs":4,"title":1},"982":{"body":110,"breadcrumbs":5,"title":2},"983":{"body":145,"breadcrumbs":5,"title":2},"984":{"body":82,"breadcrumbs":6,"title":2},"985":{"body":59,"breadcrumbs":8,"title":4},"986":{"body":195,"breadcrumbs":7,"title":3},"987":{"body":104,"breadcrumbs":7,"title":3},"988":{"body":63,"breadcrumbs":10,"title":6},"989":{"body":215,"breadcrumbs":6,"title":2},"99":{"body":0,"breadcrumbs":6,"title":2},"990":{"body":113,"breadcrumbs":10,"title":6},"991":{"body":163,"breadcrumbs":9,"title":5},"992":{"body":0,"breadcrumbs":5,"title":2},"993":{"body":111,"breadcrumbs":4,"title":1},"994":{"body":0,"breadcrumbs":4,"title":1},"995":{"body":4,"breadcrumbs":5,"title":2},"996":{"body":10,"breadcrumbs":6,"title":3},"997":{"body":75,"breadcrumbs":4,"title":1},"998":{"body":157,"breadcrumbs":4,"title":1},"999":{"body":227,"breadcrumbs":6,"title":3}},"docs":{"0":{"body":"Welcome to the documentation repository for Synapse, a Matrix homeserver implementation developed by Element.","breadcrumbs":"Welcome and Overview » Introduction","id":"0","title":"Introduction"},"1":{"body":"This documentation covers topics for installation , configuration and maintenance of your Synapse process: Learn how to install and configure your own instance, perhaps with Single Sign-On . See how to upgrade between Synapse versions. Administer your instance using the Admin API , installing pluggable modules , or by accessing the manhole . Learn how to read log lines , configure logging or set up structured logging . Scale Synapse through additional worker processes . Set up monitoring and metrics to keep an eye on your Synapse instance's performance.","breadcrumbs":"Welcome and Overview » Installing and using Synapse","id":"1","title":"Installing and using Synapse"},"10":{"body":"By default Synapse uses an SQLite database and in doing so trades performance for convenience. Almost all installations should opt to use PostgreSQL instead. Advantages include: significant performance improvements due to the superior threading and caching model, smarter query optimiser allowing the DB to be run on separate hardware For information on how to install and use PostgreSQL in Synapse, please see Using Postgres SQLite is only acceptable for testing purposes. SQLite should not be used in a production server. Synapse will perform poorly when using SQLite, especially when participating in large rooms.","breadcrumbs":"Installation » Using PostgreSQL","id":"10","title":"Using PostgreSQL"},"100":{"body":"Application services should ensure they call the /register endpoint with a username property. The legacy user property is considered deprecated and should no longer be included. A future version of Synapse (v1.88.0 or later) will remove support for legacy application service login.","breadcrumbs":"Upgrading between Synapse Versions » Application service registration with \"user\" property deprecation","id":"100","title":"Application service registration with \"user\" property deprecation"},"1000":{"body":"There are two ways to view a multi-writer stream. Treat it as a collection of distinct single-writer streams, one for each writer. Treat it as a single stream. The single stream (option 2) is conceptually simpler, and easier to represent (a single stream id). However, it requires each reader to know about the entire set of writers, to ensures that readers don't erroneously advance their current stream position too early and miss a fact from an unknown writer. In contrast, multiple parallel streams (option 1) are more complex, requiring more state to represent (map from writer to stream id). The payoff for doing so is that readers can \"peek\" ahead to facts that completed on one writer no matter the state of the others, reducing latency. Note that a multi-writer stream can be viewed in both ways. For example, the events stream is treated as multiple single-writer streams (option 1) by the sync handler, so that events are sent to clients as soon as possible. But the background process that works through events treats them as a single linear stream. Another useful example is the cache invalidation stream. The facts this stream holds are instructions to \"you should now invalidate these cache entries\". We only ever treat this as a multiple single-writer streams as there is no important ordering between cache invalidations. (Invalidations are self-contained facts; and the invalidations commute/are idempotent).","breadcrumbs":"Synapse Architecture » Streams » Multi-writer streams","id":"1000","title":"Multi-writer streams"},"1001":{"body":"Writers need to track: track their current position (i.e. its own per-writer stream ID). their facts currently awaiting completion. At startup, the current position of that writer can be found by querying the database (which suggests that facts need to be written to the database atomically, in a transaction); and there are no facts awaiting completion. To reserve a stream ID, call nextval on the appropriate postgres sequence. To write a fact to the stream: insert the appropriate rows to the appropriate backing table. To complete a fact, first remove it from your map of facts currently awaiting completion. Then, if no earlier fact is awaiting completion, the writer can advance its current position in that stream. Upon doing so it should emit an RDATA message [3] , once for every fact between the old and the new stream ID.","breadcrumbs":"Synapse Architecture » Streams » Writing to streams","id":"1001","title":"Writing to streams"},"1002":{"body":"Readers need to track the current position of every writer. At startup, they can find this by contacting each writer with a REPLICATE message, requesting that all writers reply describing their current position in their streams. Writers reply with a POSITION message. To learn about new facts, readers should listen for RDATA messages and process them to respond to the new fact. The RDATA itself is not a self-contained representation of the fact; readers will have to query the stream tables for the full details. Readers must also advance their record of the writer's current position for that stream.","breadcrumbs":"Synapse Architecture » Streams » Subscribing to streams","id":"1002","title":"Subscribing to streams"},"1003":{"body":"In a nutshell: we have an append-only log with a \"buffer/scratchpad\" at the end where we have to wait for the sequence to be linear and contiguous. we use the word fact here for two reasons. Firstly, the word \"event\" is already heavily overloaded (PDUs, EDUs, account data, ...) and we don't need to make that worse. Secondly, \"fact\" emphasises that the things we append to a stream cannot change after the fact. A fact might be expressed with 0 rows, e.g. if we opened a transaction to persist an event, but failed and rolled the transaction back before marking the fact as completed. In principle a fact might be expressed with 2 or more rows; if so, each of those rows should share the fact's stream ID. This communication used to happen directly with the writers over TCP ; nowadays it's done via Redis's Pubsub.","breadcrumbs":"Synapse Architecture » Streams » Summary","id":"1003","title":"Summary"},"1004":{"body":"","breadcrumbs":"Synapse Architecture » TCP Replication » TCP Replication","id":"1004","title":"TCP Replication"},"1005":{"body":"Previously the workers used an HTTP long poll mechanism to get updates from the master, which had the problem of causing a lot of duplicate work on the server. This TCP protocol replaces those APIs with the aim of increased efficiency.","breadcrumbs":"Synapse Architecture » TCP Replication » Motivation","id":"1005","title":"Motivation"},"1006":{"body":"The protocol is based on fire and forget, line based commands. An example flow would be (where '>' indicates master to worker and '<' worker to master flows): > SERVER example.com\n< REPLICATE\n> POSITION events master 53 53\n> RDATA events master 54 [\"$foo1:bar.com\", ...]\n> RDATA events master 55 [\"$foo4:bar.com\", ...] The example shows the server accepting a new connection and sending its identity with the SERVER command, followed by the client server to respond with the position of all streams. The server then periodically sends RDATA commands which have the format RDATA , where the format of is defined by the individual streams. The is the name of the Synapse process that generated the data (usually \"master\"). We expect an RDATA for every row in the DB. Error reporting happens by either the client or server sending an ERROR command, and usually the connection will be closed. Since the protocol is a simple line based, its possible to manually connect to the server using a tool like netcat. A few things should be noted when manually using the protocol: The federation stream is only available if federation sending has been disabled on the main process. The server will only time connections out that have sent a PING command. If a ping is sent then the connection will be closed if no further commands are received within 15s. Both the client and server protocol implementations will send an initial PING on connection and ensure at least one command every 5s is sent (not necessarily PING). RDATA commands usually include a numeric token, however if the stream has multiple rows to replicate per token the server will send multiple RDATA commands, with all but the last having a token of batch. See the documentation on commands.RdataCommand for further details.","breadcrumbs":"Synapse Architecture » TCP Replication » Overview","id":"1006","title":"Overview"},"1007":{"body":"The basic structure of the protocol is line based, where the initial word of each line specifies the command. The rest of the line is parsed based on the command. For example, the RDATA command is defined as: RDATA (Note that may contains spaces, but cannot contain newlines.) Blank lines are ignored.","breadcrumbs":"Synapse Architecture » TCP Replication » Architecture","id":"1007","title":"Architecture"},"1008":{"body":"Both sides are expected to send at least one command every 5s or so, and should send a PING command if necessary. If either side do not receive a command within e.g. 15s then the connection should be closed. Because the server may be connected to manually using e.g. netcat, the timeouts aren't enabled until an initial PING command is seen. Both the client and server implementations below send a PING command immediately on connection to ensure the timeouts are enabled. This ensures that both sides can quickly realize if the tcp connection has gone and handle the situation appropriately.","breadcrumbs":"Synapse Architecture » TCP Replication » Keep alives","id":"1008","title":"Keep alives"},"1009":{"body":"When a new connection is made, the server: Sends a SERVER command, which includes the identity of the server, allowing the client to detect if its connected to the expected server Sends a PING command as above, to enable the client to time out connections promptly. The client: Sends a NAME command, allowing the server to associate a human friendly name with the connection. This is optional. Sends a PING as above Sends a REPLICATE to get the current position of all streams. On receipt of a SERVER command, checks that the server name matches the expected server name.","breadcrumbs":"Synapse Architecture » TCP Replication » Start up","id":"1009","title":"Start up"},"101":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.84.0","id":"101","title":"Upgrading to v1.84.0"},"1010":{"body":"If either side detects an error it can send an ERROR command and close the connection. If the client side loses the connection to the server it should reconnect, following the steps above.","breadcrumbs":"Synapse Architecture » TCP Replication » Error handling","id":"1010","title":"Error handling"},"1011":{"body":"If the server sends messages faster than the client can consume them the server will first buffer a (fairly large) number of commands and then disconnect the client. This ensures that we don't queue up an unbounded number of commands in memory and gives us a potential opportunity to squawk loudly. When/if the client recovers it can reconnect to the server and ask for missed messages.","breadcrumbs":"Synapse Architecture » TCP Replication » Congestion","id":"1011","title":"Congestion"},"1012":{"body":"In general the replication stream should be considered an unreliable transport since e.g. commands are not resent if the connection disappears. The exception to that are the replication streams, i.e. RDATA commands, since these include tokens which can be used to restart the stream on connection errors. The client should keep track of the token in the last RDATA command received for each stream so that on reconnection it can start streaming from the correct place. Note: not all RDATA have valid tokens due to batching. See RdataCommand for more details.","breadcrumbs":"Synapse Architecture » TCP Replication » Reliability","id":"1012","title":"Reliability"},"1013":{"body":"An example interaction is shown below. Each line is prefixed with '>' or '<' to indicate which side is sending, these are not included on the wire: * connection established *\n> SERVER localhost:8823\n> PING 1490197665618\n< NAME synapse.app.appservice\n< PING 1490197665618\n< REPLICATE\n> POSITION events master 1 1\n> POSITION backfill master 1 1\n> POSITION caches master 1 1\n> RDATA caches master 2 [\"get_user_by_id\",[\"@01register-user:localhost:8823\"],1490197670513]\n> RDATA events master 14 [\"$149019767112vOHxz:localhost:8823\", \"!AFDCvgApUmpdfVjIXm:localhost:8823\",\"m.room.guest_access\",\"\",null]\n< PING 1490197675618\n> ERROR server stopping\n* connection closed by server * The POSITION command sent by the server is used to set the clients position without needing to send data with the RDATA command. An example of a batched set of RDATA is: > RDATA caches master batch [\"get_user_by_id\",[\"@test:localhost:8823\"],1490197670513]\n> RDATA caches master batch [\"get_user_by_id\",[\"@test2:localhost:8823\"],1490197670513]\n> RDATA caches master batch [\"get_user_by_id\",[\"@test3:localhost:8823\"],1490197670513]\n> RDATA caches master 54 [\"get_user_by_id\",[\"@test4:localhost:8823\"],1490197670513] In this case the client shouldn't advance their caches token until it sees the the last RDATA.","breadcrumbs":"Synapse Architecture » TCP Replication » Example","id":"1013","title":"Example"},"1014":{"body":"The list of valid commands, with which side can send it: server (S) or client (C): SERVER (S) Sent at the start to identify which server the client is talking to RDATA (S) A single update in a stream POSITION (S) On receipt of a POSITION command clients should check if they have missed any updates, and if so then fetch them out of band. Sent in response to a REPLICATE command (but can happen at any time). The POSITION command includes the source of the stream. Currently all streams are written by a single process (usually \"master\"). If fetching missing updates via HTTP API, rather than via the DB, then processes should make the request to the appropriate process. Two positions are included, the \"new\" position and the last position sent respectively. This allows servers to tell instances that the positions have advanced but no data has been written, without clients needlessly checking to see if they have missed any updates. Instances will only fetch stuff if there is a gap between their current position and the given last position. ERROR (S, C) There was an error PING (S, C) Sent periodically to ensure the connection is still alive NAME (C) Sent at the start by client to inform the server who they are REPLICATE (C) Asks the server for the current position of all streams. USER_SYNC (C) A user has started or stopped syncing on this process. CLEAR_USER_SYNC (C) The server should clear all associated user sync data from the worker. This is used when a worker is shutting down. FEDERATION_ACK (C) Acknowledge receipt of some federation data","breadcrumbs":"Synapse Architecture » TCP Replication » List of commands","id":"1014","title":"List of commands"},"1015":{"body":"Inform other processes that a remote server may have come back online. See synapse/replication/tcp/commands.py for a detailed description and the format of each command.","breadcrumbs":"Synapse Architecture » TCP Replication » REMOTE_SERVER_UP (S, C)","id":"1015","title":"REMOTE_SERVER_UP (S, C)"},"1016":{"body":"The cache invalidation stream is used to inform workers when they need to invalidate any of their caches in the data store. This is done by streaming all cache invalidations done on master down to the workers, assuming that any caches on the workers also exist on the master. Each individual cache invalidation results in a row being sent down replication, which includes the cache name (the name of the function) and they key to invalidate. For example: > RDATA caches master 550953771 [\"get_user_by_id\", [\"@bob:example.com\"], 1550574873251] Alternatively, an entire cache can be invalidated by sending down a null instead of the key. For example: > RDATA caches master 550953772 [\"get_user_by_id\", null, 1550574873252] However, there are times when a number of caches need to be invalidated at the same time with the same key. To reduce traffic we batch those invalidations into a single poke by defining a special cache name that workers understand to mean to expand to invalidate the correct caches. Currently the special cache names are declared in synapse/storage/_base.py and are: cs_cache_fake ─ invalidates caches that depend on the current state","breadcrumbs":"Synapse Architecture » TCP Replication » Cache Invalidation Stream","id":"1016","title":"Cache Invalidation Stream"},"1017":{"body":"This is a work-in-progress set of notes with two goals: act as a reference, explaining how Synapse implements faster joins; and record the rationale behind our choices. See also MSC3902 . The key idea is described by MSC3706 . This allows servers to request a lightweight response to the federation /send_join endpoint. This is called a faster join , also known as a partial join . In these notes we'll usually use the word \"partial\" as it matches the database schema.","breadcrumbs":"Synapse Architecture » Faster remote joins » How do faster joins work?","id":"1017","title":"How do faster joins work?"},"1018":{"body":"The response to a partial join consists of the requested join event J, a list of the servers in the room (according to the state before J), a subset of the state of the room before J, the full auth chain of that state subset. Synapse marks the room as partially joined by adding a row to the database table partial_state_rooms. It also marks the join event J as \"partially stated\", meaning that we have neither received nor computed the full state before/after J. This is done by adding a row to partial_state_events. DB schema matrix=> \\d partial_state_events\nTable \"matrix.partial_state_events\" Column │ Type │ Collation │ Nullable │ Default\n══════════╪══════╪═══════════╪══════════╪═════════ room_id │ text │ │ not null │ event_id │ text │ │ not null │ matrix=> \\d partial_state_rooms Table \"matrix.partial_state_rooms\" Column │ Type │ Collation │ Nullable │ Default ════════════════════════╪════════╪═══════════╪══════════╪═════════ room_id │ text │ │ not null │ device_lists_stream_id │ bigint │ │ not null │ 0 join_event_id │ text │ │ │ joined_via │ text │ │ │ matrix=> \\d partial_state_rooms_servers Table \"matrix.partial_state_rooms_servers\" Column │ Type │ Collation │ Nullable │ Default ═════════════╪══════╪═══════════╪══════════╪═════════ room_id │ text │ │ not null │ server_name │ text │ │ not null │ Indices, foreign-keys and check constraints are omitted for brevity. While partially joined to a room, Synapse receives events E from remote homeservers as normal, and can create events at the request of its local users. However, we run into trouble when we enforce the checks on an event . Is a valid event, otherwise it is dropped. For an event to be valid, it must contain a room_id, and it must comply with the event format of that room version. Passes signature checks, otherwise it is dropped. Passes hash checks, otherwise it is redacted before being processed further. Passes authorization rules based on the event’s auth events, otherwise it is rejected. Passes authorization rules based on the state before the event, otherwise it is rejected. Passes authorization rules based on the current state of the room, otherwise it is “soft failed”. We can enforce checks 1--4 without any problems. But we cannot enforce checks 5 or 6 with complete certainty, since Synapse does not know the full state before E, nor that of the room.","breadcrumbs":"Synapse Architecture » Faster remote joins » Overview: processing events in a partially-joined room","id":"1018","title":"Overview: processing events in a partially-joined room"},"1019":{"body":"Instead, we make a best-effort approximation. While the room is considered partially joined, Synapse tracks the \"partial state\" before events. This works in a similar way as regular state: The partial state before J is that given to us by the partial join response. The partial state before an event E is the resolution of the partial states after each of E's prev_events. If E is rejected or a message event, the partial state after E is the partial state before E. Otherwise, the partial state after E is the partial state before E, plus E itself. More concisely, partial state propagates just like full state; the only difference is that we \"seed\" it with an incomplete initial state. Synapse records that we have only calculated partial state for this event with a row in partial_state_events. While the room remains partially stated, check 5 on incoming events to that room becomes: Passes authorization rules based on the resolution between the partial state before E and E's auth events. If the event fails to pass authorization rules, it is rejected. Additionally, check 6 is deleted: no soft-failures are enforced. While partially joined, the current partial state of the room is defined as the resolution across the partial states after all forward extremities in the room. Remark. Events with partial state are not considered outliers .","breadcrumbs":"Synapse Architecture » Faster remote joins » Partial state","id":"1019","title":"Partial state"},"102":{"body":"When using workers, worker_replication_host worker_replication_http_port worker_replication_http_tls should now be removed from individual worker YAML configurations and the main process should instead be added to the instance_map in the shared YAML configuration, using the name main. The old worker_replication_* settings are now considered deprecated and are expected to be removed in Synapse v1.88.0.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of worker_replication_* configuration settings","id":"102","title":"Deprecation of worker_replication_* configuration settings"},"1020":{"body":"Using partial state means the auth checks can fail in a few different ways [1] . Is this exhaustive? We may erroneously accept an incoming event in check 5 based on partial state when it would have been rejected based on full state, or vice versa. This means that an event could erroneously be added to the current partial state of the room when it would not be present in the full state of the room, or vice versa. Additionally, we may have skipped soft-failing an event that would have been soft-failed based on full state. (Note that the discrepancies described in the last two bullets are user-visible.) This means that we have to be very careful when we want to lookup pieces of room state in a partially-joined room. Our approximation of the state may be incorrect or missing. But we can make some educated guesses. If our partial state is likely to be correct, or the consequences of our partial state being incorrect are minor, then we proceed as normal, and let the resync process fix up any mistakes (see below). When is our partial state likely to be correct? It's more accurate the closer we are to the partial join event. (So we should ideally complete the resync as soon as possible.) Non-member events: we will have received them as part of the partial join response, if they were part of the room state at that point. We may incorrectly accept or reject updates to that state (at first because we lack remote membership information; later because of compounding errors), so these can become incorrect over time. Local members' memberships: we are the only ones who can create join and knock events for our users. We can't be completely confident in the correctness of bans, invites and kicks from other homeservers, but the resync process should correct any mistakes. Remote members' memberships: we did not receive these in the /send_join response, so we have essentially no idea if these are correct or not. In short, we deem it acceptable to trust the partial state for non-membership and local membership events. For remote membership events, we wait for the resync to complete, at which point we have the full state of the room and can proceed as normal.","breadcrumbs":"Synapse Architecture » Faster remote joins » Approximation error","id":"1020","title":"Approximation error"},"1021":{"body":"The partial-state approximation is only a temporary affair. In the background, synapse beings a \"resync\" process. This is a continuous loop, starting at the partial join event and proceeding downwards through the event graph. For each E seen in the room since partial join, Synapse will fetch the event ids in the state of the room before E, via /state_ids ; the event ids in the full auth chain of E, included in the /state_ids response; and any events from the previous two bullets that Synapse hasn't persisted, via `/state . This means Synapse has (or can compute) the full state before E, which allows Synapse to properly authorise or reject E. At this point ,the event is considered to have \"full state\" rather than \"partial state\". We record this by removing E from the partial_state_events table. [ TODO: Does Synapse persist a new state group for the full state before E, or do we alter the (partial-)state group in-place? Are state groups ever marked as partially-stated? ] This scheme means it is possible for us to have accepted and sent an event to clients, only to reject it during the resync. From a client's perspective, the effect is similar to a retroactive state change due to state resolution---i.e. a \"state reset\". [2] Clients should refresh caches to detect such a change. Rumour has it that sliding sync will fix this. When all events since the join J have been fully-stated, the room resync process is complete. We record this by removing the room from partial_state_rooms.","breadcrumbs":"Synapse Architecture » Faster remote joins » Fixing the approximation with a resync","id":"1021","title":"Fixing the approximation with a resync"},"1022":{"body":"For the time being, the resync process happens on the master worker. A new replication stream un_partial_stated_room is added. Whenever a resync completes and a partial-state room becomes fully stated, a new message is sent into that stream containing the room ID.","breadcrumbs":"Synapse Architecture » Faster remote joins » Faster joins on workers","id":"1022","title":"Faster joins on workers"},"1023":{"body":"NB. The notes below are rough. Some of them are hidden under disclosures because they have yet to be implemented in mainline Synapse.","breadcrumbs":"Synapse Architecture » Faster remote joins » Notes on specific cases","id":"1023","title":"Notes on specific cases"},"1024":{"body":"When sending out messages during a partial join, we assume our partial state is accurate and proceed as normal. For this to have any hope of succeeding at all, our partial state must contain an entry for each of the (type, state key) pairs specified by the auth rules : m.room.create m.room.join_rules m.room.power_levels m.room.third_party_invite m.room.member The first four of these should be present in the state before J that is given to us in the partial join response; only membership events are omitted. In order for us to consider the user joined, we must have their membership event. That means the only possible omission is the target's membership in an invite, kick or ban. The worst possibility is that we locally invite someone who is banned according to the full state, because we lack their ban in our current partial state. The rest of the federation---at least, those who are fully joined---should correctly enforce the membership transition constraints . So any the erroneous invite should be ignored by fully-joined homeservers and resolved by the resync for partially-joined homeservers. In more generality, there are two problems we're worrying about here: We might create an event that is valid under our partial state, only to later find out that is actually invalid according to the full state. Or: we might refuse to create an event that is invalid under our partial state, even though it would be perfectly valid under the full state. However we expect such problems to be unlikely in practise, because We trust that the room has sensible power levels, e.g. that bad actors with high power levels are demoted before their ban. We trust that the resident server provides us up-to-date power levels, join rules, etc. State changes in rooms are relatively infrequent, and the resync period is relatively quick. Sending out the event over federation TODO: needs prose fleshing out. Normally: send out in a fed txn to all HSes in the room. We only know that some HSes were in the room at some point. Wat do. Send it out to the list of servers from the first join. TODO what do we do here if we have full state? If the prev event was created by us, we can risk sending it to the wrong HS. (Motivation: privacy concern of the content. Not such a big deal for a public room or an encrypted room. But non-encrypted invite-only...) But don't want to send out sensitive data in other HS's events in this way. Suppose we discover after resync that we shouldn't have sent out one our events (not a prev_event) to a target HS. Not much we can do. What about if we didn't send them an event but shouldn't've? E.g. what if someone joined from a new HS shortly after you did? We wouldn't talk to them. Could imagine sending out the \"Missed\" events after the resync but... painful to work out what they should have seen if they joined/left. Instead, just send them the latest event (if they're still in the room after resync) and let them backfill.(?) Don't do this currently. If anyone who has received our messages sends a message to a HS we missed, they can backfill our messages Gap: rooms which are infrequently used and take a long time to resync.","breadcrumbs":"Synapse Architecture » Faster remote joins » Creating events during a partial join","id":"1024","title":"Creating events during a partial join"},"1025":{"body":"NB. Not yet implemented. TODO: needs prose fleshing out. Liase with Matthieu. Explain why /send_join (Rich was surprised we didn't just create it locally. Answer: to try and avoid a join which then gets rejected after resync.) We don't know for sure that any join we create would be accepted. E.g. the joined user might have been banned; the join rules might have changed in a way that we didn't realise... some way in which the partial state was mistaken. Instead, do another partial make-join/send-join handshake to confirm that the join works. Probably going to get a bunch of duplicate state events and auth events.... but the point of partial joins is that these should be small. Many are already persisted = good. What if the second send_join response includes a different list of reisdent HSes? Could ignore it. Could even have a special flag that says \"just make me a join\", i.e. don't bother giving me state or servers in room. Deffo want the auth chain tho. SQ: wrt device lists it's a lot safer to ignore it!!!!! What if the state at the second join is inconsistent with what we have? Ignore it?","breadcrumbs":"Synapse Architecture » Faster remote joins » Joining after a partial join","id":"1025","title":"Joining after a partial join"},"1026":{"body":"NB. Not yet implemented. When you're fully joined to a room, to have U leave a room their homeserver needs to create a new leave event for U which will be accepted by other homeservers, and send that event U out to the homeservers in the federation. When is a leave event accepted? See v10 auth rules : If type is m.room.member: [...] > > 5. If membership is leave: > > 1. If the sender matches state_key, allow if and only if that user’s current membership state is invite, join, or knock. 2. [...] I think this means that (well-formed!) self-leaves are governed entirely by 4.5.1. This means that if we correctly calculate state which says that U is invited, joined or knocked and include it in the leave's auth events, our event is accepted by checks 4 and 5 on incoming events. Passes authorization rules based on the event’s auth events, otherwise > it is rejected. Passes authorization rules based on the state before the event, otherwise > it is rejected. The only way to fail check 6 is if the receiving server's current state of the room says that U is banned, has left, or has no membership event. But this is fine: the receiving server already thinks that U isn't in the room. Passes authorization rules based on the current state of the room, > otherwise it is “soft failed”. For the second point (publishing the leave event), the best thing we can do is to is publish to all HSes we know to be currently in the room. If they miss that event, they might send us traffic in the room that we don't care about. This is a problem with leaving after a \"full\" join; we don't seek to fix this with partial joins. (With that said: there's nothing machine-readable in the /send response. I don't think we can deduce \"destination has left the room\" from a failure to /send an event into that room?) Can we still do this during a partial join? We can create leave events and can choose what gets included in our auth events, so we can be sure that we pass check 4 on incoming events. For check 5, we might have an incorrect view of the state before an event. The only way we might erroneously think a leave is valid is if the partial state before the leave has U joined, invited or knocked, but the full state before the leave has U banned, left or not present, in which case the leave doesn't make anything worse: other HSes already consider us as not in the room, and will continue to do so after seeing the leave. The remaining obstacle is then: can we safely broadcast the leave event? We may miss servers or incorrectly think that a server is in the room. Or the destination server may be offline and miss the transaction containing our leave event.This should self-heal when they see an event whose prev_events descends from our leave. Another option we considered was to use federation /send_leave to ask a fully-joined server to send out the event on our behalf. But that introduces complexity without much benefit. Besides, as Rich put it, sending out leaves is pretty best-effort currently so this is probably good enough as-is. Cleanup after the last leave TODO : what cleanup is necessary? Is it all just nice-to-have to save unused work?","breadcrumbs":"Synapse Architecture » Faster remote joins » Leaving (and kicks and bans) after a partial join","id":"1026","title":"Leaving (and kicks and bans) after a partial join"},"1027":{"body":"This section covers implementation documentation for various parts of Synapse. If a developer is planning to make a change to a feature of Synapse, it can be useful for general documentation of how that feature is implemented to be available. This saves the developer time in place of needing to understand how the feature works by reading the code. Documentation that would be more useful for the perspective of a system administrator, rather than a developer who's intending to change to code, should instead be placed under the Usage section of the documentation.","breadcrumbs":"Internal Documentation » Internal Documentation","id":"1027","title":"Internal Documentation"},"1028":{"body":"https://fujifish.github.io/samling/samling.html (https://github.com/fujifish/samling) is a great resource for being able to tinker with the SAML options within Synapse without needing to deploy and configure a complicated software stack. To make Synapse (and therefore Element) use it: Use the samling.html URL above or deploy your own and visit the IdP Metadata tab. Copy the XML to your clipboard. On your Synapse server, create a new file samling.xml next to your homeserver.yaml with the XML from step 2 as the contents. Edit your homeserver.yaml to include: saml2_config: sp_config: allow_unknown_attributes: true # Works around a bug with AVA Hashes: https://github.com/IdentityPython/pysaml2/issues/388 metadata: local: [\"samling.xml\"] Ensure that your homeserver.yaml has a setting for public_baseurl: public_baseurl: http://localhost:8080/ Run apt-get install xmlsec1 and pip install --upgrade --force 'pysaml2>=4.5.0' to ensure the dependencies are installed and ready to go. Restart Synapse. Then in Element: Visit the login page and point Element towards your homeserver using the public_baseurl above. Click the Single Sign-On button. On the samling page, enter a Name Identifier and add a SAML Attribute for uid=your_localpart. The response must also be signed. Click \"Next\". Click \"Post Response\" (change nothing). You should be logged in. If you try and repeat this process, you may be automatically logged in using the information you gave previously. To fix this, open your developer console (F12 or Ctrl+Shift+I) while on the samling page and clear the site data. In Chrome, this will be a button on the Application tab.","breadcrumbs":"Internal Documentation » Single Sign-On » SAML » How to test SAML as a developer without a server","id":"1028","title":"How to test SAML as a developer without a server"},"1029":{"body":"The django-mama-cas project is an easy to run CAS implementation built on top of Django.","breadcrumbs":"Internal Documentation » Single Sign-On » CAS » How to test CAS as a developer without a server","id":"1029","title":"How to test CAS as a developer without a server"},"103":{"body":"Before: Shared YAML instance_map: generic_worker1: host: localhost port: 5678 tls: false Worker YAML worker_app: synapse.app.generic_worker\nworker_name: generic_worker1 worker_replication_host: localhost\nworker_replication_http_port: 3456\nworker_replication_http_tls: false worker_listeners: - type: http port: 1234 resources: - names: [client, federation] - type: http port: 5678 resources: - names: [replication] worker_log_config: /etc/matrix-synapse/generic-worker-log.yaml After: Shared YAML instance_map: main: host: localhost port: 3456 tls: false generic_worker1: host: localhost port: 5678 tls: false Worker YAML worker_app: synapse.app.generic_worker\nworker_name: generic_worker1 worker_listeners: - type: http port: 1234 resources: - names: [client, federation] - type: http port: 5678 resources: - names: [replication] worker_log_config: /etc/matrix-synapse/generic-worker-log.yaml Notes: tls is optional but mirrors the functionality of worker_replication_http_tls","breadcrumbs":"Upgrading between Synapse Versions » Example change","id":"103","title":"Example change"},"1030":{"body":"Create a new virtualenv: python3 -m venv Activate your virtualenv: source /path/to/your/virtualenv/bin/activate Install Django and django-mama-cas: python -m pip install \"django<3\" \"django-mama-cas==2.4.0\" Create a Django project in the current directory: django-admin startproject cas_test . Follow the install directions for django-mama-cas Setup the SQLite database: python manage.py migrate Create a user: python manage.py createsuperuser Use whatever you want as the username and password. Leave the other fields blank. Use the built-in Django test server to serve the CAS endpoints on port 8000: python manage.py runserver You should now have a Django project configured to serve CAS authentication with a single user created.","breadcrumbs":"Internal Documentation » Single Sign-On » CAS » Prerequisites","id":"1030","title":"Prerequisites"},"1031":{"body":"Modify your homeserver.yaml to enable CAS and point it to your locally running Django test server: cas_config: enabled: true server_url: \"http://localhost:8000\" service_url: \"http://localhost:8081\" #displayname_attribute: name #required_attributes: # name: value Restart Synapse. Note that the above configuration assumes the homeserver is running on port 8081 and that the CAS server is on port 8000, both on localhost.","breadcrumbs":"Internal Documentation » Single Sign-On » CAS » Configure Synapse (and Element) to use CAS","id":"1031","title":"Configure Synapse (and Element) to use CAS"},"1032":{"body":"Then in Element: Visit the login page with a Element pointing at your homeserver. Click the Single Sign-On button. Login using the credentials created with createsuperuser. You should be logged in. If you want to repeat this process you'll need to manually logout first: http://localhost:8000/admin/ Click \"logout\" in the top right.","breadcrumbs":"Internal Documentation » Single Sign-On » CAS » Testing the configuration","id":"1032","title":"Testing the configuration"},"1033":{"body":"","breadcrumbs":"Internal Documentation » Room DAG concepts » Room DAG concepts","id":"1033","title":"Room DAG concepts"},"1034":{"body":"The word \"edge\" comes from graph theory lingo. An edge is just a connection between two events. In Synapse, we connect events by specifying their prev_events. A subsequent event points back at a previous event. A (oldest) <---- B <---- C (most recent)","breadcrumbs":"Internal Documentation » Room DAG concepts » Edges","id":"1034","title":"Edges"},"1035":{"body":"Events are normally sorted by (topological_ordering, stream_ordering) where topological_ordering is just depth. In other words, we first sort by depth and then tie-break based on stream_ordering. depth is incremented as new messages are added to the DAG. Normally, stream_ordering is an auto incrementing integer, but backfilled events start with stream_ordering=-1 and decrement. Incremental /sync?since=xxx returns things in the order they arrive at the server (stream_ordering). Initial /sync, /messages (and /backfill in the federation API) return them in the order determined by the event graph (topological_ordering, stream_ordering). The general idea is that, if you're following a room in real-time (i.e. /sync), you probably want to see the messages as they arrive at your server, rather than skipping any that arrived late; whereas if you're looking at a historical section of timeline (i.e. /messages), you want to see the best representation of the state of the room as others were seeing it at the time.","breadcrumbs":"Internal Documentation » Room DAG concepts » Depth and stream ordering","id":"1035","title":"Depth and stream ordering"},"1036":{"body":"We mark an event as an outlier when we haven't figured out the state for the room at that point in the DAG yet. They are \"floating\" events that we haven't yet correlated to the DAG. Outliers typically arise when we fetch the auth chain or state for a given event. When that happens, we just grab the events in the state/auth chain, without calculating the state at those events, or backfilling their prev_events. Since we don't have the state at any events fetched in that way, we mark them as outliers. So, typically, we won't have the prev_events of an outlier in the database, (though it's entirely possible that we might have them for some other reason). Other things that make outliers different from regular events: We don't have state for them, so there should be no entry in event_to_state_groups for an outlier. (In practice this isn't always the case, though I'm not sure why: see https://github.com/matrix-org/synapse/issues/12201). We don't record entries for them in the event_edges, event_forward_extremeties or event_backward_extremities tables. Since outliers are not tied into the DAG, they do not normally form part of the timeline sent down to clients via /sync or /messages; however there is an exception:","breadcrumbs":"Internal Documentation » Room DAG concepts » Outliers","id":"1036","title":"Outliers"},"1037":{"body":"A special case of outlier events are some membership events for federated rooms that we aren't full members of. For example: invites received over federation, before we join the room rejections for said invites knock events for rooms that we would like to join but have not yet joined. In all the above cases, we don't have the state for the room, which is why they are treated as outliers. They are a bit special though, in that they are proactively sent to clients via /sync.","breadcrumbs":"Internal Documentation » Room DAG concepts » Out-of-band membership events","id":"1037","title":"Out-of-band membership events"},"1038":{"body":"Most-recent-in-time events in the DAG which are not referenced by any other events' prev_events yet. (In this definition, outliers, rejected events, and soft-failed events don't count.) The forward extremities of a room (or at least, a subset of them, if there are more than ten) are used as the prev_events when the next event is sent. The \"current state\" of a room (ie: the state which would be used if we generated a new event) is, therefore, the resolution of the room states at each of the forward extremities.","breadcrumbs":"Internal Documentation » Room DAG concepts » Forward extremity","id":"1038","title":"Forward extremity"},"1039":{"body":"The current marker of where we have backfilled up to and will generally be the prev_events of the oldest-in-time events we have in the DAG. This gives a starting point when backfilling history. Note that, unlike forward extremities, we typically don't have any backward extremity events themselves in the database - or, if we do, they will be \"outliers\" (see above). Either way, we don't expect to have the room state at a backward extremity. When we persist a non-outlier event, if it was previously a backward extremity, we clear it as a backward extremity and set all of its prev_events as the new backward extremities if they aren't already persisted as non-outliers. This therefore keeps the backward extremities up-to-date.","breadcrumbs":"Internal Documentation » Room DAG concepts » Backward extremity","id":"1039","title":"Backward extremity"},"104":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.81.0","id":"104","title":"Upgrading to v1.81.0"},"1040":{"body":"For every non-outlier event we need to know the state at that event. Instead of storing the full state for each event in the DB (i.e. a event_id -> state mapping), which is very space inefficient when state doesn't change, we instead assign each different set of state a \"state group\" and then have mappings of event_id -> state_group and state_group -> state.","breadcrumbs":"Internal Documentation » Room DAG concepts » State groups","id":"1040","title":"State groups"},"1041":{"body":"TODO: state_group_edges is a further optimization... notes from @Azrenbeth, https://pastebin.com/seUGVGeT","breadcrumbs":"Internal Documentation » Room DAG concepts » Stage group edges","id":"1041","title":"Stage group edges"},"1042":{"body":"The auth chain difference algorithm is used by V2 state resolution, where a naive implementation can be a significant source of CPU and DB usage.","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Auth Chain Difference Algorithm","id":"1042","title":"Auth Chain Difference Algorithm"},"1043":{"body":"A state set is a set of state events; e.g. the input of a state resolution algorithm is a collection of state sets. The auth chain of a set of events are all the events' auth events and their auth events, recursively (i.e. the events reachable by walking the graph induced by an event's auth events links). The auth chain difference of a collection of state sets is the union minus the intersection of the sets of auth chains corresponding to the state sets, i.e an event is in the auth chain difference if it is reachable by walking the auth event graph from at least one of the state sets but not from all of the state sets.","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Definitions","id":"1043","title":"Definitions"},"1044":{"body":"A way of calculating the auth chain difference without calculating the full auth chains for each state set is to do a parallel breadth first walk (ordered by depth) of each state set's auth chain. By tracking which events are reachable from each state set we can finish early if every pending event is reachable from every state set. This can work well for state sets that have a small auth chain difference, but can be very inefficient for larger differences. However, this algorithm is still used if we don't have a chain cover index for the room (e.g. because we're in the process of indexing it).","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Breadth First Walk Algorithm","id":"1044","title":"Breadth First Walk Algorithm"},"1045":{"body":"Synapse computes auth chain differences by pre-computing a \"chain cover\" index for the auth chain in a room, allowing us to efficiently make reachability queries like \"is event A in the auth chain of event B?\". We could do this with an index that tracks all pairs (A, B) such that A is in the auth chain of B. However, this would be prohibitively large, scaling poorly as the room accumulates more state events. Instead, we break down the graph into chains . A chain is a subset of a DAG with the following property: for any pair of events E and F in the chain, the chain contains a path E -> F or a path F -> E. This forces a chain to be linear (without forks), e.g. E -> F -> G -> ... -> H. Each event in the chain is given a sequence number local to that chain. The oldest event E in the chain has sequence number 1. If E has a child F in the chain, then F has sequence number 2. If E has a grandchild G in the chain, then G has sequence number 3; and so on. Synapse ensures that each persisted event belongs to exactly one chain, and tracks how the chains are connected to one another. This allows us to efficiently answer reachability queries. Doing so uses less storage than tracking reachability on an event-by-event basis, particularly when we have fewer and longer chains. See Jagadish, H. (1990). A compression technique to materialize transitive closure . ACM Transactions on Database Systems (TODS) , 15*(4)*, 558-598. for the original idea or Y. Chen, Y. Chen, An efficient algorithm for answering graph reachability queries , in: 2008 IEEE 24th International Conference on Data Engineering, April 2008, pp. 893–902. (PDF available via Google Scholar .) for a more modern take. In practical terms, the chain cover assigns every event a chain ID and sequence number (e.g. (5,3)), and maintains a map of links between events in chains (e.g. (5,3) -> (2,4)) such that A is reachable by B (i.e. A is in the auth chain of B) if and only if either: A and B have the same chain ID and A's sequence number is less than B's sequence number; or there is a link L between B's chain ID and A's chain ID such that L.start_seq_no <= B.seq_no and A.seq_no <= L.end_seq_no. There are actually two potential implementations, one where we store links from each chain to every other reachable chain (the transitive closure of the links graph), and one where we remove redundant links (the transitive reduction of the links graph) e.g. if we have chains C3 -> C2 -> C1 then the link C3 -> C1 would not be stored. Synapse uses the former implementation so that it doesn't need to recurse to test reachability between chains. This trades-off extra storage in order to save CPU cycles and DB queries.","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Chain Cover Index","id":"1045","title":"Chain Cover Index"},"1046":{"body":"An example auth graph would look like the following, where chains have been formed based on type/state_key and are denoted by colour and are labelled with (chain ID, sequence number). Links are denoted by the arrows (links in grey are those that would be remove in the second implementation described above). Example Note that we don't include all links between events and their auth events, as most of those links would be redundant. For example, all events point to the create event, but each chain only needs the one link from it's base to the create event.","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Example","id":"1046","title":"Example"},"1047":{"body":"This index can be used to calculate the auth chain difference of the state sets by looking at the chain ID and sequence numbers reachable from each state set: For every state set lookup the chain ID/sequence numbers of each state event Use the index to find all chains and the maximum sequence number reachable from each state set. The auth chain difference is then all events in each chain that have sequence numbers between the maximum sequence number reachable from any state set and the minimum reachable by all state sets (if any). Note that steps 2 is effectively calculating the auth chain for each state set (in terms of chain IDs and sequence numbers), and step 3 is calculating the difference between the union and intersection of the auth chains.","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Using the Index","id":"1047","title":"Using the Index"},"1048":{"body":"For example, given the above graph, we can calculate the difference between state sets consisting of: S1: Alice's invite (4,1) and Bob's second join (2,2); and S2: Alice's second join (4,3) and Bob's first join (2,1). Using the index we see that the following auth chains are reachable from each state set: S1: (1,1), (2,2), (3,1) & (4,1) S2: (1,1), (2,1), (3,2) & (4,3) And so, for each the ranges that are in the auth chain difference: Chain 1: None, (since everything can reach the create event). Chain 2: The range (1, 2] (i.e. just 2), as 1 is reachable by all state sets and the maximum reachable is 2 (corresponding to Bob's second join). Chain 3: Similarly the range (1, 2] (corresponding to the second power level). Chain 4: The range (1, 3] (corresponding to both of Alice's joins). So the final result is: Bob's second join (2,2), the second power level (3,2) and both of Alice's joins (4,2) & (4,3).","breadcrumbs":"Internal Documentation » State Resolution » The Auth Chain Difference Algorithm » Worked Example","id":"1048","title":"Worked Example"},"1049":{"body":"Synapse implementation-specific details for the media repository The media repository stores avatars, attachments and their thumbnails for media uploaded by local users. caches avatars, attachments and their thumbnails for media uploaded by remote users. caches resources and thumbnails used for URL previews. All media in Matrix can be identified by a unique MXC URI , consisting of a server name and media ID: mxc:///","breadcrumbs":"Internal Documentation » Media Repository » Media Repository","id":"1049","title":"Media Repository"},"105":{"body":"Synapse now attempts the versioned appservice paths before falling back to the legacy paths . Usage of the legacy routes should be considered deprecated. Additionally, Synapse has supported sending the application service access token via the Authorization header since v1.70.0. For backwards compatibility it is also sent as the access_token query parameter. This is insecure and should be considered deprecated. A future version of Synapse (v1.88.0 or later) will remove support for legacy application service routes and query parameter authorization.","breadcrumbs":"Upgrading between Synapse Versions » Application service path & authentication deprecations","id":"105","title":"Application service path & authentication deprecations"},"1050":{"body":"Synapse generates 24 character media IDs for content uploaded by local users. These media IDs consist of upper and lowercase letters and are case-sensitive. Other homeserver implementations may generate media IDs differently. Local media is recorded in the local_media_repository table, which includes metadata such as MIME types, upload times and file sizes. Note that this table is shared by the URL cache, which has a different media ID scheme.","breadcrumbs":"Internal Documentation » Media Repository » Local Media","id":"1050","title":"Local Media"},"1051":{"body":"A file with media ID aabbcccccccccccccccccccc and its 128x96 image/jpeg thumbnail, created by scaling, would be stored at: local_content/aa/bb/cccccccccccccccccccc\nlocal_thumbnails/aa/bb/cccccccccccccccccccc/128-96-image-jpeg-scale","breadcrumbs":"Internal Documentation » Media Repository » Paths","id":"1051","title":"Paths"},"1052":{"body":"When media from a remote homeserver is requested from Synapse, it is assigned a local filesystem_id, with the same format as locally-generated media IDs, as described above. A record of remote media is stored in the remote_media_cache table, which can be used to map remote MXC URIs (server names and media IDs) to local filesystem_ids.","breadcrumbs":"Internal Documentation » Media Repository » Remote Media","id":"1052","title":"Remote Media"},"1053":{"body":"A file from matrix.org with filesystem_id aabbcccccccccccccccccccc and its 128x96 image/jpeg thumbnail, created by scaling, would be stored at: remote_content/matrix.org/aa/bb/cccccccccccccccccccc\nremote_thumbnail/matrix.org/aa/bb/cccccccccccccccccccc/128-96-image-jpeg-scale Older thumbnails may omit the thumbnailing method: remote_thumbnail/matrix.org/aa/bb/cccccccccccccccccccc/128-96-image-jpeg Note that remote_thumbnail/ does not have an s.","breadcrumbs":"Internal Documentation » Media Repository » Paths","id":"1053","title":"Paths"},"1054":{"body":"When generating previews for URLs, Synapse may download and cache various resources, including images. These resources are assigned temporary media IDs of the form yyyy-mm-dd_aaaaaaaaaaaaaaaa, where yyyy-mm-dd is the current date and aaaaaaaaaaaaaaaa is a random sequence of 16 case-sensitive letters. The metadata for these cached resources is stored in the local_media_repository and local_media_repository_url_cache tables. Resources for URL previews are deleted after a few days.","breadcrumbs":"Internal Documentation » Media Repository » URL Previews","id":"1054","title":"URL Previews"},"1055":{"body":"The file with media ID yyyy-mm-dd_aaaaaaaaaaaaaaaa and its 128x96 image/jpeg thumbnail, created by scaling, would be stored at: url_cache/yyyy-mm-dd/aaaaaaaaaaaaaaaa\nurl_cache_thumbnails/yyyy-mm-dd/aaaaaaaaaaaaaaaa/128-96-image-jpeg-scale","breadcrumbs":"Internal Documentation » Media Repository » Paths","id":"1055","title":"Paths"},"1056":{"body":"Synapse maintains room and user statistics in various tables. These can be used for administrative purposes but are also used when generating the public room directory.","breadcrumbs":"Internal Documentation » Room and User Statistics » Room and User Statistics","id":"1056","title":"Room and User Statistics"},"1057":{"body":"","breadcrumbs":"Internal Documentation » Room and User Statistics » Synapse Developer Documentation","id":"1057","title":"Synapse Developer Documentation"},"1058":{"body":"","breadcrumbs":"Internal Documentation » Room and User Statistics » High-Level Concepts","id":"1058","title":"High-Level Concepts"},"1059":{"body":"subject : Something we are tracking stats about – currently a room or user. current row : An entry for a subject in the appropriate current statistics table. Each subject can have only one.","breadcrumbs":"Internal Documentation » Room and User Statistics » Definitions","id":"1059","title":"Definitions"},"106":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.80.0","id":"106","title":"Upgrading to v1.80.0"},"1060":{"body":"Stats correspond to the present values. Current rows contain the most up-to-date statistics for a room. Each subject can only have one entry.","breadcrumbs":"Internal Documentation » Room and User Statistics » Overview","id":"1060","title":"Overview"},"1061":{"body":"Synapse has a number of platform dependencies, including Python, Rust, PostgreSQL and SQLite. This document outlines the policy towards which versions we support, and when we drop support for versions in the future.","breadcrumbs":"Dependency Deprecation Policy » Deprecation Policy for Platform Dependencies","id":"1061","title":"Deprecation Policy for Platform Dependencies"},"1062":{"body":"Synapse follows the upstream support life cycles for Python and PostgreSQL, i.e. when a version reaches End of Life Synapse will withdraw support for that version in future releases. Details on the upstream support life cycles for Python and PostgreSQL are documented at https://endoflife.date/python and https://endoflife.date/postgresql . A Rust compiler is required to build Synapse from source. For any given release the minimum required version may be bumped up to a recent Rust version, and so people building from source should ensure they can fetch recent versions of Rust (e.g. by using rustup ). The oldest supported version of SQLite is the version provided by Debian oldstable .","breadcrumbs":"Dependency Deprecation Policy » Policy","id":"1062","title":"Policy"},"1063":{"body":"It is important for system admins to have a clear understanding of the platform requirements of Synapse and its deprecation policies so that they can effectively plan upgrading their infrastructure ahead of time. This is especially important in contexts where upgrading the infrastructure requires auditing and approval from a security team, or where otherwise upgrading is a long process. By following the upstream support life cycles Synapse can ensure that its dependencies continue to get security patches, while not requiring system admins to constantly update their platform dependencies to the latest versions. For Rust, the situation is a bit different given that a) the Rust foundation does not generally support older Rust versions, and b) the library ecosystem generally bump their minimum support Rust versions frequently. In general, the Synapse team will try to avoid updating the dependency on Rust to the absolute latest version, but introducing a formal policy is hard given the constraints of the ecosystem. On a similar note, SQLite does not generally have a concept of \"supported release\"; bugfixes are published for the latest minor release only. We chose to track Debian's oldstable as this is relatively conservative, predictably updated and is consistent with the .deb packages released by Matrix.org.","breadcrumbs":"Dependency Deprecation Policy » Context","id":"1063","title":"Context"},"1064":{"body":"I've been running my homeserver on a cubietruck at home now for some time and am often replying to statements like \"you need loads of ram to join large rooms\" with \"it works fine for me\". I thought it might be useful to curate a summary of the issues you're likely to run into to help as a scaling-down guide, maybe highlight these for development work or end up as documentation. It seems that once you get up to about 4x1.5GHz arm64 4GiB these issues are no longer a problem. Platform : 2x1GHz armhf 2GiB ram Single-board computers , SSD, postgres.","breadcrumbs":"Running Synapse on a Single-Board Computer » Summary of performance impact of running on resource constrained devices such as SBCs","id":"1064","title":"Summary of performance impact of running on resource constrained devices such as SBCs"},"1065":{"body":"This is the main reason people have a poor matrix experience on resource constrained homeservers. Element web will frequently be saying the server is offline while the python process will be pegged at 100% cpu. This feature is used to tell when other users are active (have a client app in the foreground) and therefore more likely to respond, but requires a lot of network activity to maintain even when nobody is talking in a room. Screenshot_2020-10-01_19-29-46 While synapse does have some performance issues with presence #3971 , the fundamental problem is that this is an easy feature to implement for a centralised service at nearly no overhead, but federation makes it combinatorial #8055 . There is also a client-side config option which disables the UI and idle tracking enable_presence_by_hs_url to blacklist the largest instances but I didn't notice much difference, so I recommend disabling the feature entirely at the server level as well.","breadcrumbs":"Running Synapse on a Single-Board Computer » Presence","id":"1065","title":"Presence"},"1066":{"body":"Joining a \"large\", federated room will initially fail with the below message in Element web, but waiting a while (10-60mins) and trying again will succeed without any issue. What counts as \"large\" is not message history, user count, connections to homeservers or even a simple count of the state events, it is instead how long the state resolution algorithm takes. However, each of those numbers are reasonable proxies, so we can use them as estimates since user count is one of the few things you see before joining. Screenshot_2020-10-02_17-15-06 This is #1211 and will also hopefully be mitigated by peeking matrix-org/matrix-doc#2753 so at least you don't need to wait for a join to complete before finding out if it's the kind of room you want. Note that you should first disable presence, otherwise it'll just make the situation worse #3120 . There is a lot of database interaction too, so make sure you've migrated your data from the default sqlite to postgresql. Personally, I recommend patience - once the initial join is complete there's rarely any issues with actually interacting with the room, but if you like you can just block \"large\" rooms entirely.","breadcrumbs":"Running Synapse on a Single-Board Computer » Joining","id":"1066","title":"Joining"},"1067":{"body":"Anything that requires modifying the device list #7721 will take a while to propagate, again taking the client \"Offline\" until it's complete. This includes signing in and out, editing the public name and verifying e2ee. The main mitigation I recommend is to keep long-running sessions open e.g. by using Firefox SSB \"Use this site in App mode\" or Chromium PWA \"Install Element\".","breadcrumbs":"Running Synapse on a Single-Board Computer » Sessions","id":"1067","title":"Sessions"},"1068":{"body":"Put the below in a new file at /etc/matrix-synapse/conf.d/sbc.yaml to override the defaults in homeserver.yaml. # Disable presence tracking, which is currently fairly resource intensive\n# More info: https://github.com/matrix-org/synapse/issues/9478\nuse_presence: false # Set a small complexity limit, preventing users from joining large rooms\n# which may be resource-intensive to remain a part of.\n#\n# Note that this will not prevent users from joining smaller rooms that\n# eventually become complex.\nlimit_remote_rooms: enabled: true complexity: 3.0 # Database configuration\ndatabase: # Use postgres for the best performance name: psycopg2 args: user: matrix-synapse # Generate a long, secure password using a password manager password: hunter2 database: matrix-synapse host: localhost Currently the complexity is measured by current_state_events / 500 . You can find join times and your most complex rooms like this: admin@homeserver:~$ zgrep '/client/r0/join/' /var/log/matrix-synapse/homeserver.log* | awk '{print $18, $25}' | sort --human-numeric-sort\n29.922sec/-0.002sec /_matrix/client/r0/join/%23debian-fasttrack%3Apoddery.com\n182.088sec/0.003sec /_matrix/client/r0/join/%23decentralizedweb-general%3Amatrix.org\n911.625sec/-570.847sec /_matrix/client/r0/join/%23synapse%3Amatrix.org admin@homeserver:~$ sudo --user postgres psql matrix-synapse --command 'select canonical_alias, joined_members, current_state_events from room_stats_state natural join room_stats_current where canonical_alias is not null order by current_state_events desc fetch first 5 rows only' canonical_alias | joined_members | current_state_events -------------------------------+----------------+---------------------- #_oftc_#debian:matrix.org | 871 | 52355 #matrix:matrix.org | 6379 | 10684 #irc:matrix.org | 461 | 3751 #decentralizedweb-general:matrix.org | 997 | 1509 #whatsapp:maunium.net | 554 | 854","breadcrumbs":"Running Synapse on a Single-Board Computer » Recommended configuration","id":"1068","title":"Recommended configuration"},"107":{"body":"Before this update, the POST /_matrix/client/v3/rooms/{roomId}/report/{eventId} endpoint would return a 403 if a user attempted to report an event that they did not have access to. This endpoint will now return a 404 in this case instead. Clients that implement event reporting should check that their error handling code will handle this change.","breadcrumbs":"Upgrading between Synapse Versions » Reporting events error code change","id":"107","title":"Reporting events error code change"},"108":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.79.0","id":"108","title":"Upgrading to v1.79.0"},"109":{"body":"Synapse v1.79.0 deprecates the on_threepid_bind \"third-party rules\" Synapse module callback method in favour of a new module method, on_add_user_third_party_identifier . on_threepid_bind will be removed in a future version of Synapse. You should check whether any Synapse modules in use in your deployment are making use of on_threepid_bind, and update them where possible. The arguments and functionality of the new method are the same. The justification behind the name change is that the old method's name, on_threepid_bind, was misleading. A user is considered to \"bind\" their third-party ID to their Matrix ID only if they do so via an identity server (so that users on other homeservers may find them). But this method was not called in that case - it was only called when a user added a third-party identifier on the local homeserver. Module developers may also be interested in the related on_remove_user_third_party_identifier module callback method that was also added in Synapse v1.79.0. This new method is called when a user removes a third-party identifier from their account.","breadcrumbs":"Upgrading between Synapse Versions » The on_threepid_bind module callback method has been deprecated","id":"109","title":"The on_threepid_bind module callback method has been deprecated"},"11":{"body":"The default configuration exposes a single HTTP port on the local interface: http://localhost:8008. It is suitable for local testing, but for any practical use, you will need Synapse's APIs to be served over HTTPS. The recommended way to do so is to set up a reverse proxy on port 8448. You can find documentation on doing so in the reverse proxy documentation . Alternatively, you can configure Synapse to expose an HTTPS port. To do so, you will need to edit homeserver.yaml, as follows: First, under the listeners option, add the configuration for the TLS-enabled listener like so: listeners: - port: 8448 type: http tls: true resources: - names: [client, federation] You will also need to add the options tls_certificate_path and tls_private_key_path. to your configuration file. You will need to manage provisioning of these certificates yourself. You can find more information about these options as well as how to configure synapse in the configuration manual . If you are using your own certificate, be sure to use a .pem file that includes the full certificate chain including any intermediate certificates (for instance, if using certbot, use fullchain.pem as your certificate, not cert.pem). For a more detailed guide to configuring your server for federation, see Federation .","breadcrumbs":"Installation » TLS certificates","id":"11","title":"TLS certificates"},"110":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.78.0","id":"110","title":"Upgrading to v1.78.0"},"111":{"body":"Synapse 1.78.0 replaces the /_synapse/admin/v1/media//delete admin API with an identical endpoint at /_synapse/admin/v1/media/delete. Please update your tooling to use the new endpoint. The deprecated version will be removed in a future release.","breadcrumbs":"Upgrading between Synapse Versions » Deprecate the /_synapse/admin/v1/media//delete admin API","id":"111","title":"Deprecate the /_synapse/admin/v1/media//delete admin API"},"112":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.76.0","id":"112","title":"Upgrading to v1.76.0"},"113":{"body":"When joining a room for the first time, Synapse 1.76.0 will request a partial join from the other server by default. Previously, server admins had to opt-in to this using an experimental config flag. Server admins can opt out of this feature for the time being by setting experimental: faster_joins: false in their server config.","breadcrumbs":"Upgrading between Synapse Versions » Faster joins are enabled by default","id":"113","title":"Faster joins are enabled by default"},"114":{"body":"Synapse has changed the format of the account data and devices replication streams (between workers). This is a forwards- and backwards-incompatible change: v1.75 workers cannot process account data replicated by v1.76 workers, and vice versa. Once all workers are upgraded to v1.76 (or downgraded to v1.75), account data and device replication will resume as normal.","breadcrumbs":"Upgrading between Synapse Versions » Changes to the account data replication streams","id":"114","title":"Changes to the account data replication streams"},"115":{"body":"The minimum supported version of Poetry is now 1.3.2 (previously 1.2.0, since Synapse 1.67 ). If you have used poetry install to install Synapse from a source checkout, you should upgrade poetry: see its installation instructions . For all other installation methods, no acction is required.","breadcrumbs":"Upgrading between Synapse Versions » Minimum version of Poetry is now 1.3.2","id":"115","title":"Minimum version of Poetry is now 1.3.2"},"116":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.74.0","id":"116","title":"Upgrading to v1.74.0"},"117":{"body":"This version introduces optional support for an improved user search dealing with Unicode characters . If you want to take advantage of this feature you need to install PyICU, the ICU native dependency and its development headers so that PyICU can build since no prebuilt wheels are available. You can follow the PyICU documentation to do so, and then do pip install matrix-synapse[user-search] for a PyPI install. Docker images and Debian packages need nothing specific as they already include or specify ICU as an explicit dependency.","breadcrumbs":"Upgrading between Synapse Versions » Unicode support in user search","id":"117","title":"Unicode support in user search"},"118":{"body":"Synapse 1.74 queues a background update to rebuild the user directory , in order to fix missing or erroneous entries. When this update begins, the user directory will be cleared out and rebuilt from scratch. User directory lookups will be incomplete until the rebuild completes. Admins can monitor the rebuild's progress by using the Background update Admin API .","breadcrumbs":"Upgrading between Synapse Versions » User directory rebuild","id":"118","title":"User directory rebuild"},"119":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.73.0","id":"119","title":"Upgrading to v1.73.0"},"12":{"body":"Setting up the client Well-Known URI is optional but if you set it up, it will allow users to enter their full username (e.g. @user:) into clients which support well-known lookup to automatically configure the homeserver and identity server URLs. This is useful so that users don't have to memorize or think about the actual homeserver URL you are using. The URL https:///.well-known/matrix/client should return JSON in the following format. { \"m.homeserver\": { \"base_url\": \"https://\" }\n} It can optionally contain identity server information as well. { \"m.homeserver\": { \"base_url\": \"https://\" }, \"m.identity_server\": { \"base_url\": \"https://\" }\n} To work in browser based clients, the file must be served with the appropriate Cross-Origin Resource Sharing (CORS) headers. A recommended value would be Access-Control-Allow-Origin: * which would allow all browser based clients to view it. In nginx this would be something like: location /.well-known/matrix/client { return 200 '{\"m.homeserver\": {\"base_url\": \"https://\"}}'; default_type application/json; add_header Access-Control-Allow-Origin *;\n} You should also ensure the public_baseurl option in homeserver.yaml is set correctly. public_baseurl should be set to the URL that clients will use to connect to your server. This is the same URL you put for the m.homeserver base_url above. public_baseurl: \"https://\"","breadcrumbs":"Installation » Client Well-Known URI","id":"12","title":"Client Well-Known URI"},"120":{"body":"Synapse v1.69.0 included the deprecation of legacy Prometheus metric names and offered an option to disable them. Synapse v1.71.0 disabled legacy Prometheus metric names by default. This version, v1.73.0, removes those legacy Prometheus metric names entirely. This also means that the enable_legacy_metrics configuration option has been removed; it will no longer be possible to re-enable the legacy metric names. If you use metrics and have not yet updated your Grafana dashboard(s), Prometheus console(s) or alerting rule(s), please consider doing so when upgrading to this version. Note that the included Grafana dashboard was updated in v1.72.0 to correct some metric names which were missed when legacy metrics were disabled by default. See v1.69.0: Deprecation of legacy Prometheus metric names for more context.","breadcrumbs":"Upgrading between Synapse Versions » Legacy Prometheus metric names have now been removed","id":"120","title":"Legacy Prometheus metric names have now been removed"},"121":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.72.0","id":"121","title":"Upgrading to v1.72.0"},"122":{"body":"In line with our deprecation policy , we've dropped support for PostgreSQL 10, as it is no longer supported upstream. This release of Synapse requires PostgreSQL 11+.","breadcrumbs":"Upgrading between Synapse Versions » Dropping support for PostgreSQL 10","id":"122","title":"Dropping support for PostgreSQL 10"},"123":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.71.0","id":"123","title":"Upgrading to v1.71.0"},"124":{"body":"As announced with the release of Synapse 1.69.0 , the deprecated generate_short_term_login_token module method has been removed. Modules relying on it can instead use the create_login_token method.","breadcrumbs":"Upgrading between Synapse Versions » Removal of the generate_short_term_login_token module API method","id":"124","title":"Removal of the generate_short_term_login_token module API method"},"125":{"body":"To align with spec (changed in MSC3905 ), Synapse now only considers local users to be interesting. In other words, the users namespace regex is only be applied against local users of the homeserver. Please note, this probably doesn't affect the expected behavior of your application service, since an interesting local user in a room still means all messages in the room (from local or remote users) will still be considered interesting. And matching a room with the rooms or aliases namespace regex will still consider all events sent in the room to be interesting to the application service. If one of your application service's users regex was intending to match a remote user, this will no longer match as you expect. The behavioral mismatch between matching all local users and some remote users is why the spec was changed/clarified and this caveat is no longer supported.","breadcrumbs":"Upgrading between Synapse Versions » Changes to the events received by application services (interest)","id":"125","title":"Changes to the events received by application services (interest)"},"126":{"body":"Synapse v1.71.0 disables legacy Prometheus metric names by default. For administrators that still rely on them and have not yet had chance to update their uses of the metrics, it's still possible to specify enable_legacy_metrics: true in the configuration to re-enable them temporarily. Synapse v1.73.0 will remove legacy metric names altogether and at that point, it will no longer be possible to re-enable them. If you do not use metrics or you have already updated your Grafana dashboard(s), Prometheus console(s) and alerting rule(s), there is no action needed. See v1.69.0: Deprecation of legacy Prometheus metric names .","breadcrumbs":"Upgrading between Synapse Versions » Legacy Prometheus metric names are now disabled by default","id":"126","title":"Legacy Prometheus metric names are now disabled by default"},"127":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.69.0","id":"127","title":"Upgrading to v1.69.0"},"128":{"body":"Synapse now includes information indicating if a receipt applies to a thread when replicating it to other workers. This is a forwards- and backwards-incompatible change: v1.68 and workers cannot process receipts replicated by v1.69 workers, and vice versa. Once all workers are upgraded to v1.69 (or downgraded to v1.68), receipts replication will resume as normal.","breadcrumbs":"Upgrading between Synapse Versions » Changes to the receipts replication streams","id":"128","title":"Changes to the receipts replication streams"},"129":{"body":"In current versions of Synapse, some Prometheus metrics are emitted under two different names, with one of the names being older but non-compliant with OpenMetrics and Prometheus conventions and one of the names being newer but compliant. Synapse v1.71.0 will turn the old metric names off by default . For administrators that still rely on them and have not had chance to update their uses of the metrics, it's possible to specify enable_legacy_metrics: true in the configuration to re-enable them temporarily. Synapse v1.73.0 will remove legacy metric names altogether and it will no longer be possible to re-enable them. The Grafana dashboard, Prometheus recording rules and Prometheus Consoles included in the contrib directory in the Synapse repository have been updated to no longer rely on the legacy names. These can be used on a current version of Synapse because current versions of Synapse emit both old and new names. You may need to update your alerting rules or any other rules that depend on the names of Prometheus metrics. If you want to test your changes before legacy names are disabled by default, you may specify enable_legacy_metrics: false in your homeserver configuration. A list of affected metrics is available on the Metrics How-to page .","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of legacy Prometheus metric names","id":"129","title":"Deprecation of legacy Prometheus metric names"},"13":{"body":"It is desirable for Synapse to have the capability to send email. This allows Synapse to send password reset emails, send verifications when an email address is added to a user's account, and send email notifications to users when they receive new messages. To configure an SMTP server for Synapse, modify the configuration section headed email, and be sure to have at least the smtp_host, smtp_port and notif_from fields filled out. You may also need to set smtp_user, smtp_pass, and require_transport_security. If email is not configured, password reset, registration and notifications via email will be disabled.","breadcrumbs":"Installation » Email","id":"13","title":"Email"},"130":{"body":"The following method of the module API has been deprecated, and is scheduled to be remove in v1.71.0: def generate_short_term_login_token( self, user_id: str, duration_in_ms: int = (2 * 60 * 1000), auth_provider_id: str = \"\", auth_provider_session_id: Optional[str] = None,\n) -> str: ... It has been replaced by an asynchronous equivalent: async def create_login_token( self, user_id: str, duration_in_ms: int = (2 * 60 * 1000), auth_provider_id: Optional[str] = None, auth_provider_session_id: Optional[str] = None,\n) -> str: ... Synapse will log a warning when a module uses the deprecated method, to help administrators find modules using it.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the generate_short_term_login_token module API method","id":"130","title":"Deprecation of the generate_short_term_login_token module API method"},"131":{"body":"Two changes announced in the upgrade notes for v1.67.0 have now landed in v1.68.0.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.68.0","id":"131","title":"Upgrading to v1.68.0"},"132":{"body":"Synapse now requires a SQLite version of 3.27.0 or higher if SQLite is configured as Synapse's database. Installations using Docker images from matrixdotorg , Debian packages from Matrix.org , or a PostgreSQL database are not affected.","breadcrumbs":"Upgrading between Synapse Versions » SQLite version requirement","id":"132","title":"SQLite version requirement"},"133":{"body":"Building from a source checkout of Synapse now requires a recent Rust compiler (currently Rust 1.58.1, but see also the Platform Dependency Policy ). Installations using Docker images from matrixdotorg , Debian packages from Matrix.org , or PyPI wheels via pip install matrix-synapse (on supported platforms and architectures) will not be affected.","breadcrumbs":"Upgrading between Synapse Versions » Rust requirement when building from source.","id":"133","title":"Rust requirement when building from source."},"134":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.67.0","id":"134","title":"Upgrading to v1.67.0"},"135":{"body":"Redis support was added in v1.13.0 with it becoming the recommended method in v1.18.0. It replaced the old direct TCP connections (which was deprecated as of v1.18.0) to the main process. With Redis, rather than all the workers connecting to the main process, all the workers and the main process connect to Redis, which relays replication commands between processes. This can give a significant CPU saving on the main process and is a prerequisite for upcoming performance improvements. To migrate to Redis add the redis config , and remove the TCP replication listener from config of the master and worker_replication_port from worker config. Note that a HTTP listener with a replication resource is still required.","breadcrumbs":"Upgrading between Synapse Versions » Direct TCP replication is no longer supported: migrate to Redis","id":"135","title":"Direct TCP replication is no longer supported: migrate to Redis"},"136":{"body":"The minimum supported version of poetry is now 1.2. This should only affect those installing from a source checkout.","breadcrumbs":"Upgrading between Synapse Versions » Minimum version of Poetry is now v1.2.0","id":"136","title":"Minimum version of Poetry is now v1.2.0"},"137":{"body":"From the next major release (v1.68.0) installing Synapse from a source checkout will require a recent Rust compiler. Those using packages or pip install matrix-synapse will not be affected. The simplest way of installing Rust is via rustup.rs","breadcrumbs":"Upgrading between Synapse Versions » Rust requirement in the next release","id":"137","title":"Rust requirement in the next release"},"138":{"body":"From the next major release (v1.68.0) Synapse will require SQLite 3.27.0 or higher. Synapse v1.67.0 will be the last major release supporting SQLite versions 3.22 to 3.26. Those using Docker images or Debian packages from Matrix.org will not be affected. If you have installed from source, you should check the version of SQLite used by Python with: python -c \"import sqlite3; print(sqlite3.sqlite_version)\" If this is too old, refer to your distribution for advice on upgrading.","breadcrumbs":"Upgrading between Synapse Versions » SQLite version requirement in the next release","id":"138","title":"SQLite version requirement in the next release"},"139":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.66.0","id":"139","title":"Upgrading to v1.66.0"},"14":{"body":"One way to create a new user is to do so from a client like Element . This requires registration to be enabled via the enable_registration setting. Alternatively, you can create new users from the command line. This can be done as follows: If synapse was installed via pip, activate the virtualenv as follows (if Synapse was installed via a prebuilt package, register_new_matrix_user should already be on the search path): cd ~/synapse\nsource env/bin/activate\nsynctl start # if not already running Run the following command: register_new_matrix_user -c homeserver.yaml This will prompt you to add details for the new user, and will then connect to the running Synapse to create the new user. For example: New user localpart: erikj\nPassword:\nConfirm password:\nMake admin [no]:\nSuccess! This process uses a setting registration_shared_secret , which is shared between Synapse itself and the register_new_matrix_user script. It doesn't matter what it is (a random value is generated by --generate-config), but it should be kept secret, as anyone with knowledge of it can register users, including admin accounts, on your server even if enable_registration is false.","breadcrumbs":"Installation » Registering a user","id":"14","title":"Registering a user"},"140":{"body":"As of this version, Synapse no longer allows the tasks of verifying email address ownership, and password reset confirmation, to be delegated to an identity server. This removal was previously planned for Synapse 1.64.0, but was delayed until now to give homeserver administrators more notice of the change. To continue to allow users to add email addresses to their homeserver accounts, and perform password resets, make sure that Synapse is configured with a working email server in the email configuration section (including, at a minimum, a notif_from setting.) Specifying an email setting under account_threepid_delegates will now cause an error at startup.","breadcrumbs":"Upgrading between Synapse Versions » Delegation of email validation no longer supported","id":"140","title":"Delegation of email validation no longer supported"},"141":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.64.0","id":"141","title":"Upgrading to v1.64.0"},"142":{"body":"Synapse v1.66.0 will remove the ability to delegate the tasks of verifying email address ownership, and password reset confirmation, to an identity server. If you require your homeserver to verify e-mail addresses or to support password resets via e-mail, please configure your homeserver with SMTP access so that it can send e-mails on its own behalf. Consult the configuration documentation for more information. The option that will be removed is account_threepid_delegates.email.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the ability to delegate e-mail verification to identity servers","id":"142","title":"Deprecation of the ability to delegate e-mail verification to identity servers"},"143":{"body":"Synapse now includes a flag indicating if an event is an outlier when replicating it to other workers. This is a forwards- and backwards-incompatible change: v1.63 and workers cannot process events replicated by v1.64 workers, and vice versa. Once all workers are upgraded to v1.64 (or downgraded to v1.63), event replication will resume as normal.","breadcrumbs":"Upgrading between Synapse Versions » Changes to the event replication streams","id":"143","title":"Changes to the event replication streams"},"144":{"body":"frozendict 2.3.3 has recently been released, which fixes a memory leak that occurs during /sync requests. We advise server administrators who installed Synapse via pip to upgrade frozendict with pip install --upgrade frozendict. The Docker image matrixdotorg/synapse and the Debian packages from packages.matrix.org already include the updated library.","breadcrumbs":"Upgrading between Synapse Versions » frozendict release","id":"144","title":"frozendict release"},"145":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.62.0","id":"145","title":"Upgrading to v1.62.0"},"146":{"body":"As a followup to changes in v1.60.0, the following spam-checker callbacks have changed signature: user_may_join_room user_may_invite user_may_send_3pid_invite user_may_create_room user_may_create_room_alias user_may_publish_room check_media_file_for_spam For each of these methods, the previous callback signature has been deprecated. Whereas callbacks used to return bool, they should now return Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\"]. For instance, if your module implements user_may_join_room as follows: async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool) if ...: # Request is spam return False # Request is not spam return True you should rewrite it as follows: async def user_may_join_room(self, user_id: str, room_id: str, is_invited: bool) if ...: # Request is spam, mark it as forbidden (you may use some more precise error # code if it is useful). return synapse.module_api.errors.Codes.FORBIDDEN # Request is not spam, mark it as such. return synapse.module_api.NOT_SPAM","breadcrumbs":"Upgrading between Synapse Versions » New signatures for spam checker callbacks","id":"146","title":"New signatures for spam checker callbacks"},"147":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.61.0","id":"147","title":"Upgrading to v1.61.0"},"148":{"body":"This release of Synapse will remove deprecated community/groups from codebase.","breadcrumbs":"Upgrading between Synapse Versions » Removal of deprecated community/groups","id":"148","title":"Removal of deprecated community/groups"},"149":{"body":"For those who have deployed workers, following worker endpoints will no longer exist and they can be removed from the reverse proxy configuration: ^/_matrix/federation/v1/get_groups_publicised$ ^/_matrix/client/(r0|v3|unstable)/joined_groups$ ^/_matrix/client/(r0|v3|unstable)/publicised_groups$ ^/_matrix/client/(r0|v3|unstable)/publicised_groups/ ^/_matrix/federation/v1/groups/ ^/_matrix/client/(r0|v3|unstable)/groups/","breadcrumbs":"Upgrading between Synapse Versions » Worker endpoints","id":"149","title":"Worker endpoints"},"15":{"body":"For reliable VoIP calls to be routed via this homeserver, you MUST configure a TURN server. See TURN setup for details.","breadcrumbs":"Installation » Setting up a TURN server","id":"15","title":"Setting up a TURN server"},"150":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.60.0","id":"150","title":"Upgrading to v1.60.0"},"151":{"body":"This release of Synapse will add a unique index to the state_group_edges table, in order to prevent accidentally introducing duplicate information (for example, because a database backup was restored multiple times). Duplicate rows being present in this table could cause drastic performance problems; see issue 11779 for more details. If your Synapse database already has had duplicate rows introduced into this table, this could fail, with either of these errors: On Postgres: synapse.storage.background_updates - 623 - INFO - background_updates-0 - Adding index state_group_edges_unique_idx to state_group_edges\nsynapse.storage.background_updates - 282 - ERROR - background_updates-0 - Error doing update\n...\npsycopg2.errors.UniqueViolation: could not create unique index \"state_group_edges_unique_idx\"\nDETAIL: Key (state_group, prev_state_group)=(2, 1) is duplicated. (The numbers may be different.) On SQLite: synapse.storage.background_updates - 623 - INFO - background_updates-0 - Adding index state_group_edges_unique_idx to state_group_edges\nsynapse.storage.background_updates - 282 - ERROR - background_updates-0 - Error doing update\n...\nsqlite3.IntegrityError: UNIQUE constraint failed: state_group_edges.state_group, state_group_edges.prev_state_group Expand this section for steps to resolve this problem","breadcrumbs":"Upgrading between Synapse Versions » Adding a new unique index to state_group_edges could fail if your database is corrupted","id":"151","title":"Adding a new unique index to state_group_edges could fail if your database is corrupted"},"152":{"body":"Connect to your database with psql. BEGIN;\nDELETE FROM state_group_edges WHERE (ctid, state_group, prev_state_group) IN ( SELECT row_id, state_group, prev_state_group FROM ( SELECT ctid AS row_id, MIN(ctid) OVER (PARTITION BY state_group, prev_state_group) AS min_row_id, state_group, prev_state_group FROM state_group_edges ) AS t1 WHERE row_id <> min_row_id\n);\nCOMMIT;","breadcrumbs":"Upgrading between Synapse Versions » On Postgres","id":"152","title":"On Postgres"},"153":{"body":"At the command-line, use sqlite3 path/to/your-homeserver-database.db: BEGIN;\nDELETE FROM state_group_edges WHERE (rowid, state_group, prev_state_group) IN ( SELECT row_id, state_group, prev_state_group FROM ( SELECT rowid AS row_id, MIN(rowid) OVER (PARTITION BY state_group, prev_state_group) AS min_row_id, state_group, prev_state_group FROM state_group_edges ) WHERE row_id <> min_row_id\n);\nCOMMIT;","breadcrumbs":"Upgrading between Synapse Versions » On SQLite","id":"153","title":"On SQLite"},"154":{"body":"This comment on issue 11779 has queries that can be used to check a database for this problem in advance.","breadcrumbs":"Upgrading between Synapse Versions » For more details","id":"154","title":"For more details"},"155":{"body":"The previous signature has been deprecated. Whereas check_event_for_spam callbacks used to return Union[str, bool], they should now return Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\"]. This is part of an ongoing refactoring of the SpamChecker API to make it less ambiguous and more powerful. If your module implements check_event_for_spam as follows: async def check_event_for_spam(event): if ...: # Event is spam return True # Event is not spam return False you should rewrite it as follows: async def check_event_for_spam(event): if ...: # Event is spam, mark it as forbidden (you may use some more precise error # code if it is useful). return synapse.module_api.errors.Codes.FORBIDDEN # Event is not spam, mark it as such. return synapse.module_api.NOT_SPAM","breadcrumbs":"Upgrading between Synapse Versions » New signature for the spam checker callback check_event_for_spam","id":"155","title":"New signature for the spam checker callback check_event_for_spam"},"156":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.59.0","id":"156","title":"Upgrading to v1.59.0"},"157":{"body":"The names of user devices are no longer visible to users on other homeservers by default. Device IDs are unaffected, as these are necessary to facilitate end-to-end encryption. To re-enable this functionality, set the allow_device_name_lookup_over_federation homeserver config option to true.","breadcrumbs":"Upgrading between Synapse Versions » Device name lookup over federation has been disabled by default","id":"157","title":"Device name lookup over federation has been disabled by default"},"158":{"body":"The synapse.app.appservice worker application type allowed you to configure a single worker to use to notify application services of new events, as long as this functionality was disabled on the main process with notify_appservices: False. Further, the synapse.app.user_dir worker application type allowed you to configure a single worker to be responsible for updating the user directory, as long as this was disabled on the main process with update_user_directory: False. To unify Synapse's worker types, the synapse.app.appservice worker application type and the notify_appservices configuration option have been deprecated. The synapse.app.user_dir worker application type and update_user_directory configuration option have also been deprecated. To get the same functionality as was provided by the deprecated options, it's now recommended that the synapse.app.generic_worker worker application type is used and that the notify_appservices_from_worker and/or update_user_directory_from_worker options are set to the name of a worker. For the time being, the old options can be used alongside the new options to make it easier to transition between the two configurations, however please note that: the options must not contradict each other (otherwise Synapse won't start); and the notify_appservices and update_user_directory options will be removed in a future release of Synapse. Please see the Notifying Application Services and Updating the User Directory sections of the worker documentation for more information.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the synapse.app.appservice and synapse.app.user_dir worker application types","id":"158","title":"Deprecation of the synapse.app.appservice and synapse.app.user_dir worker application types"},"159":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.58.0","id":"159","title":"Upgrading to v1.58.0"},"16":{"body":"Synapse includes support for previewing URLs, which is disabled by default. To turn it on you must enable the url_preview_enabled: True config parameter and explicitly specify the IP ranges that Synapse is not allowed to spider for previewing in the url_preview_ip_range_blacklist configuration parameter. This is critical from a security perspective to stop arbitrary Matrix users spidering 'internal' URLs on your network. At the very least we recommend that your loopback and RFC1918 IP addresses are blacklisted. 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.","breadcrumbs":"Installation » URL previews","id":"16","title":"URL previews"},"160":{"body":"The non-standard groups/communities feature in Synapse has been disabled by default and will be removed in Synapse v1.61.0.","breadcrumbs":"Upgrading between Synapse Versions » Groups/communities feature has been disabled by default","id":"160","title":"Groups/communities feature has been disabled by default"},"161":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.57.0","id":"161","title":"Upgrading to v1.57.0"},"162":{"body":"Synapse v1.57.0 includes a change to the way transaction IDs are managed for application services. If your deployment uses a dedicated worker for application service traffic, it must be stopped when the database is upgraded (which normally happens when the main process is upgraded), to ensure the change is made safely without any risk of reusing transaction IDs. Deployments which do not use separate worker processes can be upgraded as normal. Similarly, deployments where no application services are in use can be upgraded as normal. Recovering from an incorrect upgrade If the database schema is upgraded without stopping the worker responsible for AS traffic, then the following error may be given when attempting to start a Synapse worker or master process: ********************************************************************************** Error during initialisation: Postgres sequence 'application_services_txn_id_seq' is inconsistent with associated table 'application_services_txns'. This can happen if Synapse has been downgraded and then upgraded again, or due to a bad migration. To fix this error, shut down Synapse (including any and all workers) and run the following SQL: SELECT setval('application_services_txn_id_seq', ( SELECT GREATEST(MAX(txn_id), 0) FROM application_services_txns )); See docs/postgres.md for more information. There may be more information in the logs.\n********************************************************************************** This error may also be seen if Synapse is downgraded to an earlier version, and then upgraded again to v1.57.0 or later. In either case: Ensure that the worker responsible for AS traffic is stopped. Run the SQL command given in the error message via psql. Synapse should then start correctly.","breadcrumbs":"Upgrading between Synapse Versions » Changes to database schema for application services","id":"162","title":"Changes to database schema for application services"},"163":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.56.0","id":"163","title":"Upgrading to v1.56.0"},"164":{"body":"Synapse will refuse to start if registration is enabled without email, captcha, or token-based verification unless the new config flag enable_registration_without_verification is set to \"true\".","breadcrumbs":"Upgrading between Synapse Versions » Open registration without verification is now disabled by default","id":"164","title":"Open registration without verification is now disabled by default"},"165":{"body":"The non-standard groups/communities feature in Synapse has been deprecated and will be disabled by default in Synapse v1.58.0. You can test disabling it by adding the following to your homeserver configuration: experimental_features: groups_enabled: false","breadcrumbs":"Upgrading between Synapse Versions » Groups/communities feature has been deprecated","id":"165","title":"Groups/communities feature has been deprecated"},"166":{"body":"Synapse now refuses to start when using PostgreSQL with non-C values for COLLATE and CTYPE unless the config flag allow_unsafe_locale, found in the database section of the configuration file, is set to true. See the PostgreSQL documentation for more information and instructions on how to fix a database with incorrect values.","breadcrumbs":"Upgrading between Synapse Versions » Change in behaviour for PostgreSQL databases with unsafe locale","id":"166","title":"Change in behaviour for PostgreSQL databases with unsafe locale"},"167":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.55.0","id":"167","title":"Upgrading to v1.55.0"},"168":{"body":"The synctl script has been made an entry point and no longer exists at the root of Synapse's source tree. If you wish to use synctl to manage your homeserver, you should invoke synctl directly, e.g. synctl start instead of ./synctl start or /path/to/synctl start. You will need to ensure synctl is on your PATH. This is automatically the case when using Debian packages or docker images provided by Matrix.org. When installing from a wheel, sdist, or PyPI, a synctl executable is added to your Python installation's bin. This should be on your PATH automatically, though you might need to activate a virtual environment depending on how you installed Synapse.","breadcrumbs":"Upgrading between Synapse Versions » synctl script has been moved","id":"168","title":"synctl script has been moved"},"169":{"body":"Synapse v1.55.0 drops support for Mjolnir 1.3.1 and earlier. If you use the Mjolnir module to moderate your homeserver, please upgrade Mjolnir to version 1.3.2 or later before upgrading Synapse.","breadcrumbs":"Upgrading between Synapse Versions » Compatibility dropped for Mjolnir 1.3.1 and earlier","id":"169","title":"Compatibility dropped for Mjolnir 1.3.1 and earlier"},"17":{"body":"Don't forget to take backups of your new server!","breadcrumbs":"Installation » Backups","id":"17","title":"Backups"},"170":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.54.0","id":"170","title":"Upgrading to v1.54.0"},"171":{"body":"This release removes support for the structured: true logging configuration which was deprecated in Synapse v1.23.0. If your logging configuration contains structured: true then it should be modified based on the structured logging documentation .","breadcrumbs":"Upgrading between Synapse Versions » Legacy structured logging configuration removal","id":"171","title":"Legacy structured logging configuration removal"},"172":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.53.0","id":"172","title":"Upgrading to v1.53.0"},"173":{"body":"Per the deprecation notice in Synapse v1.51.0, listeners of type webclient are no longer supported and configuring them is a now a configuration error. Configuring a non-HTTP(S) web_client_location configuration is is now a configuration error. Since the webclient listener is no longer supported, this setting only applies to the root path / of Synapse's web server and no longer the /_matrix/client/ path.","breadcrumbs":"Upgrading between Synapse Versions » Dropping support for webclient listeners and non-HTTP(S) web_client_location","id":"173","title":"Dropping support for webclient listeners and non-HTTP(S) web_client_location"},"174":{"body":"The unstable validity-check endpoint for the Registration Tokens feature has been stabilised and moved from: /_matrix/client/unstable/org.matrix.msc3231/register/org.matrix.msc3231.login.registration_token/validity to: /_matrix/client/v1/register/m.login.registration_token/validity Please update any relevant reverse proxy or firewall configurations appropriately.","breadcrumbs":"Upgrading between Synapse Versions » Stablisation of MSC3231","id":"174","title":"Stablisation of MSC3231"},"175":{"body":"Formerly, entries in the cache were not evicted regardless of whether they were accessed after storing. This behavior has now changed. By default entries in the cache are now evicted after 30m of not being accessed. To change the default behavior, go to the caches section of the config and change the expire_caches and cache_entry_ttl flags as necessary. Please note that these flags replace the expiry_time flag in the config. The expiry_time flag will still continue to work, but it has been deprecated and will be removed in the future.","breadcrumbs":"Upgrading between Synapse Versions » Time-based cache expiry is now enabled by default","id":"175","title":"Time-based cache expiry is now enabled by default"},"176":{"body":"The capabilities of MSC3283 from the REST API /_matrix/client/r0/capabilities becomes stable. The old capabilities org.matrix.msc3283.set_displayname, org.matrix.msc3283.set_avatar_url and org.matrix.msc3283.3pid_changes are deprecated and scheduled to be removed in Synapse v1.54.0. The new capabilities m.set_displayname, m.set_avatar_url and m.3pid_changes are now active by default.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of capability org.matrix.msc3283.*","id":"176","title":"Deprecation of capability org.matrix.msc3283.*"},"177":{"body":"As announced with the release of Synapse 1.47.0 , the deprecated user_may_create_room_with_invites module callback has been removed. Modules relying on it can instead implement user_may_invite and use the get_room_state module API to infer whether the invite is happening while creating a room (see this function as an example). Alternately, modules can also implement on_create_room .","breadcrumbs":"Upgrading between Synapse Versions » Removal of user_may_create_room_with_invites","id":"177","title":"Removal of user_may_create_room_with_invites"},"178":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.52.0","id":"178","title":"Upgrading to v1.52.0"},"179":{"body":"Note that Twisted 22.1.0 has recently been released, which fixes a security issue within the Twisted library. We do not believe Synapse is affected by this vulnerability, though we advise server administrators who installed Synapse via pip to upgrade Twisted with pip install --upgrade Twisted treq as a matter of good practice. The Docker image matrixdotorg/synapse and the Debian packages from packages.matrix.org are using the updated library.","breadcrumbs":"Upgrading between Synapse Versions » Twisted security release","id":"179","title":"Twisted security release"},"18":{"body":"pip seems to leak lots of memory during installation. For instance, a Linux host with 512MB of RAM may run out of memory whilst installing Twisted. If this happens, you will have to individually install the dependencies which are failing, e.g.: pip install twisted If you have any other problems, feel free to ask in #synapse:matrix.org .","breadcrumbs":"Installation » Troubleshooting Installation","id":"18","title":"Troubleshooting Installation"},"180":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.51.0","id":"180","title":"Upgrading to v1.51.0"},"181":{"body":"Listeners of type webclient are deprecated and scheduled to be removed in Synapse v1.53.0. Similarly, a non-HTTP(S) web_client_location configuration is deprecated and will become a configuration error in Synapse v1.53.0.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of webclient listeners and non-HTTP(S) web_client_location","id":"181","title":"Deprecation of webclient listeners and non-HTTP(S) web_client_location"},"182":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.50.0","id":"182","title":"Upgrading to v1.50.0"},"183":{"body":"In line with our deprecation policy , we've dropped support for Python 3.6 and PostgreSQL 9.6, as they are no longer supported upstream. This release of Synapse requires Python 3.7+ and PostgreSQL 10+.","breadcrumbs":"Upgrading between Synapse Versions » Dropping support for old Python and Postgres versions","id":"183","title":"Dropping support for old Python and Postgres versions"},"184":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.47.0","id":"184","title":"Upgrading to v1.47.0"},"185":{"body":"The following admin APIs were deprecated in Synapse 1.34 (released on 2021-05-17) and have now been removed: POST /_synapse/admin/v1//delete Any scripts still using the above APIs should be converted to use the Delete Room API .","breadcrumbs":"Upgrading between Synapse Versions » Removal of old Room Admin API","id":"185","title":"Removal of old Room Admin API"},"186":{"body":"The user_may_create_room_with_invites is deprecated and will be removed in a future version of Synapse. Modules implementing this callback can instead implement user_may_invite and use the get_room_state module API method to infer whether the invite is happening in the context of creating a room. We plan to remove this callback in January 2022.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the user_may_create_room_with_invites module callback","id":"186","title":"Deprecation of the user_may_create_room_with_invites module callback"},"187":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.45.0","id":"187","title":"Upgrading to v1.45.0"},"188":{"body":"Media storage provider modules that read from the Synapse configuration object (i.e. that read the value of hs.config.[...]) now need to specify the configuration section they're reading from. This means that if a module reads the value of e.g. hs.config.media_store_path, it needs to replace it with hs.config.media.media_store_path.","breadcrumbs":"Upgrading between Synapse Versions » Changes required to media storage provider modules when reading from the Synapse configuration object","id":"188","title":"Changes required to media storage provider modules when reading from the Synapse configuration object"},"189":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.44.0","id":"189","title":"Upgrading to v1.44.0"},"19":{"body":"The minimum supported version of PostgreSQL is determined by the Dependency Deprecation Policy .","breadcrumbs":"Using Postgres » Using Postgres","id":"19","title":"Using Postgres"},"190":{"body":"The url_cache/ and url_cache_thumbnails/ directories in the media store are no longer mirrored to storage providers. These two directories can be safely deleted from any configured storage providers to reclaim space.","breadcrumbs":"Upgrading between Synapse Versions » The URL preview cache is no longer mirrored to storage providers","id":"190","title":"The URL preview cache is no longer mirrored to storage providers"},"191":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.43.0","id":"191","title":"Upgrading to v1.43.0"},"192":{"body":"The available worker applications documentation has been updated to reflect that calls to the /spaces, /hierarchy, and /summary endpoints can now be routed to workers for both client API and federation requests.","breadcrumbs":"Upgrading between Synapse Versions » The spaces summary APIs can now be handled by workers","id":"192","title":"The spaces summary APIs can now be handled by workers"},"193":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.42.0","id":"193","title":"Upgrading to v1.42.0"},"194":{"body":"The following admin APIs were deprecated in Synapse 1.25 (released on 2021-01-13) and have now been removed: POST /_synapse/admin/v1/purge_room POST /_synapse/admin/v1/shutdown_room/ Any scripts still using the above APIs should be converted to use the Delete Room API .","breadcrumbs":"Upgrading between Synapse Versions » Removal of old Room Admin API","id":"194","title":"Removal of old Room Admin API"},"195":{"body":"This may affect you if you make use of custom HTML templates for the reCAPTCHA (synapse/res/templates/recaptcha.html) or terms (synapse/res/templates/terms.html) fallback pages. The template is now provided an error variable if the authentication process failed. See the default templates linked above for an example.","breadcrumbs":"Upgrading between Synapse Versions » User-interactive authentication fallback templates can now display errors","id":"195","title":"User-interactive authentication fallback templates can now display errors"},"196":{"body":"Users will stop receiving message updates via email for addresses that were once, but not still, linked to their account.","breadcrumbs":"Upgrading between Synapse Versions » Removal of out-of-date email pushers","id":"196","title":"Removal of out-of-date email pushers"},"197":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.41.0","id":"197","title":"Upgrading to v1.41.0"},"198":{"body":"Since Synapse 1.6.0 (2019-11-26) you can set a proxy for outbound HTTP requests via http_proxy/https_proxy environment variables. This proxy was set for: push url previews phone-home stats recaptcha validation CAS auth validation OpenID Connect Federation (checking public key revocation) In this version we have added support for outbound requests for: Outbound federation Downloading remote media Fetching public keys of other servers These requests use the same proxy configuration. If you have a proxy configuration we recommend to verify the configuration. It may be necessary to adjust the no_proxy environment variable. See using a forward proxy with Synapse documentation for details.","breadcrumbs":"Upgrading between Synapse Versions » Add support for routing outbound HTTP requests via a proxy for federation","id":"198","title":"Add support for routing outbound HTTP requests via a proxy for federation"},"199":{"body":"The template_dir settings in the sso, account_validity and email sections of the configuration file are now deprecated. Server admins should use the new templates.custom_template_directory setting in the configuration file and use one single custom template directory for all aforementioned features. Template file names remain unchanged. See the related documentation for more information and examples. We plan to remove support for these settings in October 2021.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of template_dir","id":"199","title":"Deprecation of template_dir"},"2":{"body":"Contributions are welcome! Synapse is primarily written in Python . As a developer, you may be interested in the following documentation: Read the Contributing Guide . It is meant to walk new contributors through the process of developing and submitting a change to the Synapse codebase (which is hosted on GitHub ). Set up your development environment , then learn how to lint and test your code. Look at the issue tracker for bugs to fix or features to add. If you're new, it may be best to start with those labeled good first issue . Understand how Synapse is built , how to migrate database schemas , learn about federation and how to set up a local federation for development. We like to keep our git history clean. Learn how to do so! And finally, contribute to this documentation! The source for which is located here .","breadcrumbs":"Welcome and Overview » Developing on Synapse","id":"2","title":"Developing on Synapse"},"20":{"body":"Synapse will require the python postgres client library in order to connect to a postgres database. If you are using the matrix.org debian/ubuntu packages , the necessary python library will already be installed, but you will need to ensure the low-level postgres library is installed, which you can do with apt install libpq5. For other pre-built packages, please consult the documentation from the relevant package. If you installed synapse in a virtualenv , you can install the library with: ~/synapse/env/bin/pip install \"matrix-synapse[postgres]\" (substituting the path to your virtualenv for ~/synapse/env, if you used a different path). You will require the postgres development files. These are in the libpq-dev package on Debian-derived distributions.","breadcrumbs":"Using Postgres » Install postgres client libraries","id":"20","title":"Install postgres client libraries"},"200":{"body":"The media repository worker documentation has been updated to reflect that calls to /_synapse/admin/v1/users/{userId}/media must now be handled by media repository workers. This is due to the new DELETE method of this endpoint modifying the media store.","breadcrumbs":"Upgrading between Synapse Versions » /_synapse/admin/v1/users/{userId}/media must be handled by media workers","id":"200","title":"/_synapse/admin/v1/users/{userId}/media must be handled by media workers"},"201":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.39.0","id":"201","title":"Upgrading to v1.39.0"},"202":{"body":"The current third-party rules module interface is deprecated in favour of the new generic modules system introduced in Synapse v1.37.0. Authors of third-party rules modules can refer to this documentation to update their modules. Synapse administrators can refer to this documentation to update their configuration once the modules they are using have been updated. We plan to remove support for the current third-party rules interface in September 2021.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the current third-party rules module interface","id":"202","title":"Deprecation of the current third-party rules module interface"},"203":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.38.0","id":"203","title":"Upgrading to v1.38.0"},"204":{"body":"This release includes a database schema update which requires re-indexing one of the larger tables in the database, events. This could result in increased disk I/O for several hours or days after upgrading while the migration completes. Furthermore, because we have to keep the old indexes until the new indexes are ready, it could result in a significant, temporary, increase in disk space. To get a rough idea of the disk space required, check the current size of one of the indexes. For example, from a psql shell, run the following sql: SELECT pg_size_pretty(pg_relation_size('events_order_room')); We need to rebuild four indexes, so you will need to multiply this result by four to give an estimate of the disk space required. For example, on one particular server: synapse=# select pg_size_pretty(pg_relation_size('events_order_room')); pg_size_pretty\n---------------- 288 MB\n(1 row) On this server, it would be wise to ensure that at least 1152MB are free. The additional disk space will be freed once the migration completes. SQLite databases are unaffected by this change.","breadcrumbs":"Upgrading between Synapse Versions » Re-indexing of events table on Postgres databases","id":"204","title":"Re-indexing of events table on Postgres databases"},"205":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.37.0","id":"205","title":"Upgrading to v1.37.0"},"206":{"body":"The current spam checker interface is deprecated in favour of a new generic modules system. Authors of spam checker modules can refer to [this documentation](modules/porting_legacy_module.md to update their modules. Synapse administrators can refer to this documentation to update their configuration once the modules they are using have been updated. We plan to remove support for the current spam checker interface in August 2021. More module interfaces will be ported over to this new generic system in future versions of Synapse.","breadcrumbs":"Upgrading between Synapse Versions » Deprecation of the current spam checker interface","id":"206","title":"Deprecation of the current spam checker interface"},"207":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.34.0","id":"207","title":"Upgrading to v1.34.0"},"208":{"body":"The room_invite_state_types configuration setting has been deprecated and replaced with room_prejoin_state. See the sample configuration file . If you have set room_invite_state_types to the default value you should simply remove it from your configuration file. The default value used to be: room_invite_state_types: - \"m.room.join_rules\" - \"m.room.canonical_alias\" - \"m.room.avatar\" - \"m.room.encryption\" - \"m.room.name\" If you have customised this value, you should remove room_invite_state_types and configure room_prejoin_state instead.","breadcrumbs":"Upgrading between Synapse Versions » room_invite_state_types configuration setting","id":"208","title":"room_invite_state_types configuration setting"},"209":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.33.0","id":"209","title":"Upgrading to v1.33.0"},"21":{"body":"Assuming your PostgreSQL database user is called postgres, first authenticate as the database user with: su - postgres\n# Or, if your system uses sudo to get administrative rights\nsudo -u postgres bash Then, create a postgres user and a database with: # this will prompt for a password for the new user\ncreateuser --pwprompt synapse_user createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse The above will create a user called synapse_user, and a database called synapse. Note that the PostgreSQL database must have the correct encoding set (as shown above), otherwise it will not be able to store UTF8 strings. You may need to enable password authentication so synapse_user can connect to the database. See https://www.postgresql.org/docs/current/auth-pg-hba-conf.html .","breadcrumbs":"Using Postgres » Set up database","id":"21","title":"Set up database"},"210":{"body":"This may affect you if you have enabled the account validity feature, and have made use of a custom HTML template specified by the account_validity.template_dir or account_validity.account_renewed_html_path Synapse config options. The template can now accept an expiration_ts variable, which represents the unix timestamp in milliseconds for the future date of which their account has been renewed until. See the default template for an example of usage. ALso note that a new HTML template, account_previously_renewed.html, has been added. This is is shown to users when they attempt to renew their account with a valid renewal token that has already been used before. The default template contents can been found here , and can also accept an expiration_ts variable. This template replaces the error message users would previously see upon attempting to use a valid renewal token more than once.","breadcrumbs":"Upgrading between Synapse Versions » Account Validity HTML templates can now display a user's expiration date","id":"210","title":"Account Validity HTML templates can now display a user's expiration date"},"211":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.32.0","id":"211","title":"Upgrading to v1.32.0"},"212":{"body":"This release introduces a regression that can overwhelm connected Prometheus instances. This issue is not present in Synapse v1.32.0rc1. If you have been affected, please downgrade to 1.31.0. You then may need to remove excess writeahead logs in order for Prometheus to recover. Instructions for doing so are provided here .","breadcrumbs":"Upgrading between Synapse Versions » Regression causing connected Prometheus instances to become overwhelmed","id":"212","title":"Regression causing connected Prometheus instances to become overwhelmed"},"213":{"body":"In line with our deprecation policy , we've dropped support for Python 3.5 and PostgreSQL 9.5, as they are no longer supported upstream. This release of Synapse requires Python 3.6+ and PostgreSQL 9.6+ or SQLite 3.22+.","breadcrumbs":"Upgrading between Synapse Versions » Dropping support for old Python, Postgres and SQLite versions","id":"213","title":"Dropping support for old Python, Postgres and SQLite versions"},"214":{"body":"The deprecated v1 \"list accounts\" admin API (GET /_synapse/admin/v1/users/) has been removed in this version. The v2 list accounts API has been available since Synapse 1.7.0 (2019-12-13), and is accessible under GET /_synapse/admin/v2/users. The deprecation of the old endpoint was announced with Synapse 1.28.0 (released on 2021-02-25).","breadcrumbs":"Upgrading between Synapse Versions » Removal of old List Accounts Admin API","id":"214","title":"Removal of old List Accounts Admin API"},"215":{"body":"In compliance with the Application Service spec , Application Services are now required to use the m.login.application_service type when registering users via the /_matrix/client/r0/register endpoint. This behaviour was deprecated in Synapse v1.30.0. Please ensure your Application Services are up to date.","breadcrumbs":"Upgrading between Synapse Versions » Application Services must use type m.login.application_service when registering users","id":"215","title":"Application Services must use type m.login.application_service when registering users"},"216":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.29.0","id":"216","title":"Upgrading to v1.29.0"},"217":{"body":"When using Synapse with a reverse proxy (in particular, when using the x_forwarded option on an HTTP listener), Synapse now expects to receive an X-Forwarded-Proto header on incoming HTTP requests. If it is not set, Synapse will log a warning on each received request. To avoid the warning, administrators using a reverse proxy should ensure that the reverse proxy sets X-Forwarded-Proto header to https or http to indicate the protocol used by the client. Synapse also requires the Host header to be preserved. See the reverse proxy documentation , where the example configurations have been updated to show how to set these headers. (Users of Caddy are unaffected, since we believe it sets X-Forwarded-Proto by default.)","breadcrumbs":"Upgrading between Synapse Versions » Requirement for X-Forwarded-Proto header","id":"217","title":"Requirement for X-Forwarded-Proto header"},"218":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.27.0","id":"218","title":"Upgrading to v1.27.0"},"219":{"body":"This version changes the URI used for callbacks from OAuth2 and SAML2 identity providers: If your server is configured for single sign-on via an OpenID Connect or OAuth2 identity provider, you will need to add [synapse public baseurl]/_synapse/client/oidc/callback to the list of permitted \"redirect URIs\" at the identity provider. See the OpenID docs for more information on setting up OpenID Connect. If your server is configured for single sign-on via a SAML2 identity provider, you will need to add [synapse public baseurl]/_synapse/client/saml2/authn_response as a permitted \"ACS location\" (also known as \"allowed callback URLs\") at the identity provider. The \"Issuer\" in the \"AuthnRequest\" to the SAML2 identity provider is also updated to [synapse public baseurl]/_synapse/client/saml2/metadata.xml. If your SAML2 identity provider uses this property to validate or otherwise identify Synapse, its configuration will need to be updated to use the new URL. Alternatively you could create a new, separate \"EntityDescriptor\" in your SAML2 identity provider with the new URLs and leave the URLs in the existing \"EntityDescriptor\" as they were.","breadcrumbs":"Upgrading between Synapse Versions » Changes to callback URI for OAuth2 / OpenID Connect and SAML2","id":"219","title":"Changes to callback URI for OAuth2 / OpenID Connect and SAML2"},"22":{"body":"When you are ready to start using PostgreSQL, edit the database section in your config file to match the following lines: database: name: psycopg2 args: user: password: dbname: host: cp_min: 5 cp_max: 10 All key, values in args are passed to the psycopg2.connect(..) function, except keys beginning with cp_, which are consumed by the twisted adbapi connection pool. See the libpq documentation for a list of options which can be passed. You should consider tuning the args.keepalives_* options if there is any danger of the connection between your homeserver and database dropping, otherwise Synapse may block for an extended period while it waits for a response from the database server. Example values might be: database: args: # ... as above # seconds of inactivity after which TCP should send a keepalive message to the server keepalives_idle: 10 # the number of seconds after which a TCP keepalive message that is not # acknowledged by the server should be retransmitted keepalives_interval: 10 # the number of TCP keepalives that can be lost before the client's connection # to the server is considered dead keepalives_count: 3","breadcrumbs":"Using Postgres » Synapse config","id":"22","title":"Synapse config"},"220":{"body":"The HTML templates for SSO and email notifications now have Jinja2's autoescape enabled for files ending in .html, .htm, and .xml. If you have customised these templates and see issues when viewing them you might need to update them. It is expected that most configurations will need no changes. If you have customised the templates names for these templates, it is recommended to verify they end in .html to ensure autoescape is enabled. The above applies to the following templates: add_threepid.html add_threepid_failure.html add_threepid_success.html notice_expiry.html notice_expiry.html notif_mail.html (which, by default, includes room.html and notif.html) password_reset.html password_reset_confirmation.html password_reset_failure.html password_reset_success.html registration.html registration_failure.html registration_success.html sso_account_deactivated.html sso_auth_bad_user.html sso_auth_confirm.html sso_auth_success.html sso_error.html sso_login_idp_picker.html sso_redirect_confirm.html","breadcrumbs":"Upgrading between Synapse Versions » Changes to HTML templates","id":"220","title":"Changes to HTML templates"},"221":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.26.0","id":"221","title":"Upgrading to v1.26.0"},"222":{"body":"v1.26.0 includes a lot of large changes. If something problematic occurs, you may want to roll-back to a previous version of Synapse. Because v1.26.0 also includes a new database schema version, reverting that version is also required alongside the generic rollback instructions mentioned above. In short, to roll back to v1.25.0 you need to: Stop the server Decrease the schema version in the database: UPDATE schema_version SET version = 58; Delete the ignored users & chain cover data: DROP TABLE IF EXISTS ignored_users;\nUPDATE rooms SET has_auth_chain_index = false; For PostgreSQL run: TRUNCATE event_auth_chain_links;\nTRUNCATE event_auth_chains; For SQLite run: DELETE FROM event_auth_chain_links;\nDELETE FROM event_auth_chains; Mark the deltas as not run (so they will re-run on upgrade). DELETE FROM applied_schema_deltas WHERE version = 59 AND file = \"59/01ignored_user.py\";\nDELETE FROM applied_schema_deltas WHERE version = 59 AND file = \"59/06chain_cover_index.sql\"; Downgrade Synapse by following the instructions for your installation method in the \"Rolling back to older versions\" section above.","breadcrumbs":"Upgrading between Synapse Versions » Rolling back to v1.25.0 after a failed upgrade","id":"222","title":"Rolling back to v1.25.0 after a failed upgrade"},"223":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.25.0","id":"223","title":"Upgrading to v1.25.0"},"224":{"body":"This is the last release of Synapse which guarantees support with Python 3.5, which passed its upstream End of Life date several months ago. We will attempt to maintain support through March 2021, but without guarantees. In the future, Synapse will follow upstream schedules for ending support of older versions of Python and PostgreSQL. Please upgrade to at least Python 3.6 and PostgreSQL 9.6 as soon as possible.","breadcrumbs":"Upgrading between Synapse Versions » Last release supporting Python 3.5","id":"224","title":"Last release supporting Python 3.5"},"225":{"body":"Synapse v1.25.0 includes new settings, ip_range_blacklist and ip_range_whitelist, for controlling outgoing requests from Synapse for federation, identity servers, push, and for checking key validity for third-party invite events. The previous setting, federation_ip_range_blacklist, is deprecated. The new ip_range_blacklist defaults to private IP ranges if it is not defined. If you have never customised federation_ip_range_blacklist it is recommended that you remove that setting. If you have customised federation_ip_range_blacklist you should update the setting name to ip_range_blacklist. If you have a custom push server that is reached via private IP space you may need to customise ip_range_blacklist or ip_range_whitelist.","breadcrumbs":"Upgrading between Synapse Versions » Blacklisting IP ranges","id":"225","title":"Blacklisting IP ranges"},"226":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.24.0","id":"226","title":"Upgrading to v1.24.0"},"227":{"body":"This release allows the OpenID Connect mapping provider to perform normalisation of the localpart of the Matrix ID. This allows for the mapping provider to specify different algorithms, instead of the default way . If your Synapse configuration uses a custom mapping provider (oidc_config.user_mapping_provider.module is specified and not equal to synapse.handlers.oidc_handler.JinjaOidcMappingProvider) then you must ensure that map_user_attributes of the mapping provider performs some normalisation of the localpart returned. To match previous behaviour you can use the map_username_to_mxid_localpart function provided by Synapse. An example is shown below: from synapse.types import map_username_to_mxid_localpart class MyMappingProvider: def map_user_attributes(self, userinfo, token): # ... your custom logic ... sso_user_id = ... localpart = map_username_to_mxid_localpart(sso_user_id) return {\"localpart\": localpart}","breadcrumbs":"Upgrading between Synapse Versions » Custom OpenID Connect mapping provider breaking change","id":"227","title":"Custom OpenID Connect mapping provider breaking change"},"228":{"body":"Historically, the Synapse Admin API has been accessible under: /_matrix/client/api/v1/admin /_matrix/client/unstable/admin /_matrix/client/r0/admin /_synapse/admin/v1 The endpoints with /_matrix/client/* prefixes have been removed as of v1.24.0. The Admin API is now only accessible under: /_synapse/admin/v1 The only exception is the /admin/whois endpoint, which is also available via the client-server API . The deprecation of the old endpoints was announced with Synapse 1.20.0 (released on 2020-09-22) and makes it easier for homeserver admins to lock down external access to the Admin API endpoints.","breadcrumbs":"Upgrading between Synapse Versions » Removal historical Synapse Admin API","id":"228","title":"Removal historical Synapse Admin API"},"229":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.23.0","id":"229","title":"Upgrading to v1.23.0"},"23":{"body":"Postgres uses separate directories for database locations between major versions (typically /var/lib/postgresql//main). Therefore, it is recommended to stop Synapse and other services (MAS, etc) before upgrading Postgres major versions. It is also strongly recommended to back up your database beforehand to ensure no data loss arising from a failed upgrade.","breadcrumbs":"Using Postgres » Postgresql major version upgrades","id":"23","title":"Postgresql major version upgrades"},"230":{"body":"This release deprecates use of the structured: true logging configuration for structured logging. If your logging configuration contains structured: true then it should be modified based on the structured logging documentation . The structured and drains logging options are now deprecated and should be replaced by standard logging configuration of handlers and formatters. A future will release of Synapse will make using structured: true an error.","breadcrumbs":"Upgrading between Synapse Versions » Structured logging configuration breaking changes","id":"230","title":"Structured logging configuration breaking changes"},"231":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.22.0","id":"231","title":"Upgrading to v1.22.0"},"232":{"body":"This release introduces a backwards-incompatible change to modules making use of ThirdPartyEventRules in Synapse. If you make use of a module defined under the third_party_event_rules config option, please make sure it is updated to handle the below change: The http_client argument is no longer passed to modules as they are initialised. Instead, modules are expected to make use of the http_client property on the ModuleApi class. Modules are now passed a module_api argument during initialisation, which is an instance of ModuleApi. ModuleApi instances have a http_client property which acts the same as the http_client argument previously passed to ThirdPartyEventRules modules.","breadcrumbs":"Upgrading between Synapse Versions » ThirdPartyEventRules breaking changes","id":"232","title":"ThirdPartyEventRules breaking changes"},"233":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.21.0","id":"233","title":"Upgrading to v1.21.0"},"234":{"body":"The reverse proxy documentation has been updated to include reverse proxy directives for /_synapse/client/* endpoints. As the user password reset flow now uses endpoints under this prefix, you must update your reverse proxy configurations for user password reset to work . Additionally, note that the Synapse worker documentation has been updated to : state that the /_synapse/client/password_reset/email/submit_token endpoint can be handled by all workers. If you make use of Synapse's worker feature, please update your reverse proxy configuration to reflect this change.","breadcrumbs":"Upgrading between Synapse Versions » Forwarding /_synapse/client through your reverse proxy","id":"234","title":"Forwarding /_synapse/client through your reverse proxy"},"235":{"body":"A new HTML template, password_reset_confirmation.html , has been added to the synapse/res/templates directory. If you are using a custom template directory, you may want to copy the template over and modify it. Note that as of v1.20.0, templates do not need to be included in custom template directories for Synapse to start. The default templates will be used if a custom template cannot be found. This page will appear to the user after clicking a password reset link that has been emailed to them. To complete password reset, the page must include a way to make a POST request to /_synapse/client/password_reset/{medium}/submit_token with the query parameters from the original link, presented as a URL-encoded form. See the file itself for more details.","breadcrumbs":"Upgrading between Synapse Versions » New HTML templates","id":"235","title":"New HTML templates"},"236":{"body":"The saml_error.html template was removed from Synapse and replaced with the sso_error.html template. If your Synapse is configured to use SAML and a custom sso_redirect_confirm_template_dir configuration then any customisations of the saml_error.html template will need to be merged into the sso_error.html template. These templates are similar, but the parameters are slightly different: The msg parameter should be renamed to error_description. There is no longer a code parameter for the response code. A string error parameter is available that includes a short hint of why a user is seeing the error page.","breadcrumbs":"Upgrading between Synapse Versions » Updated Single Sign-on HTML Templates","id":"236","title":"Updated Single Sign-on HTML Templates"},"237":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.18.0","id":"237","title":"Upgrading to v1.18.0"},"238":{"body":"From 10th August 2020, we will no longer publish Docker images with the -py3 tag suffix. The images tagged with the -py3 suffix have been identical to the non-suffixed tags since release 0.99.0, and the suffix is obsolete. On 10th August, we will remove the latest-py3 tag. Existing per-release tags (such as v1.18.0-py3 will not be removed, but no new -py3 tags will be added. Scripts relying on the -py3 suffix will need to be updated.","breadcrumbs":"Upgrading between Synapse Versions » Docker -py3 suffix will be removed in future versions","id":"238","title":"Docker -py3 suffix will be removed in future versions"},"239":{"body":"When setting up worker processes, we now recommend the use of a Redis server for replication. The old direct TCP connection method is deprecated and will be removed in a future release. See the worker documentation for more details.","breadcrumbs":"Upgrading between Synapse Versions » Redis replication is now recommended in lieu of TCP replication","id":"239","title":"Redis replication is now recommended in lieu of TCP replication"},"24":{"body":"Don't forget to back up your database!","breadcrumbs":"Using Postgres » Backups","id":"24","title":"Backups"},"240":{"body":"This version includes a database update which is run as part of the upgrade, and which may take a couple of minutes in the case of a large server. Synapse will not respond to HTTP requests while this update is taking place.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.14.0","id":"240","title":"Upgrading to v1.14.0"},"241":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.13.0","id":"241","title":"Upgrading to v1.13.0"},"242":{"body":"A bug was introduced in Synapse 1.4.0 which could cause the room directory to be incomplete or empty if Synapse was upgraded directly from v1.2.1 or earlier, to versions between v1.4.0 and v1.12.x. This will not be a problem for Synapse installations which were: : - created at v1.4.0 or later, - upgraded via v1.3.x, or - upgraded straight from v1.2.1 or earlier to v1.13.0 or later. If completeness of the room directory is a concern, installations which are affected can be repaired as follows: Run the following sql from a psql or sqlite3 console: INSERT INTO background_updates (update_name, progress_json, depends_on) VALUES ('populate_stats_process_rooms', '{}', 'current_state_events_membership'); INSERT INTO background_updates (update_name, progress_json, depends_on) VALUES ('populate_stats_process_users', '{}', 'populate_stats_process_rooms'); Restart synapse.","breadcrumbs":"Upgrading between Synapse Versions » Incorrect database migration in old synapse versions","id":"242","title":"Incorrect database migration in old synapse versions"},"243":{"body":"New templates (sso_auth_confirm.html, sso_auth_success.html, and sso_account_deactivated.html) were added to Synapse. If your Synapse is configured to use SSO and a custom sso_redirect_confirm_template_dir configuration then these templates will need to be copied from synapse/res/templates into that directory.","breadcrumbs":"Upgrading between Synapse Versions » New Single Sign-on HTML Templates","id":"243","title":"New Single Sign-on HTML Templates"},"244":{"body":"Plugins using the complete_sso_login method of synapse.module_api.ModuleApi should update to using the async/await version complete_sso_login_async which includes additional checks. The non-async version is considered deprecated.","breadcrumbs":"Upgrading between Synapse Versions » Synapse SSO Plugins Method Deprecation","id":"244","title":"Synapse SSO Plugins Method Deprecation"},"245":{"body":"v1.13.0 includes a lot of large changes. If something problematic occurs, you may want to roll-back to a previous version of Synapse. Because v1.13.0 also includes a new database schema version, reverting that version is also required alongside the generic rollback instructions mentioned above. In short, to roll back to v1.12.4 you need to: Stop the server Decrease the schema version in the database: UPDATE schema_version SET version = 57; Downgrade Synapse by following the instructions for your installation method in the \"Rolling back to older versions\" section above.","breadcrumbs":"Upgrading between Synapse Versions » Rolling back to v1.12.4 after a failed upgrade","id":"245","title":"Rolling back to v1.12.4 after a failed upgrade"},"246":{"body":"This version includes a database update which is run as part of the upgrade, and which may take some time (several hours in the case of a large server). Synapse will not respond to HTTP requests while this update is taking place. This is only likely to be a problem in the case of a server which is participating in many rooms. As with all upgrades, it is recommended that you have a recent backup of your database which can be used for recovery in the event of any problems. As an initial check to see if you will be affected, you can try running the following query from the psql or sqlite3 console. It is safe to run it while Synapse is still running. SELECT MAX(q.v) FROM ( SELECT ( SELECT ej.json AS v FROM state_events se INNER JOIN event_json ej USING (event_id) WHERE se.room_id=rooms.room_id AND se.type='m.room.create' AND se.state_key='' LIMIT 1 ) FROM rooms WHERE rooms.room_version IS NULL\n) q; This query will take about the same amount of time as the upgrade process: ie, if it takes 5 minutes, then it is likely that Synapse will be unresponsive for 5 minutes during the upgrade. If you consider an outage of this duration to be acceptable, no further action is necessary and you can simply start Synapse 1.12.0. If you would prefer to reduce the downtime, continue with the steps below. The easiest workaround for this issue is to manually create a new index before upgrading. On PostgreSQL, his can be done as follows: CREATE INDEX CONCURRENTLY tmp_upgrade_1_12_0_index\nON state_events(room_id) WHERE type = 'm.room.create'; The above query may take some time, but is also safe to run while Synapse is running. We assume that no SQLite users have databases large enough to be affected. If you are affected, you can run a similar query, omitting the CONCURRENTLY keyword. Note however that this operation may in itself cause Synapse to stop running for some time. Synapse admins are reminded that SQLite is not recommended for use outside a test environment . Once the index has been created, the SELECT query in step 1 above should complete quickly. It is therefore safe to upgrade to Synapse 1.12.0. Once Synapse 1.12.0 has successfully started and is responding to HTTP requests, the temporary index can be removed: DROP INDEX tmp_upgrade_1_12_0_index;","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.12.0","id":"246","title":"Upgrading to v1.12.0"},"247":{"body":"Synapse will now log a warning on start up if used with a PostgreSQL database that has a non-recommended locale set. See Postgres for details.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.10.0","id":"247","title":"Upgrading to v1.10.0"},"248":{"body":"Specifying a log_file config option will now cause Synapse to refuse to start, and should be replaced by with the log_config option. Support for the log_file option was removed in v1.3.0 and has since had no effect.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.8.0","id":"248","title":"Upgrading to v1.8.0"},"249":{"body":"In an attempt to configure Synapse in a privacy preserving way, the default behaviours of allow_public_rooms_without_auth and allow_public_rooms_over_federation have been inverted. This means that by default, only authenticated users querying the Client/Server API will be able to query the room directory, and relatedly that the server will not share room directory information with other servers over federation. If your installation does not explicitly set these settings one way or the other and you want either setting to be true then it will necessary to update your homeserver configuration file accordingly. For more details on the surrounding context see our explainer .","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.7.0","id":"249","title":"Upgrading to v1.7.0"},"25":{"body":"The default settings should be fine for most deployments. For larger scale deployments tuning some of the settings is recommended, details of which can be found at https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server . In particular, we've found tuning the following values helpful for performance: shared_buffers effective_cache_size work_mem maintenance_work_mem autovacuum_work_mem Note that the appropriate values for those fields depend on the amount of free memory the database host has available. Additionally, admins of large deployments might want to consider using huge pages to help manage memory, especially when using large values of shared_buffers. You can read more about that here .","breadcrumbs":"Using Postgres » Tuning Postgres","id":"25","title":"Tuning Postgres"},"250":{"body":"This release includes a database migration which may take several minutes to complete if there are a large number (more than a million or so) of entries in the devices table. This is only likely to a be a problem on very large installations.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.5.0","id":"250","title":"Upgrading to v1.5.0"},"251":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.4.0","id":"251","title":"Upgrading to v1.4.0"},"252":{"body":"If you have configured a custom template directory with the email.template_dir option, be aware that there are new templates regarding registration and threepid management (see below) that must be included. registration.html and registration.txt registration_success.html and registration_failure.html add_threepid.html and add_threepid.txt add_threepid_failure.html and add_threepid_success.html Synapse will expect these files to exist inside the configured template directory, and will fail to start if they are absent. To view the default templates, see synapse/res/templates .","breadcrumbs":"Upgrading between Synapse Versions » New custom templates","id":"252","title":"New custom templates"},"253":{"body":"Note: As of this release, users will be unable to add phone numbers or email addresses to their accounts, without changes to the Synapse configuration. This includes adding an email address during registration. It is possible for a user to associate an email address or phone number with their account, for a number of reasons: for use when logging in, as an alternative to the user id. in the case of email, as an alternative contact to help with account recovery. in the case of email, to receive notifications of missed messages. Before an email address or phone number can be added to a user's account, or before such an address is used to carry out a password-reset, Synapse must confirm the operation with the owner of the email address or phone number. It does this by sending an email or text giving the user a link or token to confirm receipt. This process is known as '3pid verification'. ('3pid', or 'threepid', stands for third-party identifier, and we use it to refer to external identifiers such as email addresses and phone numbers.) Previous versions of Synapse delegated the task of 3pid verification to an identity server by default. In most cases this server is vector.im or matrix.org. In Synapse 1.4.0, for security and privacy reasons, the homeserver will no longer delegate this task to an identity server by default. Instead, the server administrator will need to explicitly decide how they would like the verification messages to be sent. In the medium term, the vector.im and matrix.org identity servers will disable support for delegated 3pid verification entirely. However, in order to ease the transition, they will retain the capability for a limited period. Delegated email verification will be disabled on Monday 2nd December 2019 (giving roughly 2 months notice). Disabling delegated SMS verification will follow some time after that once SMS verification support lands in Synapse. Once delegated 3pid verification support has been disabled in the vector.im and matrix.org identity servers, all Synapse versions that depend on those instances will be unable to verify email and phone numbers through them. There are no imminent plans to remove delegated 3pid verification from Sydent generally. (Sydent is the identity server project that backs the vector.im and matrix.org instances).","breadcrumbs":"Upgrading between Synapse Versions » 3pid verification changes","id":"253","title":"3pid verification changes"},"254":{"body":"Following upgrade, to continue verifying email (e.g. as part of the registration process), admins can either:- Configure Synapse to use an email server. Run or choose an identity server which allows delegated email verification and delegate to it. Configure SMTP in Synapse To configure an SMTP server for Synapse, modify the configuration section headed email, and be sure to have at least the smtp_host, smtp_port and notif_from fields filled out. You may also need to set smtp_user, smtp_pass, and require_transport_security. See the sample configuration file for more details on these settings. Delegate email to an identity server Some admins will wish to continue using email verification as part of the registration process, but will not immediately have an appropriate SMTP server at hand. To this end, we will continue to support email verification delegation via the vector.im and matrix.org identity servers for two months. Support for delegated email verification will be disabled on Monday 2nd December. The account_threepid_delegates dictionary defines whether the homeserver should delegate an external server (typically an identity server ) to handle sending confirmation messages via email and SMS. So to delegate email verification, in homeserver.yaml, set account_threepid_delegates.email to the base URL of an identity server. For example: account_threepid_delegates: email: https://example.com # Delegate email sending to example.com Note that account_threepid_delegates.email replaces the deprecated email.trust_identity_server_for_password_resets: if email.trust_identity_server_for_password_resets is set to true, and account_threepid_delegates.email is not set, then the first entry in trusted_third_party_id_servers will be used as the account_threepid_delegate for email. This is to ensure compatibility with existing Synapse installs that set up external server handling for these tasks before v1.4.0. If email.trust_identity_server_for_password_resets is true and no trusted identity server domains are configured, Synapse will report an error and refuse to start. If email.trust_identity_server_for_password_resets is false or absent and no email delegate is configured in account_threepid_delegates, then Synapse will send email verification messages itself, using the configured SMTP server (see above). that type.","breadcrumbs":"Upgrading between Synapse Versions » Email","id":"254","title":"Email"},"255":{"body":"Synapse does not support phone-number verification itself, so the only way to maintain the ability for users to add phone numbers to their accounts will be by continuing to delegate phone number verification to the matrix.org and vector.im identity servers (or another identity server that supports SMS sending). The account_threepid_delegates dictionary defines whether the homeserver should delegate an external server (typically an identity server ) to handle sending confirmation messages via email and SMS. So to delegate phone number verification, in homeserver.yaml, set account_threepid_delegates.msisdn to the base URL of an identity server. For example: account_threepid_delegates: msisdn: https://example.com # Delegate sms sending to example.com The matrix.org and vector.im identity servers will continue to support delegated phone number verification via SMS until such time as it is possible for admins to configure their servers to perform phone number verification directly. More details will follow in a future release.","breadcrumbs":"Upgrading between Synapse Versions » Phone numbers","id":"255","title":"Phone numbers"},"256":{"body":"If you encounter problems with v1.4.0, it should be possible to roll back to v1.3.1, subject to the following: The 'room statistics' engine was heavily reworked in this release (see #5971 ), including significant changes to the database schema, which are not easily reverted. This will cause the room statistics engine to stop updating when you downgrade. The room statistics are essentially unused in v1.3.1 (in future versions of Synapse, they will be used to populate the room directory), so there should be no loss of functionality. However, the statistics engine will write errors to the logs, which can be avoided by setting the following in homeserver.yaml: stats: enabled: false Don't forget to re-enable it when you upgrade again, in preparation for its use in the room directory!","breadcrumbs":"Upgrading between Synapse Versions » Rolling back to v1.3.1","id":"256","title":"Rolling back to v1.3.1"},"257":{"body":"Some counter metrics have been renamed, with the old names deprecated. See the metrics documentation for details.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.2.0","id":"257","title":"Upgrading to v1.2.0"},"258":{"body":"Synapse v1.1.0 removes support for older Python and PostgreSQL versions, as outlined in our deprecation notice .","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.1.0","id":"258","title":"Upgrading to v1.1.0"},"259":{"body":"Synapse v1.1.0 has a minimum Python requirement of Python 3.5. Python 3.6 or Python 3.7 are recommended as they have improved internal string handling, significantly reducing memory usage. If you use current versions of the Matrix.org-distributed Debian packages or Docker images, action is not required. If you install Synapse in a Python virtual environment, please see \"Upgrading to v0.34.0\" for notes on setting up a new virtualenv under Python 3.","breadcrumbs":"Upgrading between Synapse Versions » Minimum Python Version","id":"259","title":"Minimum Python Version"},"26":{"body":"","breadcrumbs":"Using Postgres » Porting from SQLite","id":"26","title":"Porting from SQLite"},"260":{"body":"If using PostgreSQL under Synapse, you will need to use PostgreSQL 9.5 or above. Please see the PostgreSQL documentation for more details on upgrading your database.","breadcrumbs":"Upgrading between Synapse Versions » Minimum PostgreSQL Version","id":"260","title":"Minimum PostgreSQL Version"},"261":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.0","id":"261","title":"Upgrading to v1.0"},"262":{"body":"Synapse v1.0 is the first release to enforce validation of TLS certificates for the federation API. It is therefore essential that your certificates are correctly configured. Note, v1.0 installations will also no longer be able to federate with servers that have not correctly configured their certificates. In rare cases, it may be desirable to disable certificate checking: for example, it might be essential to be able to federate with a given legacy server in a closed federation. This can be done in one of two ways:- Configure the global switch federation_verify_certificates to false. Configure a whitelist of server domains to trust via federation_certificate_verification_whitelist. See the sample configuration file for more details on these settings.","breadcrumbs":"Upgrading between Synapse Versions » Validation of TLS certificates","id":"262","title":"Validation of TLS certificates"},"263":{"body":"When a user requests a password reset, Synapse will send an email to the user to confirm the request. Previous versions of Synapse delegated the job of sending this email to an identity server. If the identity server was somehow malicious or became compromised, it would be theoretically possible to hijack an account through this means. Therefore, by default, Synapse v1.0 will send the confirmation email itself. If Synapse is not configured with an SMTP server, password reset via email will be disabled. To configure an SMTP server for Synapse, modify the configuration section headed email, and be sure to have at least the smtp_host, smtp_port and notif_from fields filled out. You may also need to set smtp_user, smtp_pass, and require_transport_security. If you are absolutely certain that you wish to continue using an identity server for password resets, set trust_identity_server_for_password_resets to true. See the sample configuration file for more details on these settings.","breadcrumbs":"Upgrading between Synapse Versions » Email","id":"263","title":"Email"},"264":{"body":"Some new templates have been added to the default template directory for the purpose of the homeserver sending its own password reset emails. If you have configured a custom template_dir in your Synapse config, these files will need to be added. password_reset.html and password_reset.txt are HTML and plain text templates respectively that contain the contents of what will be emailed to the user upon attempting to reset their password via email. password_reset_success.html and password_reset_failure.html are HTML files that the content of which (assuming no redirect URL is set) will be shown to the user after they attempt to click the link in the email sent to them.","breadcrumbs":"Upgrading between Synapse Versions » New email templates","id":"264","title":"New email templates"},"265":{"body":"Please be aware that, before Synapse v1.0 is released around March 2019, you will need to replace any self-signed certificates with those verified by a root CA. Information on how to do so can be found at the ACME docs.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.99.0","id":"265","title":"Upgrading to v0.99.0"},"266":{"body":"This release is the first to fully support Python 3. Synapse will now run on Python versions 3.5, or 3.6 (as well as 2.7). We recommend switching to Python 3, as it has been shown to give performance improvements. For users who have installed Synapse into a virtualenv, we recommend doing this by creating a new virtualenv. For example: virtualenv -p python3 ~/synapse/env3\nsource ~/synapse/env3/bin/activate\npip install matrix-synapse You can then start synapse as normal, having activated the new virtualenv: cd ~/synapse\nsource env3/bin/activate\nsynctl start Users who have installed from distribution packages should see the relevant package documentation. See below for notes on Debian packages. When upgrading to Python 3, you must make sure that your log files are configured as UTF-8, by adding encoding: utf8 to the RotatingFileHandler configuration (if you have one) in your .log.config file. For example, if your log.config file contains: handlers: file: class: logging.handlers.RotatingFileHandler formatter: precise filename: homeserver.log maxBytes: 104857600 backupCount: 10 filters: [context] console: class: logging.StreamHandler formatter: precise filters: [context] Then you should update this to be: handlers: file: class: logging.handlers.RotatingFileHandler formatter: precise filename: homeserver.log maxBytes: 104857600 backupCount: 10 filters: [context] encoding: utf8 console: class: logging.StreamHandler formatter: precise filters: [context] There is no need to revert this change if downgrading to Python 2. We are also making available Debian packages which will run Synapse on Python 3. You can switch to these packages with apt-get install matrix-synapse-py3, however, please read debian/NEWS before doing so. The existing matrix-synapse packages will continue to use Python 2 for the time being. This release removes the riot.im from the default list of trusted identity servers. If riot.im is in your homeserver's list of trusted_third_party_id_servers, you should remove it. It was added in case a hypothetical future identity server was put there. If you don't remove it, users may be unable to deactivate their accounts. This release no longer installs the (unmaintained) Matrix Console web client as part of the default installation. It is possible to re-enable it by installing it separately and setting the web_client_location config option, but please consider switching to another client.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.34.0","id":"266","title":"Upgrading to v0.34.0"},"267":{"body":"This release removes the example email notification templates from res/templates (they are now internal to the python package). This should only affect you if you (a) deploy your Synapse instance from a git checkout or a github snapshot URL, and (b) have email notifications enabled. If you have email notifications enabled, you should ensure that email.template_dir is either configured to point at a directory where you have installed customised templates, or leave it unset to use the default templates.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.33.7","id":"267","title":"Upgrading to v0.33.7"},"268":{"body":"This release expands the anonymous usage stats sent if the opt-in report_stats configuration is set to true. We now capture RSS memory and cpu use at a very coarse level. This requires administrators to install the optional psutil python module. We would appreciate it if you could assist by ensuring this module is available and report_stats is enabled. This will let us see if performance changes to synapse are having an impact to the general community.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.27.3","id":"268","title":"Upgrading to v0.27.3"},"269":{"body":"If you want to use the new URL previewing API (/_matrix/media/r0/preview_url) then you have to explicitly enable it in the config and update your dependencies dependencies. See README.rst for details.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.15.0","id":"269","title":"Upgrading to v0.15.0"},"27":{"body":"The script synapse_port_db allows porting an existing synapse server backed by SQLite to using PostgreSQL. This is done as a two phase process: Copy the existing SQLite database to a separate location and run the port script against that offline database. Shut down the server. Rerun the port script to port any data that has come in since taking the first snapshot. Restart server against the PostgreSQL database. The port script is designed to be run repeatedly against newer snapshots of the SQLite database file. This makes it safe to repeat step 1 if there was a delay between taking the previous snapshot and being ready to do step 2. It is safe to at any time kill the port script and restart it. However, under no circumstances should the SQLite database be VACUUMed between multiple runs of the script. Doing so can lead to an inconsistent copy of your database into Postgres. To avoid accidental error, the script will check that SQLite's auto_vacuum mechanism is disabled, but the script is not able to protect against a manual VACUUM operation performed either by the administrator or by any automated task that the administrator may have configured. Note that the database may take up significantly more (25% - 100% more) space on disk after porting to Postgres.","breadcrumbs":"Using Postgres » Overview","id":"27","title":"Overview"},"270":{"body":"This release includes the option to send anonymous usage stats to matrix.org, and requires that administrators explicitly opt in or out by setting the report_stats option to either true or false. We would really appreciate it if you could help our project out by reporting anonymized usage statistics from your homeserver. Only very basic aggregate data (e.g. number of users) will be reported, but it helps us to track the growth of the Matrix community, and helps us to make Matrix a success, as well as to convince other networks that they should peer with us.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.11.0","id":"270","title":"Upgrading to v0.11.0"},"271":{"body":"Application services have had a breaking API change in this version. They can no longer register themselves with a home server using the AS HTTP API. This decision was made because a compromised application service with free reign to register any regex in effect grants full read/write access to the home server if a regex of .* is used. An attack where a compromised AS re-registers itself with .* was deemed too big of a security risk to ignore, and so the ability to register with the HS remotely has been removed. It has been replaced by specifying a list of application service registrations in homeserver.yaml: app_service_config_files: [\"registration-01.yaml\", \"registration-02.yaml\"] Where registration-01.yaml looks like: url: # e.g. \"https://my.application.service.com\"\nas_token: \nhs_token: \nsender_localpart: # This is a new field which denotes the user_id localpart when using the AS token\nnamespaces: users: - exclusive: regex: # e.g. \"@prefix_.*\" aliases: - exclusive: regex: rooms: - exclusive: regex: ","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.9.0","id":"271","title":"Upgrading to v0.9.0"},"272":{"body":"Servers which use captchas will need to add their public key to: static/client/register/register_config.js window.matrixRegistrationConfig = { recaptcha_public_key: \"YOUR_PUBLIC_KEY\" }; This is required in order to support registration fallback (typically used on mobile devices).","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.8.0","id":"272","title":"Upgrading to v0.8.0"},"273":{"body":"New dependencies are: pydenticon simplejson syutil matrix-angular-sdk To pull in these dependencies in a virtual env, run: python synapse/python_dependencies.py | xargs -n 1 pip install","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.7.0","id":"273","title":"Upgrading to v0.7.0"},"274":{"body":"To pull in new dependencies, run: python setup.py develop --user This update includes a change to the database schema. To upgrade you first need to upgrade the database by running: python scripts/upgrade_db_to_v0.6.0.py Where is the location of the database, is the server name as specified in the synapse configuration, and is the location of the signing key as specified in the synapse configuration. This may take some time to complete. Failures of signatures and content hashes can safely be ignored.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.6.0","id":"274","title":"Upgrading to v0.6.0"},"275":{"body":"Depending on precisely when you installed v0.5.0 you may have ended up with a stale release of the reference matrix webclient installed as a python module. To uninstall it and ensure you are depending on the latest module, please run: $ pip uninstall syweb","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.5.1","id":"275","title":"Upgrading to v0.5.1"},"276":{"body":"The webclient has been split out into a separate repository/package in this release. Before you restart your homeserver you will need to pull in the webclient package by running: python setup.py develop --user This release completely changes the database schema and so requires upgrading it before starting the new version of the homeserver. The script \"database-prepare-for-0.5.0.sh\" should be used to upgrade the database. This will save all user information, such as logins and profiles, but will otherwise purge the database. This includes messages, which rooms the home server was a member of and room alias mappings. If you would like to keep your history, please take a copy of your database file and ask for help in #matrix:matrix.org. The upgrade process is, unfortunately, non trivial and requires human intervention to resolve any resulting conflicts during the upgrade process. Before running the command the homeserver should be first completely shutdown. To run it, simply specify the location of the database, e.g.: ./scripts/database-prepare-for-0.5.0.sh \"homeserver.db\" Once this has successfully completed it will be safe to restart the homeserver. You may notice that the homeserver takes a few seconds longer to restart than usual as it reinitializes the database. On startup of the new version, users can either rejoin remote rooms using room aliases or by being reinvited. Alternatively, if any other homeserver sends a message to a room that the homeserver was previously in the local HS will automatically rejoin the room.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.5.0","id":"276","title":"Upgrading to v0.5.0"},"277":{"body":"This release needs an updated syutil version. Run: python setup.py develop You will also need to upgrade your configuration as the signing key format has changed. Run: python -m synapse.app.homeserver --config-path --generate-config","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.4.0","id":"277","title":"Upgrading to v0.4.0"},"278":{"body":"This registration API now closely matches the login API. This introduces a bit more backwards and forwards between the HS and the client, but this improves the overall flexibility of the API. You can now GET on /register to retrieve a list of valid registration flows. Upon choosing one, they are submitted in the same way as login, e.g: { type: m.login.password, user: foo, password: bar\n} The default HS supports 2 flows, with and without Identity Server email authentication. Enabling captcha on the HS will add in an extra step to all flows: m.login.recaptcha which must be completed before you can transition to the next stage. There is a new login type: m.login.email.identity which contains the threepidCreds key which were previously sent in the original register request. For more information on this, see the specification.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.3.0","id":"278","title":"Upgrading to v0.3.0"},"279":{"body":"The VoIP specification has changed between v0.2.0 and v0.3.0. Users should refresh any browser tabs to get the latest web client code. Users on v0.2.0 of the web client will not be able to call those on v0.3.0 and vice versa.","breadcrumbs":"Upgrading between Synapse Versions » Web Client","id":"279","title":"Web Client"},"28":{"body":"Firstly, shut down the currently running synapse server and copy its database file (typically homeserver.db) to another location. Once the copy is complete, restart synapse. For instance: synctl stop\ncp homeserver.db homeserver.db.snapshot\nsynctl start Copy the old config file into a new config file: cp homeserver.yaml homeserver-postgres.yaml Edit the database section as described in the section Synapse config above and with the SQLite snapshot located at homeserver.db.snapshot simply run: synapse_port_db --sqlite-database homeserver.db.snapshot \\ --postgres-config homeserver-postgres.yaml The flag --curses displays a coloured curses progress UI. (NOTE: if your terminal is too small the script will error out) If the script took a long time to complete, or time has otherwise passed since the original snapshot was taken, repeat the previous steps with a newer snapshot. To complete the conversion shut down the synapse server and run the port script one last time, e.g. if the SQLite database is at homeserver.db run: synapse_port_db --sqlite-database homeserver.db \\ --postgres-config homeserver-postgres.yaml Once that has completed, change the synapse config to point at the PostgreSQL database configuration file homeserver-postgres.yaml: synctl stop\nmv homeserver.yaml homeserver-old-sqlite.yaml\nmv homeserver-postgres.yaml homeserver.yaml\nsynctl start Synapse should now be running against PostgreSQL.","breadcrumbs":"Using Postgres » Using the port script","id":"28","title":"Using the port script"},"280":{"body":"The home server now requires setting up of SSL config before it can run. To automatically generate default config use: $ python synapse/app/homeserver.py \\ --server-name machine.my.domain.name \\ --bind-port 8448 \\ --config-path homeserver.config \\ --generate-config This config can be edited if desired, for example to specify a different SSL certificate to use. Once done you can run the home server using: $ python synapse/app/homeserver.py --config-path homeserver.config See the README.rst for more information. Also note that some config options have been renamed, including: \"host\" to \"server-name\" \"database\" to \"database-path\" \"port\" to \"bind-port\" and \"unsecure-port\"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.2.0","id":"280","title":"Upgrading to v0.2.0"},"281":{"body":"This release completely changes the database schema and so requires upgrading it before starting the new version of the homeserver. The script \"database-prepare-for-0.0.1.sh\" should be used to upgrade the database. This will save all user information, such as logins and profiles, but will otherwise purge the database. This includes messages, which rooms the home server was a member of and room alias mappings. Before running the command the homeserver should be first completely shutdown. To run it, simply specify the location of the database, e.g.: ./scripts/database-prepare-for-0.0.1.sh \"homeserver.db\" Once this has successfully completed it will be safe to restart the homeserver. You may notice that the homeserver takes a few seconds longer to restart than usual as it reinitializes the database. On startup of the new version, users can either rejoin remote rooms using room aliases or by being reinvited. Alternatively, if any other homeserver sends a message to a room that the homeserver was previously in the local HS will automatically rejoin the room.","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v0.0.1","id":"281","title":"Upgrading to v0.0.1"},"282":{"body":"Federation is the process by which users on different servers can participate in the same room. For this to work, those other servers must be able to contact yours to send messages. The server_name configured in the Synapse configuration file (often homeserver.yaml) defines how resources (users, rooms, etc.) will be identified (eg: @user:example.com, #room:example.com). By default, it is also the domain that other servers will use to try to reach your server (via port 8448). This is easy to set up and will work provided you set the server_name to match your machine's public DNS hostname. For this default configuration to work, you will need to listen for TLS connections on port 8448. The preferred way to do that is by using a reverse proxy: see the reverse proxy documentation for instructions on how to correctly set one up. In some cases you might not want to run Synapse on the machine that has the server_name as its public DNS hostname, or you might want federation traffic to use a different port than 8448. For example, you might want to have your user names look like @user:example.com, but you want to run Synapse on synapse.example.com on port 443. This can be done using delegation, which allows an admin to control where federation traffic should be sent. See the delegation documentation for instructions on how to set this up. Once federation has been configured, you should be able to join a room over federation. A good place to start is #synapse:matrix.org - a room for Synapse admins.","breadcrumbs":"Federation » Setting up federation","id":"282","title":"Setting up federation"},"283":{"body":"You can use the federation tester to check if your homeserver is configured correctly. Alternatively try the JSON API used by the federation tester . Note that you'll have to modify this URL to replace DOMAIN with your server_name. Hitting the API directly provides extra detail. The typical failure mode for federation is that when the server tries to join a room, it is rejected with \"401: Unauthorized\". Generally this means that other servers in the room could not access yours. (Joining a room over federation is a complicated dance which requires connections in both directions). Another common problem is that people on other servers can't join rooms that you invite them to. This can be caused by an incorrectly-configured reverse proxy: see the reverse proxy documentation for instructions on how to correctly configure a reverse proxy.","breadcrumbs":"Federation » Troubleshooting","id":"283","title":"Troubleshooting"},"284":{"body":"HTTP 308 Permanent Redirect redirects are not followed : Due to missing features in the HTTP library used by Synapse, 308 redirects are currently not followed by federating servers, which can cause M_UNKNOWN or 401 Unauthorized errors. This may affect users who are redirecting apex-to-www (e.g. example.com -> www.example.com), and especially users of the Kubernetes Nginx Ingress module, which uses 308 redirect codes by default. For those Kubernetes users, this Stackoverflow post might be helpful. For other users, switching to a 301 Moved Permanently code may be an option. 308 redirect codes will be supported properly in a future release of Synapse.","breadcrumbs":"Federation » Known issues","id":"284","title":"Known issues"},"285":{"body":"If you want to get up and running quickly with a trio of homeservers in a private federation, there is a script in the demo directory. This is mainly useful just for development purposes. See demo scripts .","breadcrumbs":"Federation » Running a demo federation of Synapses","id":"285","title":"Running a demo federation of Synapses"},"286":{"body":"This section contains information on tweaking Synapse via the various options in the configuration file. A configuration file should have been generated when you installed Synapse .","breadcrumbs":"Configuration » Configuration","id":"286","title":"Configuration"},"287":{"body":"This is intended as a guide to the Synapse configuration. The behavior of a Synapse instance can be modified through the many configuration settings documented here — each config option is explained, including what the default is, how to change the default and what sort of behaviour the setting governs. Also included is an example configuration for each setting. If you don't want to spend a lot of time thinking about options, the config as generated sets sensible defaults for all values. Do note however that the database defaults to SQLite, which is not recommended for production usage. You can read more on this subject here .","breadcrumbs":"Configuration » Configuration Manual » Configuring Synapse","id":"287","title":"Configuring Synapse"},"288":{"body":"Configuration options that take a time period can be set using a number followed by a letter. Letters have the following meanings: s = second m = minute h = hour d = day w = week y = year For example, setting redaction_retention_period: 5m would remove redacted messages from the database after 5 minutes, rather than 5 months. In addition, configuration options referring to size use the following suffixes: K = KiB, or 1024 bytes M = MiB, or 1,048,576 bytes G = GiB, or 1,073,741,824 bytes T = TiB, or 1,099,511,627,776 bytes For example, setting max_avatar_size: 10M means that Synapse will not accept files larger than 10,485,760 bytes for a user avatar.","breadcrumbs":"Configuration » Configuration Manual » Config Conventions","id":"288","title":"Config Conventions"},"289":{"body":"The configuration file can be validated with the following command: python -m synapse.config read -c To validate the entire file, omit read : python -m synapse.config -c To see how to set other options, check the help reference: python -m synapse.config --help","breadcrumbs":"Configuration » Configuration Manual » Config Validation","id":"289","title":"Config Validation"},"29":{"body":"","breadcrumbs":"Using Postgres » Troubleshooting","id":"29","title":"Troubleshooting"},"290":{"body":"The configuration file is a YAML file, which means that certain syntax rules apply if you want your config file to be read properly. A few helpful things to know: # before any option in the config will comment out that setting and either a default (if available) will be applied or Synapse will ignore the setting. Thus, in example #1 below, the setting will be read and applied, but in example #2 the setting will not be read and a default will be applied. Example #1: pid_file: DATADIR/homeserver.pid Example #2: #pid_file: DATADIR/homeserver.pid Indentation matters! The indentation before a setting will determine whether a given setting is read as part of another setting, or considered on its own. Thus, in example #1, the enabled setting is read as a sub-option of the presence setting, and will be properly applied. However, the lack of indentation before the enabled setting in example #2 means that when reading the config, Synapse will consider both presence and enabled as different settings. In this case, presence has no value, and thus a default applied, and enabled is an option that Synapse doesn't recognize and thus ignores. Example #1: presence: enabled: false Example #2: presence:\nenabled: false In this manual, all top-level settings (ones with no indentation) are identified at the beginning of their section (i.e. \"### example_setting\") and the sub-options, if any, are identified and listed in the body of the section. In addition, each setting has an example of its usage, with the proper indentation shown.","breadcrumbs":"Configuration » Configuration Manual » YAML","id":"290","title":"YAML"},"291":{"body":"Server admins can expand Synapse's functionality with external modules. See here for more documentation on how to configure or create custom modules for Synapse.","breadcrumbs":"Configuration » Configuration Manual » Modules","id":"291","title":"Modules"},"292":{"body":"Use the module sub-option to add modules under this option to extend functionality. The module setting then has a sub-option, config, which can be used to define some configuration for the module. Defaults to none. Example configuration: modules: - module: my_super_module.MySuperClass config: do_thing: true - module: my_other_super_module.SomeClass config: {}","breadcrumbs":"Configuration » Configuration Manual » modules","id":"292","title":"modules"},"293":{"body":"Define your homeserver name and other base options.","breadcrumbs":"Configuration » Configuration Manual » Server","id":"293","title":"Server"},"294":{"body":"This sets the public-facing domain of the server. The server_name name will appear at the end of usernames and room addresses created on your server. For example if the server_name was example.com, usernames on your server would be in the format @user:example.com In most cases you should avoid using a matrix specific subdomain such as matrix.example.com or synapse.example.com as the server_name for the same reasons you wouldn't use user@email.example.com as your email address. See here for information on how to host Synapse on a subdomain while preserving a clean server_name. The server_name cannot be changed later so it is important to configure this correctly before you start Synapse. It should be all lowercase and may contain an explicit port. There is no default for this option. Example configuration #1: server_name: matrix.org Example configuration #2: server_name: localhost:8080","breadcrumbs":"Configuration » Configuration Manual » server_name","id":"294","title":"server_name"},"295":{"body":"When running Synapse as a daemon, the file to store the pid in. Defaults to none. Example configuration: pid_file: DATADIR/homeserver.pid","breadcrumbs":"Configuration » Configuration Manual » pid_file","id":"295","title":"pid_file"},"296":{"body":"Specifies whether Synapse should be started as a daemon process. If Synapse is being managed by systemd , this option must be omitted or set to false. This can also be set by the --daemonize (-D) argument when starting Synapse. See worker_daemonize for more information on daemonizing workers. Example configuration: daemonize: true","breadcrumbs":"Configuration » Configuration Manual » daemonize","id":"296","title":"daemonize"},"297":{"body":"Print the path to the pidfile just before daemonizing. Defaults to false. This can also be set by the --print-pidfile argument when starting Synapse. Example configuration: print_pidfile: true","breadcrumbs":"Configuration » Configuration Manual » print_pidfile","id":"297","title":"print_pidfile"},"298":{"body":"A suffix that is appended to the Synapse user-agent (ex. Synapse/v1.123.0). Defaults to None Example configuration: user_agent_suffix: \" (I'm a teapot; Linux x86_64)\"","breadcrumbs":"Configuration » Configuration Manual » user_agent_suffix","id":"298","title":"user_agent_suffix"},"299":{"body":"Determines whether we should freeze the internal dict object in FrozenEvent. Freezing prevents bugs where we accidentally share e.g. signature dicts. However, freezing a dict is expensive. Defaults to false. Example configuration: use_frozen_dicts: true","breadcrumbs":"Configuration » Configuration Manual » use_frozen_dicts","id":"299","title":"use_frozen_dicts"},"3":{"body":"If you've found a security issue in Synapse or any other Element project, please report it to us in accordance with our Security Disclosure Policy . Thank you!","breadcrumbs":"Welcome and Overview » Reporting a security vulnerability","id":"3","title":"Reporting a security vulnerability"},"30":{"body":"If you get an error along the lines of FATAL: Ident authentication failed for user \"synapse_user\", you may need to use an authentication method other than ident: If the synapse_user user has a password, add the password to the database: section of homeserver.yaml. Then add the following to pg_hba.conf: host synapse synapse_user ::1/128 md5 # or `scram-sha-256` instead of `md5` if you use that If the synapse_user user does not have a password, then a password doesn't have to be added to homeserver.yaml. But the following does need to be added to pg_hba.conf: host synapse synapse_user ::1/128 trust Note that line order matters in pg_hba.conf, so make sure that if you do add a new line, it is inserted before: host all all ::1/128 ident","breadcrumbs":"Using Postgres » Alternative auth methods","id":"30","title":"Alternative auth methods"},"300":{"body":"The absolute URL to the web client which / will redirect to. Defaults to none. Example configuration: web_client_location: https://riot.example.com/","breadcrumbs":"Configuration » Configuration Manual » web_client_location","id":"300","title":"web_client_location"},"301":{"body":"The public-facing base URL that clients use to access this Homeserver (not including _matrix/...). This is the same URL a user might enter into the 'Custom Homeserver URL' field on their client. If you use Synapse with a reverse proxy, this should be the URL to reach Synapse via the proxy. Otherwise, it should be the URL to reach Synapse's client HTTP listener (see 'listeners' below). Defaults to https:///. Example configuration: public_baseurl: https://example.com/","breadcrumbs":"Configuration » Configuration Manual » public_baseurl","id":"301","title":"public_baseurl"},"302":{"body":"By default, other servers will try to reach our server on port 8448, which can be inconvenient in some environments. Provided https:/// on port 443 is routed to Synapse, this option configures Synapse to serve a file at https:///.well-known/matrix/server. This will tell other servers to send traffic to port 443 instead. This option currently defaults to false. See Delegation of incoming federation traffic for more information. Example configuration: serve_server_wellknown: true","breadcrumbs":"Configuration » Configuration Manual » serve_server_wellknown","id":"302","title":"serve_server_wellknown"},"303":{"body":"This option allows server runners to add arbitrary key-value pairs to the client-facing .well-known response . Note that the public_baseurl config option must be provided for Synapse to serve a response to /.well-known/matrix/client at all. If this option is provided, it parses the given yaml to json and serves it on /.well-known/matrix/client endpoint alongside the standard properties. Added in Synapse 1.62.0. Example configuration: extra_well_known_client_content : option1: value1 option2: value2","breadcrumbs":"Configuration » Configuration Manual » extra_well_known_client_content","id":"303","title":"extra_well_known_client_content"},"304":{"body":"Set the soft limit on the number of file descriptors synapse can use. Zero is used to indicate synapse should set the soft limit to the hard limit. Defaults to 0. Example configuration: soft_file_limit: 3","breadcrumbs":"Configuration » Configuration Manual » soft_file_limit","id":"304","title":"soft_file_limit"},"305":{"body":"Presence tracking allows users to see the state (e.g online/offline) of other local and remote users. Set the enabled sub-option to false to disable presence tracking on this homeserver. Defaults to true. This option replaces the previous top-level 'use_presence' option. Example configuration: presence: enabled: false include_offline_users_on_sync: false enabled can also be set to a special value of \"untracked\" which ignores updates received via clients and federation, while still accepting updates from the module API . The \"untracked\" option was added in Synapse 1.96.0. When clients perform an initial or full_state sync, presence results for offline users are not included by default. Setting include_offline_users_on_sync to true will always include offline users in the results. Defaults to false.","breadcrumbs":"Configuration » Configuration Manual » presence","id":"305","title":"presence"},"306":{"body":"Whether to require authentication to retrieve profile data (avatars, display names) of other users through the client API. Defaults to false. Note that profile data is also available via the federation API, unless allow_profile_lookup_over_federation is set to false. Example configuration: require_auth_for_profile_requests: true","breadcrumbs":"Configuration » Configuration Manual » require_auth_for_profile_requests","id":"306","title":"require_auth_for_profile_requests"},"307":{"body":"Use this option to require a user to share a room with another user in order to retrieve their profile information. Only checked on Client-Server requests. Profile requests from other servers should be checked by the requesting server. Defaults to false. Example configuration: limit_profile_requests_to_users_who_share_rooms: true","breadcrumbs":"Configuration » Configuration Manual » limit_profile_requests_to_users_who_share_rooms","id":"307","title":"limit_profile_requests_to_users_who_share_rooms"},"308":{"body":"Use this option to prevent a user's profile data from being retrieved and displayed in a room until they have joined it. By default, a user's profile data is included in an invite event, regardless of the values of the above two settings, and whether or not the users share a server. Defaults to true. Example configuration: include_profile_data_on_invite: false","breadcrumbs":"Configuration » Configuration Manual » include_profile_data_on_invite","id":"308","title":"include_profile_data_on_invite"},"309":{"body":"If set to true, removes the need for authentication to access the server's public rooms directory through the client API, meaning that anyone can query the room directory. Defaults to false. Example configuration: allow_public_rooms_without_auth: true","breadcrumbs":"Configuration » Configuration Manual » allow_public_rooms_without_auth","id":"309","title":"allow_public_rooms_without_auth"},"31":{"body":"Synapse will refuse to start when using a database with incorrect values of COLLATE and CTYPE unless the config flag allow_unsafe_locale, found in the database section of the config, is set to true. Using different locales can cause issues if the locale library is updated from underneath the database, or if a different version of the locale is used on any replicas. If you have a database with an unsafe locale, the safest way to fix the issue is to dump the database and recreate it with the correct locale parameter (as shown above). It is also possible to change the parameters on a live database and run a REINDEX on the entire database, however extreme care must be taken to avoid database corruption. Note that the above may fail with an error about duplicate rows if corruption has already occurred, and such duplicate rows will need to be manually removed.","breadcrumbs":"Using Postgres » Fixing incorrect COLLATE or CTYPE","id":"31","title":"Fixing incorrect COLLATE or CTYPE"},"310":{"body":"If set to true, allows any other homeserver to fetch the server's public rooms directory via federation. Defaults to false. Example configuration: allow_public_rooms_over_federation: true","breadcrumbs":"Configuration » Configuration Manual » allow_public_rooms_over_federation","id":"310","title":"allow_public_rooms_over_federation"},"311":{"body":"The default room version for newly created rooms on this server. Known room versions are listed here For example, for room version 1, default_room_version should be set to \"1\". Currently defaults to \"10\" . Changed in Synapse 1.76: the default version room version was increased from 9 to 10 . Example configuration: default_room_version: \"8\"","breadcrumbs":"Configuration » Configuration Manual » default_room_version","id":"311","title":"default_room_version"},"312":{"body":"The garbage collection threshold parameters to pass to gc.set_threshold, if defined. Defaults to none. Example configuration: gc_thresholds: [700, 10, 10]","breadcrumbs":"Configuration » Configuration Manual » gc_thresholds","id":"312","title":"gc_thresholds"},"313":{"body":"The minimum time in seconds between each GC for a generation, regardless of the GC thresholds. This ensures that we don't do GC too frequently. A value of [1s, 10s, 30s] indicates that a second must pass between consecutive generation 0 GCs, etc. Defaults to [1s, 10s, 30s]. Example configuration: gc_min_interval: [0.5s, 30s, 1m]","breadcrumbs":"Configuration » Configuration Manual » gc_min_interval","id":"313","title":"gc_min_interval"},"314":{"body":"Set the limit on the returned events in the timeline in the get and sync operations. Defaults to 100. A value of -1 means no upper limit. Example configuration: filter_timeline_limit: 5000","breadcrumbs":"Configuration » Configuration Manual » filter_timeline_limit","id":"314","title":"filter_timeline_limit"},"315":{"body":"Whether room invites to users on this server should be blocked (except those sent by local server admins). Defaults to false. Example configuration: block_non_admin_invites: true","breadcrumbs":"Configuration » Configuration Manual » block_non_admin_invites","id":"315","title":"block_non_admin_invites"},"316":{"body":"If set to false, new messages will not be indexed for searching and users will receive errors when searching for messages. Defaults to true. Example configuration: enable_search: false","breadcrumbs":"Configuration » Configuration Manual » enable_search","id":"316","title":"enable_search"},"317":{"body":"This option prevents outgoing requests from being sent to the specified blacklisted IP address CIDR ranges. If this option is not specified then it defaults to private IP address ranges (see the example below). The blacklist applies to the outbound requests for federation, identity servers, push servers, and for checking key validity for third-party invite events. (0.0.0.0 and :: are always blacklisted, whether or not they are explicitly listed here, since they correspond to unroutable addresses.) This option replaces federation_ip_range_blacklist in Synapse v1.25.0. Note: The value is ignored when an HTTP proxy is in use. Example configuration: ip_range_blacklist: - '127.0.0.0/8' - '10.0.0.0/8' - '172.16.0.0/12' - '192.168.0.0/16' - '100.64.0.0/10' - '192.0.0.0/24' - '169.254.0.0/16' - '192.88.99.0/24' - '198.18.0.0/15' - '192.0.2.0/24' - '198.51.100.0/24' - '203.0.113.0/24' - '224.0.0.0/4' - '::1/128' - 'fe80::/10' - 'fc00::/7' - '2001:db8::/32' - 'ff00::/8' - 'fec0::/10'","breadcrumbs":"Configuration » Configuration Manual » ip_range_blacklist","id":"317","title":"ip_range_blacklist"},"318":{"body":"List of IP address CIDR ranges that should be allowed for federation, identity servers, push servers, and for checking key validity for third-party invite events. This is useful for specifying exceptions to wide-ranging blacklisted target IP ranges - e.g. for communication with a push server only visible in your network. This whitelist overrides ip_range_blacklist and defaults to an empty list. Example configuration: ip_range_whitelist: - '192.168.1.1'","breadcrumbs":"Configuration » Configuration Manual » ip_range_whitelist","id":"318","title":"ip_range_whitelist"},"319":{"body":"List of ports that Synapse should listen on, their purpose and their configuration. Sub-options for each listener include: port: the TCP port to bind to. tag: An alias for the port in the logger name. If set the tag is logged instead of the port. Default to None, is optional and only valid for listener with type: http. See the docs request log format . bind_addresses: a list of local addresses to listen on. The default is 'all local interfaces'. type: the type of listener. Normally http, but other valid options are: manhole: (see the docs here ), metrics: (see the docs here ), tls: set to true to enable TLS for this listener. Will use the TLS key/cert specified in tls_private_key_path / tls_certificate_path. x_forwarded: Only valid for an 'http' listener. Set to true to use the X-Forwarded-For header as the client IP. Useful when Synapse is behind a reverse-proxy . request_id_header: The header extracted from each incoming request that is used as the basis for the request ID. The request ID is used in logs and tracing to correlate and match up requests. When unset, Synapse will automatically generate sequential request IDs. This option is useful when Synapse is behind a reverse-proxy . Added in Synapse 1.68.0. resources: Only valid for an 'http' listener. A list of resources to host on this port. Sub-options for each resource are: names: a list of names of HTTP resources. See below for a list of valid resource names. compress: set to true to enable gzip compression on HTTP bodies for this resource. This is currently only supported with the client, consent, metrics and federation resources. additional_resources: Only valid for an 'http' listener. A map of additional endpoints which should be loaded via dynamic modules. Unix socket support ( Added in Synapse 1.89.0 ): path: A path and filename for a Unix socket. Make sure it is located in a directory with read and write permissions, and that it already exists (the directory will not be created). Defaults to None. Note : The use of both path and port options for the same listener is not compatible. The x_forwarded option defaults to true when using Unix sockets and can be omitted. Other options that would not make sense to use with a UNIX socket, such as bind_addresses and tls will be ignored and can be removed. mode: The file permissions to set on the UNIX socket. Defaults to 666 Note: Must be set as type: http (does not support metrics and manhole). Also make sure that metrics is not included in resources -> names Valid resource names are: client: the client-server API (/_matrix/client). Also implies media and static. If configuring the main process, the Synapse Admin API (/_synapse/admin) is also implied. consent: user consent forms (/_matrix/consent). See here for more. federation: the server-server API (/_matrix/federation). Also implies media, keys, openid keys: the key discovery API (/_matrix/key). media: the media API (/_matrix/media). metrics: the metrics interface. See here . (Not compatible with Unix sockets) openid: OpenID authentication. See here . replication: the HTTP replication API (/_synapse/replication). See here . static: static resources under synapse/static (/_matrix/static). (Mostly useful for 'fallback authentication'.) health: the health check endpoint . This endpoint is by default active for all other resources and does not have to be activated separately. This is only useful if you want to use the health endpoint explicitly on a dedicated port or for workers and containers without listener e.g. application services . Example configuration #1: listeners: # TLS-enabled listener: for when matrix traffic is sent directly to synapse. # # (Note that you will also need to give Synapse a TLS key and certificate: see the TLS section # below.) # - port: 8448 type: http tls: true resources: - names: [client, federation] Example configuration #2: listeners: # Insecure HTTP listener: for when matrix traffic passes through a reverse proxy # that unwraps TLS. # # If you plan to use a reverse proxy, please see # https://element-hq.github.io/synapse/latest/reverse_proxy.html. # - port: 8008 tls: false type: http x_forwarded: true bind_addresses: ['::1', '127.0.0.1'] resources: - names: [client, federation] compress: false # example additional_resources: additional_resources: \"/_matrix/my/custom/endpoint\": module: my_module.CustomRequestHandler config: {} # Turn on the twisted ssh manhole service on localhost on the given # port. - port: 9000 bind_addresses: ['::1', '127.0.0.1'] type: manhole Example configuration #3: listeners: # Unix socket listener: Ideal for Synapse deployments behind a reverse proxy, offering # lightweight interprocess communication without TCP/IP overhead, avoid port # conflicts, and providing enhanced security through system file permissions. # # Note that x_forwarded will default to true, when using a UNIX socket. Please see # https://element-hq.github.io/synapse/latest/reverse_proxy.html. # - path: /run/synapse/main_public.sock type: http resources: - names: [client, federation]","breadcrumbs":"Configuration » Configuration Manual » listeners","id":"319","title":"listeners"},"32":{"body":"It is recommended to put a reverse proxy such as nginx , Apache , Caddy , HAProxy or relayd in front of Synapse. One advantage of doing so is that it means that you can expose the default https port (443) to Matrix clients without needing to run Synapse with root privileges. You should configure your reverse proxy to forward requests to /_matrix or /_synapse/client to Synapse, and have it set the X-Forwarded-For and X-Forwarded-Proto request headers. You should remember that Matrix clients and other Matrix servers do not necessarily need to connect to your server via the same server name or port. Indeed, clients will use port 443 by default, whereas servers default to port 8448. Where these are different, we refer to the 'client port' and the 'federation port'. See the Matrix specification for more details of the algorithm used for federation connections, and Delegation for instructions on setting up delegation. NOTE : Your reverse proxy must not canonicalise or normalise the requested URI in any way (for example, by decoding %xx escapes). Beware that Apache will canonicalise URIs unless you specify nocanon. Let's assume that we expect clients to connect to our server at https://matrix.example.com, and other servers to connect at https://example.com:8448. The following sections detail the configuration of the reverse proxy and the homeserver.","breadcrumbs":"Configuring a Reverse Proxy » Using a reverse proxy with Synapse","id":"32","title":"Using a reverse proxy with Synapse"},"320":{"body":"Turn on the Twisted telnet manhole service on the given port. Defaults to none. This can also be set by the --manhole argument when starting Synapse. Example configuration: manhole: 1234","breadcrumbs":"Configuration » Configuration Manual » manhole","id":"320","title":"manhole"},"321":{"body":"Connection settings for the manhole. You can find more information on the manhole here . Manhole sub-options include: username : the username for the manhole. This defaults to 'matrix'. password: The password for the manhole. This defaults to 'rabbithole'. ssh_priv_key_path and ssh_pub_key_path: The private and public SSH key pair used to encrypt the manhole traffic. If these are left unset, then hardcoded and non-secret keys are used, which could allow traffic to be intercepted if sent over a public network. Example configuration: manhole_settings: username: manhole password: mypassword ssh_priv_key_path: CONFDIR/id_rsa ssh_pub_key_path: CONFDIR/id_rsa.pub","breadcrumbs":"Configuration » Configuration Manual » manhole_settings","id":"321","title":"manhole_settings"},"322":{"body":"Forward extremities can build up in a room due to networking delays between homeservers. Once this happens in a large room, calculation of the state of that room can become quite expensive. To mitigate this, once the number of forward extremities reaches a given threshold, Synapse will send an org.matrix.dummy_event event, which will reduce the forward extremities in the room. This setting defines the threshold (i.e. number of forward extremities in the room) at which dummy events are sent. The default value is 10. Example configuration: dummy_events_threshold: 5","breadcrumbs":"Configuration » Configuration Manual » dummy_events_threshold","id":"322","title":"dummy_events_threshold"},"323":{"body":"An optional duration. If set, Synapse will run a daily background task to log out and delete any device that hasn't been accessed for more than the specified amount of time. Defaults to no duration, which means devices are never pruned. Note: This task will always run on the main process, regardless of the value of run_background_tasks_on. This is due to workers currently not having the ability to delete devices. Example configuration: delete_stale_devices_after: 1y","breadcrumbs":"Configuration » Configuration Manual » delete_stale_devices_after","id":"323","title":"delete_stale_devices_after"},"324":{"body":"Configuration for sending emails from Synapse. Server admins can configure custom templates for email content. See here for more information. This setting has the following sub-options: smtp_host: The hostname of the outgoing SMTP server to use. Defaults to 'localhost'. smtp_port: The port on the mail server for outgoing SMTP. Defaults to 465 if force_tls is true, else 25. Changed in Synapse 1.64.0: the default port is now aware of force_tls. smtp_user and smtp_pass: Username/password for authentication to the SMTP server. By default, no authentication is attempted. force_tls: By default, Synapse connects over plain text and then optionally upgrades to TLS via STARTTLS. If this option is set to true, TLS is used from the start (Implicit TLS), and the option require_transport_security is ignored. It is recommended to enable this if supported by your mail server. New in Synapse 1.64.0. require_transport_security: Set to true to require TLS transport security for SMTP. By default, Synapse will connect over plain text, and will then switch to TLS via STARTTLS if the SMTP server supports it . If this option is set, Synapse will refuse to connect unless the server supports STARTTLS. enable_tls: By default, if the server supports TLS, it will be used, and the server must present a certificate that is valid for tlsname. If this option is set to false, TLS will not be used. tlsname: The domain name the SMTP server's TLS certificate must be valid for, defaulting to smtp_host. notif_from: defines the \"From\" address to use when sending emails. It must be set if email sending is enabled. The placeholder '%(app)s' will be replaced by the application name, which is normally set in app_name, but may be overridden by the Matrix client application. Note that the placeholder must be written '%(app)s', including the trailing 's'. app_name: app_name defines the default value for '%(app)s' in notif_from and email subjects. It defaults to 'Matrix'. enable_notifs: Set to true to allow users to receive e-mail notifications. If this is not set, users can configure e-mail notifications but will not receive them. Disabled by default. notif_for_new_users: Set to false to disable automatic subscription to email notifications for new users. Enabled by default. notif_delay_before_mail: The time to wait before emailing about a notification. This gives the user a chance to view the message via push or an open client. Defaults to 10 minutes. New in Synapse 1.99.0. client_base_url: Custom URL for client links within the email notifications. By default links will be based on \"https://matrix.to\". (This setting used to be called riot_base_url; the old name is still supported for backwards-compatibility but is now deprecated.) validation_token_lifetime: Configures the time that a validation email will expire after sending. Defaults to 1h. invite_client_location: The web client location to direct users to during an invite. This is passed to the identity server as the org.matrix.web_client_location key. Defaults to unset, giving no guidance to the identity server. subjects: Subjects to use when sending emails from Synapse. The placeholder '%(app)s' will be replaced with the value of the app_name setting, or by a value dictated by the Matrix client application. In addition, each subject can use the following placeholders: '%(person)s', which will be replaced by the displayname of the user(s) that sent the message(s), e.g. \"Alice and Bob\", and '%(room)s', which will be replaced by the name of the room the message(s) have been sent to, e.g. \"My super room\". In addition, emails related to account administration will can use the '%(server_name)s' placeholder, which will be replaced by the value of the server_name setting in your Synapse configuration. Here is a list of subjects for notification emails that can be set: message_from_person_in_room: Subject to use to notify about one message from one or more user(s) in a room which has a name. Defaults to \"[%(app)s] You have a message on %(app)s from %(person)s in the %(room)s room...\" message_from_person: Subject to use to notify about one message from one or more user(s) in a room which doesn't have a name. Defaults to \"[%(app)s] You have a message on %(app)s from %(person)s...\" messages_from_person: Subject to use to notify about multiple messages from one or more users in a room which doesn't have a name. Defaults to \"[%(app)s] You have messages on %(app)s from %(person)s...\" messages_in_room: Subject to use to notify about multiple messages in a room which has a name. Defaults to \"[%(app)s] You have messages on %(app)s in the %(room)s room...\" messages_in_room_and_others: Subject to use to notify about multiple messages in multiple rooms. Defaults to \"[%(app)s] You have messages on %(app)s in the %(room)s room and others...\" messages_from_person_and_others: Subject to use to notify about multiple messages from multiple persons in multiple rooms. This is similar to the setting above except it's used when the room in which the notification was triggered has no name. Defaults to \"[%(app)s] You have messages on %(app)s from %(person)s and others...\" invite_from_person_to_room: Subject to use to notify about an invite to a room which has a name. Defaults to \"[%(app)s] %(person)s has invited you to join the %(room)s room on %(app)s...\" invite_from_person: Subject to use to notify about an invite to a room which doesn't have a name. Defaults to \"[%(app)s] %(person)s has invited you to chat on %(app)s...\" password_reset: Subject to use when sending a password reset email. Defaults to \"[%(server_name)s] Password reset\" email_validation: Subject to use when sending a verification email to assert an address's ownership. Defaults to \"[%(server_name)s] Validate your email\" Example configuration: email: smtp_host: mail.server smtp_port: 587 smtp_user: \"exampleusername\" smtp_pass: \"examplepassword\" force_tls: true require_transport_security: true enable_tls: false tlsname: mail.server.example.com notif_from: \"Your Friendly %(app)s homeserver \" app_name: my_branded_matrix_server enable_notifs: true notif_for_new_users: false client_base_url: \"http://localhost/riot\" validation_token_lifetime: 15m invite_client_location: https://app.element.io subjects: message_from_person_in_room: \"[%(app)s] You have a message on %(app)s from %(person)s in the %(room)s room...\" message_from_person: \"[%(app)s] You have a message on %(app)s from %(person)s...\" messages_from_person: \"[%(app)s] You have messages on %(app)s from %(person)s...\" messages_in_room: \"[%(app)s] You have messages on %(app)s in the %(room)s room...\" messages_in_room_and_others: \"[%(app)s] You have messages on %(app)s in the %(room)s room and others...\" messages_from_person_and_others: \"[%(app)s] You have messages on %(app)s from %(person)s and others...\" invite_from_person_to_room: \"[%(app)s] %(person)s has invited you to join the %(room)s room on %(app)s...\" invite_from_person: \"[%(app)s] %(person)s has invited you to chat on %(app)s...\" password_reset: \"[%(server_name)s] Password reset\" email_validation: \"[%(server_name)s] Validate your email\"","breadcrumbs":"Configuration » Configuration Manual » email","id":"324","title":"email"},"325":{"body":"The maximum allowed duration by which sent events can be delayed, as per MSC4140 . Must be a positive value if set. Defaults to no duration (null), which disallows sending delayed events. Example configuration: max_event_delay_duration: 24h","breadcrumbs":"Configuration » Configuration Manual » max_event_delay_duration","id":"325","title":"max_event_delay_duration"},"326":{"body":"Useful options for Synapse admins.","breadcrumbs":"Configuration » Configuration Manual » Homeserver blocking","id":"326","title":"Homeserver blocking"},"327":{"body":"How to reach the server admin, used in ResourceLimitError. Defaults to none. Example configuration: admin_contact: 'mailto:admin@server.com'","breadcrumbs":"Configuration » Configuration Manual » admin_contact","id":"327","title":"admin_contact"},"328":{"body":"Blocks users from connecting to the homeserver and provides a human-readable reason why the connection was blocked. Defaults to false. Example configuration: hs_disabled: true\nhs_disabled_message: 'Reason for why the HS is blocked'","breadcrumbs":"Configuration » Configuration Manual » hs_disabled and hs_disabled_message","id":"328","title":"hs_disabled and hs_disabled_message"},"329":{"body":"This option disables/enables monthly active user blocking. Used in cases where the admin or server owner wants to limit to the number of monthly active users. When enabled and a limit is reached the server returns a ResourceLimitError with error type Codes.RESOURCE_LIMIT_EXCEEDED. Defaults to false. If this is enabled, a value for max_mau_value must also be set. See Monthly Active Users for details on how to configure MAU. Example configuration: limit_usage_by_mau: true","breadcrumbs":"Configuration » Configuration Manual » limit_usage_by_mau","id":"329","title":"limit_usage_by_mau"},"33":{"body":"The HTTP configuration will need to be updated for Synapse to correctly record client IP addresses and generate redirect URLs while behind a reverse proxy. In homeserver.yaml set x_forwarded: true in the port 8008 section and consider setting bind_addresses: ['127.0.0.1'] so that the server only listens to traffic on localhost. (Do not change bind_addresses to 127.0.0.1 when using a containerized Synapse, as that will prevent it from responding to proxied traffic.) Optionally, you can also set request_id_header so that the server extracts and re-uses the same request ID format that the reverse proxy is using.","breadcrumbs":"Configuring a Reverse Proxy » Homeserver Configuration","id":"33","title":"Homeserver Configuration"},"330":{"body":"This option sets the hard limit of monthly active users above which the server will start blocking user actions if limit_usage_by_mau is enabled. Defaults to 0. Example configuration: max_mau_value: 50","breadcrumbs":"Configuration » Configuration Manual » max_mau_value","id":"330","title":"max_mau_value"},"331":{"body":"The option mau_trial_days is a means to add a grace period for active users. It means that users must be active for the specified number of days before they can be considered active and guards against the case where lots of users sign up in a short space of time never to return after their initial session. Defaults to 0. Example configuration: mau_trial_days: 5","breadcrumbs":"Configuration » Configuration Manual » mau_trial_days","id":"331","title":"mau_trial_days"},"332":{"body":"The option mau_appservice_trial_days is similar to mau_trial_days, but applies a different trial number if the user was registered by an appservice. A value of 0 means no trial days are applied. Appservices not listed in this dictionary use the value of mau_trial_days instead. Example configuration: mau_appservice_trial_days: my_appservice_id: 3 another_appservice_id: 6","breadcrumbs":"Configuration » Configuration Manual » mau_appservice_trial_days","id":"332","title":"mau_appservice_trial_days"},"333":{"body":"The option mau_limit_alerting is a means of limiting client-side alerting should the mau limit be reached. This is useful for small instances where the admin has 5 mau seats (say) for 5 specific people and no interest increasing the mau limit further. Defaults to true, which means that alerting is enabled. Example configuration: mau_limit_alerting: false","breadcrumbs":"Configuration » Configuration Manual » mau_limit_alerting","id":"333","title":"mau_limit_alerting"},"334":{"body":"If enabled, the metrics for the number of monthly active users will be populated, however no one will be limited based on these numbers. If limit_usage_by_mau is true, this is implied to be true. Defaults to false. Example configuration: mau_stats_only: true","breadcrumbs":"Configuration » Configuration Manual » mau_stats_only","id":"334","title":"mau_stats_only"},"335":{"body":"Sometimes the server admin will want to ensure certain accounts are never blocked by mau checking. These accounts are specified by this option. Defaults to none. Add accounts by specifying the medium and address of the reserved threepid (3rd party identifier). Example configuration: mau_limit_reserved_threepids: - medium: 'email' address: 'reserved_user@example.com'","breadcrumbs":"Configuration » Configuration Manual » mau_limit_reserved_threepids","id":"335","title":"mau_limit_reserved_threepids"},"336":{"body":"This option is used by phonehome stats to group together related servers. Defaults to none. Example configuration: server_context: context","breadcrumbs":"Configuration » Configuration Manual » server_context","id":"336","title":"server_context"},"337":{"body":"When this option is enabled, the room \"complexity\" will be checked before a user joins a new remote room. If it is above the complexity limit, the server will disallow joining, or will instantly leave. This is useful for homeservers that are resource-constrained. Options for this setting include: enabled: whether this check is enabled. Defaults to false. complexity: the limit above which rooms cannot be joined. The default is 1.0. complexity_error: override the error which is returned when the room is too complex with a custom message. admins_can_join: allow server admins to join complex rooms. Default is false. Room complexity is an arbitrary measure based on factors such as the number of users in the room. Example configuration: limit_remote_rooms: enabled: true complexity: 0.5 complexity_error: \"I can't let you do that, Dave.\" admins_can_join: true","breadcrumbs":"Configuration » Configuration Manual » limit_remote_rooms","id":"337","title":"limit_remote_rooms"},"338":{"body":"Whether to require a user to be in the room to add an alias to it. Defaults to true. Example configuration: require_membership_for_aliases: false","breadcrumbs":"Configuration » Configuration Manual » require_membership_for_aliases","id":"338","title":"require_membership_for_aliases"},"339":{"body":"Whether to allow per-room membership profiles through the sending of membership events with profile information that differs from the target's global profile. Defaults to true. Example configuration: allow_per_room_profiles: false","breadcrumbs":"Configuration » Configuration Manual » allow_per_room_profiles","id":"339","title":"allow_per_room_profiles"},"34":{"body":"NOTE : You only need one of these.","breadcrumbs":"Configuring a Reverse Proxy » Reverse-proxy configuration examples","id":"34","title":"Reverse-proxy configuration examples"},"340":{"body":"The largest permissible file size in bytes for a user avatar. Defaults to no restriction. Use M for MB and K for KB. Note that user avatar changes will not work if this is set without using Synapse's media repository. Example configuration: max_avatar_size: 10M","breadcrumbs":"Configuration » Configuration Manual » max_avatar_size","id":"340","title":"max_avatar_size"},"341":{"body":"The MIME types allowed for user avatars. Defaults to no restriction. Note that user avatar changes will not work if this is set without using Synapse's media repository. Example configuration: allowed_avatar_mimetypes: [\"image/png\", \"image/jpeg\", \"image/gif\"]","breadcrumbs":"Configuration » Configuration Manual » allowed_avatar_mimetypes","id":"341","title":"allowed_avatar_mimetypes"},"342":{"body":"How long to keep redacted events in unredacted form in the database. After this period redacted events get replaced with their redacted form in the DB. Synapse will check whether the rentention period has concluded for redacted events every 5 minutes. Thus, even if this option is set to 0, Synapse may still take up to 5 minutes to purge redacted events from the database. Defaults to 7d. Set to null to disable. Example configuration: redaction_retention_period: 28d","breadcrumbs":"Configuration » Configuration Manual » redaction_retention_period","id":"342","title":"redaction_retention_period"},"343":{"body":"How long to keep locally forgotten rooms before purging them from the DB. Defaults to null, meaning it's disabled. Example configuration: forgotten_room_retention_period: 28d","breadcrumbs":"Configuration » Configuration Manual » forgotten_room_retention_period","id":"343","title":"forgotten_room_retention_period"},"344":{"body":"How long to track users' last seen time and IPs in the database. Defaults to 28d. Set to null to disable clearing out of old rows. Example configuration: user_ips_max_age: 14d","breadcrumbs":"Configuration » Configuration Manual » user_ips_max_age","id":"344","title":"user_ips_max_age"},"345":{"body":"Inhibits the /requestToken endpoints from returning an error that might leak information about whether an e-mail address is in use or not on this homeserver. Defaults to false. Note that for some endpoints the error situation is the e-mail already being used, and for others the error is entering the e-mail being unused. If this option is enabled, instead of returning an error, these endpoints will act as if no error happened and return a fake session ID ('sid') to clients. Example configuration: request_token_inhibit_3pid_errors: true","breadcrumbs":"Configuration » Configuration Manual » request_token_inhibit_3pid_errors","id":"345","title":"request_token_inhibit_3pid_errors"},"346":{"body":"A list of domains that the domain portion of next_link parameters must match. This parameter is optionally provided by clients while requesting validation of an email or phone number, and maps to a link that users will be automatically redirected to after validation succeeds. Clients can make use this parameter to aid the validation process. The whitelist is applied whether the homeserver or an identity server is handling validation. The default value is no whitelist functionality; all domains are allowed. Setting this value to an empty list will instead disallow all domains. Example configuration: next_link_domain_whitelist: [\"matrix.org\"]","breadcrumbs":"Configuration » Configuration Manual » next_link_domain_whitelist","id":"346","title":"next_link_domain_whitelist"},"347":{"body":"These options define templates to use when generating email or HTML page contents. The custom_template_directory determines which directory Synapse will try to find template files in to use to generate email or HTML page contents. If not set, or a file is not found within the template directory, a default template from within the Synapse package will be used. See here for more information about using custom templates. Example configuration: templates: custom_template_directory: /path/to/custom/templates/","breadcrumbs":"Configuration » Configuration Manual » templates and custom_template_directory","id":"347","title":"templates and custom_template_directory"},"348":{"body":"This option and the associated options determine message retention policy at the server level. Room admins and mods can define a retention period for their rooms using the m.room.retention state event, and server admins can cap this period by setting the allowed_lifetime_min and allowed_lifetime_max config options. If this feature is enabled, Synapse will regularly look for and purge events which are older than the room's maximum retention period. Synapse will also filter events received over federation so that events that should have been purged are ignored and not stored again. The message retention policies feature is disabled by default. You can read more about this feature here . This setting has the following sub-options: default_policy: Default retention policy. If set, Synapse will apply it to rooms that lack the 'm.room.retention' state event. This option is further specified by the min_lifetime and max_lifetime sub-options associated with it. Note that the value of min_lifetime doesn't matter much because Synapse doesn't take it into account yet. allowed_lifetime_min and allowed_lifetime_max: Retention policy limits. If set, and the state of a room contains a m.room.retention event in its state which contains a min_lifetime or a max_lifetime that's out of these bounds, Synapse will cap the room's policy to these limits when running purge jobs. purge_jobs and the associated shortest_max_lifetime and longest_max_lifetime sub-options: Server admins can define the settings of the background jobs purging the events whose lifetime has expired under the purge_jobs section. If no configuration is provided for this option, a single job will be set up to delete expired events in every room daily. Each job's configuration defines which range of message lifetimes the job takes care of. For example, if shortest_max_lifetime is '2d' and longest_max_lifetime is '3d', the job will handle purging expired events in rooms whose state defines a max_lifetime that's both higher than 2 days, and lower than or equal to 3 days. Both the minimum and the maximum value of a range are optional, e.g. a job with no shortest_max_lifetime and a longest_max_lifetime of '3d' will handle every room with a retention policy whose max_lifetime is lower than or equal to three days. The rationale for this per-job configuration is that some rooms might have a retention policy with a low max_lifetime, where history needs to be purged of outdated messages on a more frequent basis than for the rest of the rooms (e.g. every 12h), but not want that purge to be performed by a job that's iterating over every room it knows, which could be heavy on the server. If any purge job is configured, it is strongly recommended to have at least a single job with neither shortest_max_lifetime nor longest_max_lifetime set, or one job without shortest_max_lifetime and one job without longest_max_lifetime set. Otherwise some rooms might be ignored, even if allowed_lifetime_min and allowed_lifetime_max are set, because capping a room's policy to these values is done after the policies are retrieved from Synapse's database (which is done using the range specified in a purge job's configuration). Example configuration: retention: enabled: true default_policy: min_lifetime: 1d max_lifetime: 1y allowed_lifetime_min: 1d allowed_lifetime_max: 1y purge_jobs: - longest_max_lifetime: 3d interval: 12h - shortest_max_lifetime: 3d interval: 1d","breadcrumbs":"Configuration » Configuration Manual » retention","id":"348","title":"retention"},"349":{"body":"Options related to TLS.","breadcrumbs":"Configuration » Configuration Manual » TLS","id":"349","title":"TLS"},"35":{"body":"server { listen 443 ssl; listen [::]:443 ssl; # For the federation port listen 8448 ssl default_server; listen [::]:8448 ssl default_server; server_name matrix.example.com; location ~ ^(/_matrix|/_synapse/client) { # note: do not add a path (even a single /) after the port in `proxy_pass`, # otherwise nginx will canonicalise the URI and cause signature verification # errors. proxy_pass http://localhost:8008; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host:$server_port; # Nginx by default only allows file uploads up to 1M in size # Increase client_max_body_size to match max_upload_size defined in homeserver.yaml client_max_body_size 50M; # Synapse responses may be chunked, which is an HTTP/1.1 feature. proxy_http_version 1.1; }\n}","breadcrumbs":"Configuring a Reverse Proxy » nginx","id":"35","title":"nginx"},"350":{"body":"This option specifies a PEM-encoded X509 certificate for TLS. This certificate, as of Synapse 1.0, will need to be a valid and verifiable certificate, signed by a recognised Certificate Authority. Defaults to none. Be sure to use a .pem file that includes the full certificate chain including any intermediate certificates (for instance, if using certbot, use fullchain.pem as your certificate, not cert.pem). Example configuration: tls_certificate_path: \"CONFDIR/SERVERNAME.tls.crt\"","breadcrumbs":"Configuration » Configuration Manual » tls_certificate_path","id":"350","title":"tls_certificate_path"},"351":{"body":"PEM-encoded private key for TLS. Defaults to none. Example configuration: tls_private_key_path: \"CONFDIR/SERVERNAME.tls.key\"","breadcrumbs":"Configuration » Configuration Manual » tls_private_key_path","id":"351","title":"tls_private_key_path"},"352":{"body":"Whether to verify TLS server certificates for outbound federation requests. Defaults to true. To disable certificate verification, set the option to false. Example configuration: federation_verify_certificates: false","breadcrumbs":"Configuration » Configuration Manual » federation_verify_certificates","id":"352","title":"federation_verify_certificates"},"353":{"body":"The minimum TLS version that will be used for outbound federation requests. Defaults to \"1\". Configurable to \"1\", \"1.1\", \"1.2\", or \"1.3\". Note that setting this value higher than \"1.2\" will prevent federation to most of the public Matrix network: only configure it to \"1.3\" if you have an entirely private federation setup and you can ensure TLS 1.3 support. Example configuration: federation_client_minimum_tls_version: \"1.2\"","breadcrumbs":"Configuration » Configuration Manual » federation_client_minimum_tls_version","id":"353","title":"federation_client_minimum_tls_version"},"354":{"body":"Skip federation certificate verification on a given whitelist of domains. This setting should only be used in very specific cases, such as federation over Tor hidden services and similar. For private networks of homeservers, you likely want to use a private CA instead. Only effective if federation_verify_certificates is true. Example configuration: federation_certificate_verification_whitelist: - lon.example.com - \"*.domain.com\" - \"*.onion\"","breadcrumbs":"Configuration » Configuration Manual » federation_certificate_verification_whitelist","id":"354","title":"federation_certificate_verification_whitelist"},"355":{"body":"List of custom certificate authorities for federation traffic. This setting should only normally be used within a private network of homeservers. Note that this list will replace those that are provided by your operating environment. Certificates must be in PEM format. Example configuration: federation_custom_ca_list: - myCA1.pem - myCA2.pem - myCA3.pem","breadcrumbs":"Configuration » Configuration Manual » federation_custom_ca_list","id":"355","title":"federation_custom_ca_list"},"356":{"body":"Options related to federation.","breadcrumbs":"Configuration » Configuration Manual » Federation","id":"356","title":"Federation"},"357":{"body":"Restrict federation to the given whitelist of domains. N.B. we recommend also firewalling your federation listener to limit inbound federation traffic as early as possible, rather than relying purely on this application-layer restriction. If not specified, the default is to whitelist everything. Note: this does not stop a server from joining rooms that servers not on the whitelist are in. As such, this option is really only useful to establish a \"private federation\", where a group of servers all whitelist each other and have the same whitelist. Example configuration: federation_domain_whitelist: - lon.example.com - nyc.example.com - syd.example.com","breadcrumbs":"Configuration » Configuration Manual » federation_domain_whitelist","id":"357","title":"federation_domain_whitelist"},"358":{"body":"Enables an endpoint for fetching the federation whitelist config. The request method and path is GET /_synapse/client/v1/config/federation_whitelist, and the response format is: { \"whitelist_enabled\": true, // Whether the federation whitelist is being enforced \"whitelist\": [ // Which server names are allowed by the whitelist \"example.com\" ]\n} If whitelist_enabled is false then the server is permitted to federate with all others. The endpoint requires authentication. Example configuration: federation_whitelist_endpoint_enabled: true","breadcrumbs":"Configuration » Configuration Manual » federation_whitelist_endpoint_enabled","id":"358","title":"federation_whitelist_endpoint_enabled"},"359":{"body":"Report prometheus metrics on the age of PDUs being sent to and received from the given domains. This can be used to give an idea of \"delay\" on inbound and outbound federation, though be aware that any delay can be due to problems at either end or with the intermediate network. By default, no domains are monitored in this way. Example configuration: federation_metrics_domains: - matrix.org - example.com","breadcrumbs":"Configuration » Configuration Manual » federation_metrics_domains","id":"359","title":"federation_metrics_domains"},"36":{"body":"matrix.example.com { reverse_proxy /_matrix/* localhost:8008 reverse_proxy /_synapse/client/* localhost:8008\n} example.com:8448 { reverse_proxy /_matrix/* localhost:8008\n} Delegation example: example.com { header /.well-known/matrix/* Content-Type application/json header /.well-known/matrix/* Access-Control-Allow-Origin * respond /.well-known/matrix/server `{\"m.server\": \"matrix.example.com:443\"}` respond /.well-known/matrix/client `{\"m.homeserver\":{\"base_url\":\"https://matrix.example.com\"},\"m.identity_server\":{\"base_url\":\"https://identity.example.com\"}}`\n} matrix.example.com { reverse_proxy /_matrix/* localhost:8008 reverse_proxy /_synapse/client/* localhost:8008\n}","breadcrumbs":"Configuring a Reverse Proxy » Caddy v2","id":"36","title":"Caddy v2"},"360":{"body":"Set to false to disable profile lookup over federation. By default, the Federation API allows other homeservers to obtain profile data of any user on this homeserver. Example configuration: allow_profile_lookup_over_federation: false","breadcrumbs":"Configuration » Configuration Manual » allow_profile_lookup_over_federation","id":"360","title":"allow_profile_lookup_over_federation"},"361":{"body":"Set this option to true to allow device display name lookup over federation. By default, the Federation API prevents other homeservers from obtaining the display names of any user devices on this homeserver. Example configuration: allow_device_name_lookup_over_federation: true","breadcrumbs":"Configuration » Configuration Manual » allow_device_name_lookup_over_federation","id":"361","title":"allow_device_name_lookup_over_federation"},"362":{"body":"The federation section defines some sub-options related to federation. The following options are related to configuring timeout and retry logic for one request, independently of the others. Short retry algorithm is used when something or someone will wait for the request to have an answer, while long retry is used for requests that happen in the background, like sending a federation transaction. client_timeout: timeout for the federation requests. Default to 60s. max_short_retry_delay: maximum delay to be used for the short retry algo. Default to 2s. max_long_retry_delay: maximum delay to be used for the short retry algo. Default to 60s. max_short_retries: maximum number of retries for the short retry algo. Default to 3 attempts. max_long_retries: maximum number of retries for the long retry algo. Default to 10 attempts. The following options control the retry logic when communicating with a specific homeserver destination. Unlike the previous configuration options, these values apply across all requests for a given destination and the state of the backoff is stored in the database. destination_min_retry_interval: the initial backoff, after the first request fails. Defaults to 10m. destination_retry_multiplier: how much we multiply the backoff by after each subsequent fail. Defaults to 2. destination_max_retry_interval: a cap on the backoff. Defaults to a week. Example configuration: federation: client_timeout: 180s max_short_retry_delay: 7s max_long_retry_delay: 100s max_short_retries: 5 max_long_retries: 20 destination_min_retry_interval: 30s destination_retry_multiplier: 5 destination_max_retry_interval: 12h","breadcrumbs":"Configuration » Configuration Manual » federation","id":"362","title":"federation"},"363":{"body":"Options related to caching.","breadcrumbs":"Configuration » Configuration Manual » Caching","id":"363","title":"Caching"},"364":{"body":"The number of events to cache in memory. Defaults to 10K. Like other caches, this is affected by caches.global_factor (see below). For example, the default is 10K and the global_factor default is 0.5. Since 10K * 0.5 is 5K then the event cache size will be 5K. The cache affected by this configuration is named as \" getEvent \". Note that this option is not part of the caches section. Example configuration: event_cache_size: 15K","breadcrumbs":"Configuration » Configuration Manual » event_cache_size","id":"364","title":"event_cache_size"},"365":{"body":"A cache 'factor' is a multiplier that can be applied to each of Synapse's caches in order to increase or decrease the maximum number of entries that can be stored. caches can be configured through the following sub-options: global_factor: Controls the global cache factor, which is the default cache factor for all caches if a specific factor for that cache is not otherwise set. This can also be set by the SYNAPSE_CACHE_FACTOR environment variable. Setting by environment variable takes priority over setting through the config file. Defaults to 0.5, which will halve the size of all caches. Note that changing this value also affects the HTTP connection pool. per_cache_factors: A dictionary of cache name to cache factor for that individual cache. Overrides the global cache factor for a given cache. These can also be set through environment variables comprised of SYNAPSE_CACHE_FACTOR_ + the name of the cache in capital letters and underscores. Setting by environment variable takes priority over setting through the config file. Ex. SYNAPSE_CACHE_FACTOR_GET_USERS_WHO_SHARE_ROOM_WITH_USER=2.0 Some caches have '*' and other characters that are not alphanumeric or underscores. These caches can be named with or without the special characters stripped. For example, to specify the cache factor for *stateGroupCache* via an environment variable would be SYNAPSE_CACHE_FACTOR_STATEGROUPCACHE=2.0. expire_caches: Controls whether cache entries are evicted after a specified time period. Defaults to true. Set to false to disable this feature. Note that never expiring caches may result in excessive memory usage. cache_entry_ttl: If expire_caches is enabled, this flag controls how long an entry can be in a cache without having been accessed before being evicted. Defaults to 30m. sync_response_cache_duration: Controls how long the results of a /sync request are cached for after a successful response is returned. A higher duration can help clients with intermittent connections, at the cost of higher memory usage. A value of zero means that sync responses are not cached. Defaults to 2m. Changed in Synapse 1.62.0 : The default was changed from 0 to 2m. cache_autotuning and its sub-options max_cache_memory_usage, target_cache_memory_usage, and min_cache_ttl work in conjunction with each other to maintain a balance between cache memory usage and cache entry availability. You must be using jemalloc to utilize this option, and all three of the options must be specified for this feature to work. This option defaults to off, enable it by providing values for the sub-options listed below. Please note that the feature will not work and may cause unstable behavior (such as excessive emptying of caches or exceptions) if all of the values are not provided. Please see the Config Conventions for information on how to specify memory size and cache expiry durations. max_cache_memory_usage sets a ceiling on how much memory the cache can use before caches begin to be continuously evicted. They will continue to be evicted until the memory usage drops below the target_cache_memory_usage, set in the setting below, or until the min_cache_ttl is hit. There is no default value for this option. target_cache_memory_usage sets a rough target for the desired memory usage of the caches. There is no default value for this option. min_cache_ttl sets a limit under which newer cache entries are not evicted and is only applied when caches are actively being evicted/max_cache_memory_usage has been exceeded. This is to protect hot caches from being emptied while Synapse is evicting due to memory. There is no default value for this option. Example configuration: event_cache_size: 15K\ncaches: global_factor: 1.0 per_cache_factors: get_users_who_share_room_with_user: 2.0 sync_response_cache_duration: 2m cache_autotuning: max_cache_memory_usage: 1024M target_cache_memory_usage: 758M min_cache_ttl: 5m","breadcrumbs":"Configuration » Configuration Manual » caches and associated values","id":"365","title":"caches and associated values"},"366":{"body":"The cache factors (i.e. caches.global_factor and caches.per_cache_factors) may be reloaded at any time by sending a SIGHUP signal to Synapse using e.g. kill -HUP [PID_OF_SYNAPSE_PROCESS] If you are running multiple workers, you must individually update the worker config file and send this signal to each worker process. If you're using the example systemd service file in Synapse's contrib directory, you can send a SIGHUP signal by using systemctl reload matrix-synapse.","breadcrumbs":"Configuration » Configuration Manual » Reloading cache factors","id":"366","title":"Reloading cache factors"},"367":{"body":"Config options related to database settings.","breadcrumbs":"Configuration » Configuration Manual » Database","id":"367","title":"Database"},"368":{"body":"The database setting defines the database that synapse uses to store all of its data. Associated sub-options: name: this option specifies the database engine to use: either sqlite3 (for SQLite) or psycopg2 (for PostgreSQL). If no name is specified Synapse will default to SQLite. txn_limit gives the maximum number of transactions to run per connection before reconnecting. Defaults to 0, which means no limit. allow_unsafe_locale is an option specific to Postgres. Under the default behavior, Synapse will refuse to start if the postgres db is set to a non-C locale. You can override this behavior (which is not recommended) by setting allow_unsafe_locale to true. Note that doing so may corrupt your database. You can find more information here and here . args gives options which are passed through to the database engine, except for options starting with cp_, which are used to configure the Twisted connection pool. For a reference to valid arguments, see: for sqlite for postgres for the connection pool For more information on using Synapse with Postgres, see here . Example SQLite configuration: database: name: sqlite3 args: database: /path/to/homeserver.db Example Postgres configuration: database: name: psycopg2 txn_limit: 10000 args: user: synapse_user password: secretpassword dbname: synapse host: localhost port: 5432 cp_min: 5 cp_max: 10","breadcrumbs":"Configuration » Configuration Manual » database","id":"368","title":"database"},"369":{"body":"The databases option allows specifying a mapping between certain database tables and database host details, spreading the load of a single Synapse instance across multiple database backends. This is often referred to as \"database sharding\". This option is only supported for PostgreSQL database backends. Important note: This is a supported option, but is not currently used in production by the Matrix.org Foundation. Proceed with caution and always make backups. databases is a dictionary of arbitrarily-named database entries. Each entry is equivalent to the value of the database homeserver config option (see above), with the addition of a data_stores key. data_stores is an array of strings that specifies the data store(s) (a defined label for a set of tables) that should be stored on the associated database backend entry. The currently defined values for data_stores are: \"state\": Database that relates to state groups will be stored in this database. Specifically, that means the following tables: state_groups state_group_edges state_groups_state And the following sequences: state_groups_seq_id \"main\": All other database tables and sequences. All databases will end up with additional tables used for tracking database schema migrations and any pending background updates. Synapse will create these automatically on startup when checking for and/or performing database schema migrations. To migrate an existing database configuration (e.g. all tables on a single database) to a different configuration (e.g. the \"main\" data store on one database, and \"state\" on another), do the following: Take a backup of your existing database. Things can and do go wrong and database corruption is no joke! Ensure all pending database migrations have been applied and background updates have run. The simplest way to do this is to use the update_synapse_database script supplied with your Synapse installation. update_synapse_database --database-config homeserver.yaml --run-background-updates Copy over the necessary tables and sequences from one database to the other. Tables relating to database migrations, schemas, schema versions and background updates should not be copied. As an example, say that you'd like to split out the \"state\" data store from an existing database which currently contains all data stores. Simply copy the tables and sequences defined above for the \"state\" datastore from the existing database to the secondary database. As noted above, additional tables will be created in the secondary database when Synapse is started. Modify/create the databases option in your homeserver.yaml to match the desired database configuration. Start Synapse. Check that it starts up successfully and that things generally seem to be working. Drop the old tables that were copied in step 3. Only one of the options database or databases may be specified in your config, but not both. Example configuration: databases: basement_box: name: psycopg2 txn_limit: 10000 data_stores: [\"main\"] args: user: synapse_user password: secretpassword dbname: synapse_main host: localhost port: 5432 cp_min: 5 cp_max: 10 my_other_database: name: psycopg2 txn_limit: 10000 data_stores: [\"state\"] args: user: synapse_user password: secretpassword dbname: synapse_state host: localhost port: 5432 cp_min: 5 cp_max: 10","breadcrumbs":"Configuration » Configuration Manual » databases","id":"369","title":"databases"},"37":{"body":" SSLEngine on ServerName matrix.example.com RequestHeader set \"X-Forwarded-Proto\" expr=%{REQUEST_SCHEME} AllowEncodedSlashes NoDecode ProxyPreserveHost on ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix ProxyPass /_synapse/client http://127.0.0.1:8008/_synapse/client nocanon ProxyPassReverse /_synapse/client http://127.0.0.1:8008/_synapse/client\n SSLEngine on ServerName example.com RequestHeader set \"X-Forwarded-Proto\" expr=%{REQUEST_SCHEME} AllowEncodedSlashes NoDecode ProxyPass /_matrix http://127.0.0.1:8008/_matrix nocanon ProxyPassReverse /_matrix http://127.0.0.1:8008/_matrix\n NOTE : ensure the nocanon options are included. NOTE 2 : It appears that Synapse is currently incompatible with the ModSecurity module for Apache (mod_security2). If you need it enabled for other services on your web server, you can disable it for Synapse's two VirtualHosts by including the following lines before each of the two above: SecRuleEngine off\n NOTE 3 : Missing ProxyPreserveHost on can lead to a redirect loop.","breadcrumbs":"Configuring a Reverse Proxy » Apache","id":"37","title":"Apache"},"370":{"body":"Config options related to logging.","breadcrumbs":"Configuration » Configuration Manual » Logging","id":"370","title":"Logging"},"371":{"body":"This option specifies a yaml python logging config file as described here . Example configuration: log_config: \"CONFDIR/SERVERNAME.log.config\"","breadcrumbs":"Configuration » Configuration Manual » log_config","id":"371","title":"log_config"},"372":{"body":"Options related to ratelimiting in Synapse. Each ratelimiting configuration is made of two parameters: per_second: number of requests a client can send per second. burst_count: number of requests a client can send before being throttled.","breadcrumbs":"Configuration » Configuration Manual » Ratelimiting","id":"372","title":"Ratelimiting"},"373":{"body":"Ratelimiting settings for client messaging. This is a ratelimiting option for messages that ratelimits sending based on the account the client is using. It defaults to: per_second: 0.2, burst_count: 10. Example configuration: rc_message: per_second: 0.5 burst_count: 15","breadcrumbs":"Configuration » Configuration Manual » rc_message","id":"373","title":"rc_message"},"374":{"body":"This option ratelimits registration requests based on the client's IP address. It defaults to per_second: 0.17, burst_count: 3. Example configuration: rc_registration: per_second: 0.15 burst_count: 2","breadcrumbs":"Configuration » Configuration Manual » rc_registration","id":"374","title":"rc_registration"},"375":{"body":"This option checks the validity of registration tokens that ratelimits requests based on the client's IP address. Defaults to per_second: 0.1, burst_count: 5. Example configuration: rc_registration_token_validity: per_second: 0.3 burst_count: 6","breadcrumbs":"Configuration » Configuration Manual » rc_registration_token_validity","id":"375","title":"rc_registration_token_validity"},"376":{"body":"This option specifies several limits for login: address ratelimits login requests based on the client's IP address. Defaults to per_second: 0.003, burst_count: 5. account ratelimits login requests based on the account the client is attempting to log into. Defaults to per_second: 0.003, burst_count: 5. failed_attempts ratelimits login requests based on the account the client is attempting to log into, based on the amount of failed login attempts for this account. Defaults to per_second: 0.17, burst_count: 3. Example configuration: rc_login: address: per_second: 0.15 burst_count: 5 account: per_second: 0.18 burst_count: 4 failed_attempts: per_second: 0.19 burst_count: 7","breadcrumbs":"Configuration » Configuration Manual » rc_login","id":"376","title":"rc_login"},"377":{"body":"This option sets ratelimiting redactions by room admins. If this is not explicitly set then it uses the same ratelimiting as per rc_message. This is useful to allow room admins to deal with abuse quickly. Example configuration: rc_admin_redaction: per_second: 1 burst_count: 50","breadcrumbs":"Configuration » Configuration Manual » rc_admin_redaction","id":"377","title":"rc_admin_redaction"},"378":{"body":"This option allows for ratelimiting number of rooms a user can join. This setting has the following sub-options: local: ratelimits when users are joining rooms the server is already in. Defaults to per_second: 0.1, burst_count: 10. remote: ratelimits when users are trying to join rooms not on the server (which can be more computationally expensive than restricting locally). Defaults to per_second: 0.01, burst_count: 10 Example configuration: rc_joins: local: per_second: 0.2 burst_count: 15 remote: per_second: 0.03 burst_count: 12","breadcrumbs":"Configuration » Configuration Manual » rc_joins","id":"378","title":"rc_joins"},"379":{"body":"This option allows admins to ratelimit joins to a room based on the number of recent joins (local or remote) to that room. It is intended to mitigate mass-join spam waves which target multiple homeservers. By default, one join is permitted to a room every second, with an accumulating buffer of up to ten instantaneous joins. Example configuration (default values): rc_joins_per_room: per_second: 1 burst_count: 10 Added in Synapse 1.64.0.","breadcrumbs":"Configuration » Configuration Manual » rc_joins_per_room","id":"379","title":"rc_joins_per_room"},"38":{"body":"frontend https bind *:443,[::]:443 ssl crt /etc/ssl/haproxy/ strict-sni alpn h2,http/1.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-For %[src] # Matrix client traffic acl matrix-host hdr(host) -i matrix.example.com matrix.example.com:443 acl matrix-path path_beg /_matrix acl matrix-path path_beg /_synapse/client use_backend matrix if matrix-host matrix-path frontend matrix-federation bind *:8448,[::]:8448 ssl crt /etc/ssl/haproxy/synapse.pem alpn h2,http/1.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-For %[src] default_backend matrix backend matrix server matrix 127.0.0.1:8008 Example configuration, if using a UNIX socket. The configuration lines regarding the frontends do not need to be modified. backend matrix server matrix unix@/run/synapse/main_public.sock Example configuration when using a single port for both client and federation traffic. frontend https bind *:443,[::]:443 ssl crt /etc/ssl/haproxy/ strict-sni alpn h2,http/1.1 http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-For %[src] acl matrix-host hdr(host) -i matrix.example.com matrix.example.com:443 acl matrix-sni ssl_fc_sni matrix.example.com acl matrix-path path_beg /_matrix acl matrix-path path_beg /_synapse/client use_backend matrix if matrix-host matrix-path use_backend matrix if matrix-sni backend matrix server matrix 127.0.0.1:8008 Delegation example: frontend https acl matrix-well-known-client-path path /.well-known/matrix/client acl matrix-well-known-server-path path /.well-known/matrix/server use_backend matrix-well-known-client if matrix-well-known-client-path use_backend matrix-well-known-server if matrix-well-known-server-path backend matrix-well-known-client http-after-response set-header Access-Control-Allow-Origin \"*\" http-after-response set-header Access-Control-Allow-Methods \"GET, POST, PUT, DELETE, OPTIONS\" http-after-response set-header Access-Control-Allow-Headers \"Origin, X-Requested-With, Content-Type, Accept, Authorization\" http-request return status 200 content-type application/json string '{\"m.homeserver\":{\"base_url\":\"https://matrix.example.com\"},\"m.identity_server\":{\"base_url\":\"https://identity.example.com\"}}' backend matrix-well-known-server http-after-response set-header Access-Control-Allow-Origin \"*\" http-after-response set-header Access-Control-Allow-Methods \"GET, POST, PUT, DELETE, OPTIONS\" http-after-response set-header Access-Control-Allow-Headers \"Origin, X-Requested-With, Content-Type, Accept, Authorization\" http-request return status 200 content-type application/json string '{\"m.server\":\"matrix.example.com:443\"}'","breadcrumbs":"Configuring a Reverse Proxy » HAProxy","id":"38","title":"HAProxy"},"380":{"body":"This option ratelimits how often a user or IP can attempt to validate a 3PID. Defaults to per_second: 0.003, burst_count: 5. Example configuration: rc_3pid_validation: per_second: 0.003 burst_count: 5","breadcrumbs":"Configuration » Configuration Manual » rc_3pid_validation","id":"380","title":"rc_3pid_validation"},"381":{"body":"This option sets ratelimiting how often invites can be sent in a room or to a specific user. per_room defaults to per_second: 0.3, burst_count: 10, per_user defaults to per_second: 0.003, burst_count: 5, and per_issuer defaults to per_second: 0.3, burst_count: 10. Client requests that invite user(s) when creating a room will count against the rc_invites.per_room limit, whereas client requests to invite a single user to a room will count against both the rc_invites.per_user and rc_invites.per_room limits. Federation requests to invite a user will count against the rc_invites.per_user limit only, as Synapse presumes ratelimiting by room will be done by the sending server. The rc_invites.per_user limit applies to the receiver of the invite, rather than the sender, meaning that a rc_invite.per_user.burst_count of 5 mandates that a single user cannot receive more than a burst of 5 invites at a time. In contrast, the rc_invites.per_issuer limit applies to the issuer of the invite, meaning that a rc_invite.per_issuer.burst_count of 5 mandates that single user cannot send more than a burst of 5 invites at a time. Changed in version 1.63: added the per_issuer limit. Example configuration: rc_invites: per_room: per_second: 0.5 burst_count: 5 per_user: per_second: 0.004 burst_count: 3 per_issuer: per_second: 0.5 burst_count: 5","breadcrumbs":"Configuration » Configuration Manual » rc_invites","id":"381","title":"rc_invites"},"382":{"body":"This option ratelimits 3PID invites (i.e. invites sent to a third-party ID such as an email address or a phone number) based on the account that's sending the invite. Defaults to per_second: 0.2, burst_count: 10. Example configuration: rc_third_party_invite: per_second: 0.2 burst_count: 10","breadcrumbs":"Configuration » Configuration Manual » rc_third_party_invite","id":"382","title":"rc_third_party_invite"},"383":{"body":"This option ratelimits creation of MXC URIs via the /_matrix/media/v1/create endpoint based on the account that's creating the media. Defaults to per_second: 10, burst_count: 50. Example configuration: rc_media_create: per_second: 10 burst_count: 50","breadcrumbs":"Configuration » Configuration Manual » rc_media_create","id":"383","title":"rc_media_create"},"384":{"body":"Defines limits on federation requests. The rc_federation configuration has the following sub-options: window_size: window size in milliseconds. Defaults to 1000. sleep_limit: number of federation requests from a single server in a window before the server will delay processing the request. Defaults to 10. sleep_delay: duration in milliseconds to delay processing events from remote servers by if they go over the sleep limit. Defaults to 500. reject_limit: maximum number of concurrent federation requests allowed from a single server. Defaults to 50. concurrent: number of federation requests to concurrently process from a single server. Defaults to 3. Example configuration: rc_federation: window_size: 750 sleep_limit: 15 sleep_delay: 400 reject_limit: 40 concurrent: 5","breadcrumbs":"Configuration » Configuration Manual » rc_federation","id":"384","title":"rc_federation"},"385":{"body":"This option sets ratelimiting for presence. The rc_presence.per_user option sets rate limits on how often a specific users' presence updates are evaluated. Ratelimited presence updates sent via sync are ignored, and no error is returned to the client. This option also sets the rate limit for the PUT /_matrix/client/v3/presence/{userId}/status endpoint. per_user defaults to per_second: 0.1, burst_count: 1. Example configuration: rc_presence: per_user: per_second: 0.05 burst_count: 1","breadcrumbs":"Configuration » Configuration Manual » rc_presence","id":"385","title":"rc_presence"},"386":{"body":"Ratelimiting settings for delayed event management. This is a ratelimiting option that ratelimits attempts to restart, cancel, or view delayed events based on the sending client's account and device ID. It defaults to: per_second: 1, burst_count: 5. Attempts to create or send delayed events are ratelimited not by this setting, but by rc_message. Setting this to a high value allows clients to make delayed event management requests often (such as repeatedly restarting a delayed event with a short timeout, or restarting several different delayed events all at once) without the risk of being ratelimited. Example configuration: rc_delayed_event_mgmt: per_second: 2 burst_count: 20","breadcrumbs":"Configuration » Configuration Manual » rc_delayed_event_mgmt","id":"386","title":"rc_delayed_event_mgmt"},"387":{"body":"Sets outgoing federation transaction frequency for sending read-receipts, per-room. If we end up trying to send out more read-receipts, they will get buffered up into fewer transactions. Defaults to 50. Example configuration: federation_rr_transactions_per_room_per_second: 40","breadcrumbs":"Configuration » Configuration Manual » federation_rr_transactions_per_room_per_second","id":"387","title":"federation_rr_transactions_per_room_per_second"},"388":{"body":"Config options related to Synapse's media store.","breadcrumbs":"Configuration » Configuration Manual » Media Store","id":"388","title":"Media Store"},"389":{"body":"When set to true, all subsequent media uploads will be marked as authenticated, and will not be available over legacy unauthenticated media endpoints (/_matrix/media/(r0|v3|v1)/download and /_matrix/media/(r0|v3|v1)/thumbnail) - requests for authenticated media over these endpoints will result in a 404. All media, including authenticated media, will be available over the authenticated media endpoints _matrix/client/v1/media/download and _matrix/client/v1/media/thumbnail. Media uploaded prior to setting this option to true will still be available over the legacy endpoints. Note if the setting is switched to false after enabling, media marked as authenticated will be available over legacy endpoints. Defaults to true (previously false). In a future release of Synapse, this option will be removed and become always-on. In all cases, authenticated requests to download media will succeed, but for unauthenticated requests, this case-by-case breakdown describes whether media downloads are permitted: enable_authenticated_media = False: unauthenticated client or homeserver requesting local media: allowed unauthenticated client or homeserver requesting remote media: allowed as long as the media is in the cache, or as long as the remote homeserver does not require authentication to retrieve the media enable_authenticated_media = True: unauthenticated client or homeserver requesting local media: allowed if the media was stored on the server whilst enable_authenticated_media was False (or in a previous Synapse version where this option did not exist); otherwise denied. unauthenticated client or homeserver requesting remote media: the same as for local media; allowed if the media was stored on the server whilst enable_authenticated_media was False (or in a previous Synapse version where this option did not exist); otherwise denied. It is especially notable that media downloaded before this option existed (in older Synapse versions), or whilst this option was set to False, will perpetually be available over the legacy, unauthenticated endpoint, even after this option is set to True. This is for backwards compatibility with older clients and homeservers that do not yet support requesting authenticated media; those older clients or homeservers will not be cut off from media they can already see. Changed in Synapse 1.120: This option now defaults to True when not set, whereas before this version it defaulted to False. Example configuration: enable_authenticated_media: false","breadcrumbs":"Configuration » Configuration Manual » enable_authenticated_media","id":"389","title":"enable_authenticated_media"},"39":{"body":"table { 127.0.0.1 }\ntable { 127.0.0.1 } http protocol \"https\" { tls { no tlsv1.0, ciphers \"HIGH\" } tls keypair \"example.com\" match header set \"X-Forwarded-For\" value \"$REMOTE_ADDR\" match header set \"X-Forwarded-Proto\" value \"https\" # set CORS header for .well-known/matrix/server, .well-known/matrix/client # httpd does not support setting headers, so do it here match request path \"/.well-known/matrix/*\" tag \"matrix-cors\" match response tagged \"matrix-cors\" header set \"Access-Control-Allow-Origin\" value \"*\" pass quick path \"/_matrix/*\" forward to pass quick path \"/_synapse/client/*\" forward to # pass on non-matrix traffic to webserver pass forward to \n} relay \"https_traffic\" { listen on egress port 443 tls protocol \"https\" forward to port 8008 check tcp forward to port 8080 check tcp\n} http protocol \"matrix\" { tls { no tlsv1.0, ciphers \"HIGH\" } tls keypair \"example.com\" block pass quick path \"/_matrix/*\" forward to pass quick path \"/_synapse/client/*\" forward to \n} relay \"matrix_federation\" { listen on egress port 8448 tls protocol \"matrix\" forward to port 8008 check tcp\n}","breadcrumbs":"Configuring a Reverse Proxy » Relayd","id":"39","title":"Relayd"},"390":{"body":"Enable the media store service in the Synapse master. Defaults to true. Set to false if you are using a separate media store worker. Example configuration: enable_media_repo: false","breadcrumbs":"Configuration » Configuration Manual » enable_media_repo","id":"390","title":"enable_media_repo"},"391":{"body":"Directory where uploaded images and attachments are stored. Example configuration: media_store_path: \"DATADIR/media_store\"","breadcrumbs":"Configuration » Configuration Manual » media_store_path","id":"391","title":"media_store_path"},"392":{"body":"How many pending media uploads can a given user have? A pending media upload is a created MXC URI that (a) is not expired (the unused_expires_at timestamp has not passed) and (b) the media has not yet been uploaded for. Defaults to 5. Example configuration: max_pending_media_uploads: 5","breadcrumbs":"Configuration » Configuration Manual » max_pending_media_uploads","id":"392","title":"max_pending_media_uploads"},"393":{"body":"How long to wait in milliseconds before expiring created media IDs. Defaults to \"24h\" Example configuration: unused_expiration_time: \"1h\"","breadcrumbs":"Configuration » Configuration Manual » unused_expiration_time","id":"393","title":"unused_expiration_time"},"394":{"body":"Media storage providers allow media to be stored in different locations. Defaults to none. Associated sub-options are: module: type of resource, e.g. file_system. store_local: whether to store newly uploaded local files store_remote: whether to store newly downloaded local files store_synchronous: whether to wait for successful storage for local uploads config: sets a path to the resource through the directory option Example configuration: media_storage_providers: - module: file_system store_local: false store_remote: false store_synchronous: false config: directory: /mnt/some/other/directory","breadcrumbs":"Configuration » Configuration Manual » media_storage_providers","id":"394","title":"media_storage_providers"},"395":{"body":"The largest allowed upload size in bytes. If you are using a reverse proxy you may also need to set this value in your reverse proxy's config. Defaults to 50M. Notably Nginx has a small max body size by default. See here for more on using a reverse proxy with Synapse. Example configuration: max_upload_size: 60M","breadcrumbs":"Configuration » Configuration Manual » max_upload_size","id":"395","title":"max_upload_size"},"396":{"body":"Maximum number of pixels that will be thumbnailed. Defaults to 32M. Example configuration: max_image_pixels: 35M","breadcrumbs":"Configuration » Configuration Manual » max_image_pixels","id":"396","title":"max_image_pixels"},"397":{"body":"Remote media downloads are ratelimited using a leaky bucket algorithm , where a given \"bucket\" is keyed to the IP address of the requester when requesting remote media downloads. This configuration option sets the size of the bucket against which the size in bytes of downloads are penalized - if the bucket is full, ie a given number of bytes have already been downloaded, further downloads will be denied until the bucket drains. Defaults to 500MiB. See also remote_media_download_per_second which determines the rate at which the \"bucket\" is emptied and thus has available space to authorize new requests. Example configuration: remote_media_download_burst_count: 200M","breadcrumbs":"Configuration » Configuration Manual » remote_media_download_burst_count","id":"397","title":"remote_media_download_burst_count"},"398":{"body":"Works in conjunction with remote_media_download_burst_count to ratelimit remote media downloads - this configuration option determines the rate at which the \"bucket\" (see above) leaks in bytes per second. As requests are made to download remote media, the size of those requests in bytes is added to the bucket, and once the bucket has reached it's capacity, no more requests will be allowed until a number of bytes has \"drained\" from the bucket. This setting determines the rate at which bytes drain from the bucket, with the practical effect that the larger the number, the faster the bucket leaks, allowing for more bytes downloaded over a shorter period of time. Defaults to 87KiB per second. See also remote_media_download_burst_count. Example configuration: remote_media_download_per_second: 40K","breadcrumbs":"Configuration » Configuration Manual » remote_media_download_per_second","id":"398","title":"remote_media_download_per_second"},"399":{"body":"A list of domains to never download media from. Media from these domains that is already downloaded will not be deleted, but will be inaccessible to users. This option does not affect admin APIs trying to download/operate on media. This will not prevent the listed domains from accessing media themselves. It simply prevents users on this server from downloading media originating from the listed servers. This will have no effect on media originating from the local server. This only affects media downloaded from other Matrix servers, to control URL previews see url_preview_ip_range_blacklist or url_preview_url_blacklist . Defaults to an empty list (nothing blocked). Example configuration: prevent_media_downloads_from: - evil.example.org - evil2.example.org","breadcrumbs":"Configuration » Configuration Manual » prevent_media_downloads_from","id":"399","title":"prevent_media_downloads_from"},"4":{"body":"","breadcrumbs":"Installation » Installation Instructions","id":"4","title":"Installation Instructions"},"40":{"body":"Synapse exposes a health check endpoint for use by reverse proxies. Each configured HTTP listener has a /health endpoint which always returns 200 OK (and doesn't get logged).","breadcrumbs":"Configuring a Reverse Proxy » Health check endpoint","id":"40","title":"Health check endpoint"},"400":{"body":"Whether to generate new thumbnails on the fly to precisely match the resolution requested by the client. If true then whenever a new resolution is requested by the client the server will generate a new thumbnail. If false the server will pick a thumbnail from a precalculated list. Defaults to false. Example configuration: dynamic_thumbnails: true","breadcrumbs":"Configuration » Configuration Manual » dynamic_thumbnails","id":"400","title":"dynamic_thumbnails"},"401":{"body":"List of thumbnails to precalculate when an image is uploaded. Associated sub-options are: width height method: i.e. crop, scale, etc. Example configuration: thumbnail_sizes: - width: 32 height: 32 method: crop - width: 96 height: 96 method: crop - width: 320 height: 240 method: scale - width: 640 height: 480 method: scale - width: 800 height: 600 method: scale","breadcrumbs":"Configuration » Configuration Manual » thumbnail_sizes","id":"401","title":"thumbnail_sizes"},"402":{"body":"Controls whether local media and entries in the remote media cache (media that is downloaded from other homeservers) should be removed under certain conditions, typically for the purpose of saving space. Purging media files will be the carried out by the media worker (that is, the worker that has the enable_media_repo homeserver config option set to 'true'). This may be the main process. The media_retention.local_media_lifetime and media_retention.remote_media_lifetime config options control whether media will be purged if it has not been accessed in a given amount of time. Note that media is 'accessed' when loaded in a room in a client, or otherwise downloaded by a local or remote user. If the media has never been accessed, the media's creation time is used instead. Both thumbnails and the original media will be removed. If either of these options are unset, then media of that type will not be purged. Local or cached remote media that has been quarantined will not be deleted. Similarly, local media that has been marked as protected from quarantine will not be deleted. Example configuration: media_retention: local_media_lifetime: 90d remote_media_lifetime: 14d","breadcrumbs":"Configuration » Configuration Manual » media_retention","id":"402","title":"media_retention"},"403":{"body":"This setting determines whether the preview URL API is enabled. It is disabled by default. Set to true to enable. If enabled you must specify a url_preview_ip_range_blacklist blacklist. Example configuration: url_preview_enabled: true","breadcrumbs":"Configuration » Configuration Manual » url_preview_enabled","id":"403","title":"url_preview_enabled"},"404":{"body":"List of IP address CIDR ranges that the URL preview spider is denied from accessing. There are no defaults: you must explicitly specify a list for URL previewing to work. You should specify any internal services in your network that you do not want synapse to try to connect to, otherwise anyone in any Matrix room could cause your synapse to issue arbitrary GET requests to your internal services, causing serious security issues. (0.0.0.0 and :: are always blacklisted, whether or not they are explicitly listed here, since they correspond to unroutable addresses.) This must be specified if url_preview_enabled is set. It is recommended that you use the following example list as a starting point. Note: The value is ignored when an HTTP proxy is in use. Example configuration: url_preview_ip_range_blacklist: - '127.0.0.0/8' - '10.0.0.0/8' - '172.16.0.0/12' - '192.168.0.0/16' - '100.64.0.0/10' - '192.0.0.0/24' - '169.254.0.0/16' - '192.88.99.0/24' - '198.18.0.0/15' - '192.0.2.0/24' - '198.51.100.0/24' - '203.0.113.0/24' - '224.0.0.0/4' - '::1/128' - 'fe80::/10' - 'fc00::/7' - '2001:db8::/32' - 'ff00::/8' - 'fec0::/10'","breadcrumbs":"Configuration » Configuration Manual » url_preview_ip_range_blacklist","id":"404","title":"url_preview_ip_range_blacklist"},"405":{"body":"This option sets a list of IP address CIDR ranges that the URL preview spider is allowed to access even if they are specified in url_preview_ip_range_blacklist. This is useful for specifying exceptions to wide-ranging blacklisted target IP ranges - e.g. for enabling URL previews for a specific private website only visible in your network. Defaults to none. Example configuration: url_preview_ip_range_whitelist: - '192.168.1.1'","breadcrumbs":"Configuration » Configuration Manual » url_preview_ip_range_whitelist","id":"405","title":"url_preview_ip_range_whitelist"},"406":{"body":"Optional list of URL matches that the URL preview spider is denied from accessing. This is a usability feature, not a security one. You should use url_preview_ip_range_blacklist in preference to this, otherwise someone could define a public DNS entry that points to a private IP address and circumvent the blacklist. Applications that perform redirects or serve different content when detecting that Synapse is accessing them can also bypass the blacklist. This is more useful if you know there is an entire shape of URL that you know that you do not want Synapse to preview. Each list entry is a dictionary of url component attributes as returned by urlparse.urlsplit as applied to the absolute form of the URL. See here for more information. Some examples are: username netloc scheme path The values of the dictionary are treated as a filename match pattern applied to that component of URLs, unless they start with a ^ in which case they are treated as a regular expression match. If all the specified component matches for a given list item succeed, the URL is blacklisted. Example configuration: url_preview_url_blacklist: # blacklist any URL with a username in its URI - username: '*' # blacklist all *.google.com URLs - netloc: 'google.com' - netloc: '*.google.com' # blacklist all plain HTTP URLs - scheme: 'http' # blacklist http(s)://www.acme.com/foo - netloc: 'www.acme.com' path: '/foo' # blacklist any URL with a literal IPv4 address - netloc: '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$'","breadcrumbs":"Configuration » Configuration Manual » url_preview_url_blacklist","id":"406","title":"url_preview_url_blacklist"},"407":{"body":"The largest allowed URL preview spidering size in bytes. Defaults to 10M. Example configuration: max_spider_size: 8M","breadcrumbs":"Configuration » Configuration Manual » max_spider_size","id":"407","title":"max_spider_size"},"408":{"body":"A list of values for the Accept-Language HTTP header used when downloading webpages during URL preview generation. This allows Synapse to specify the preferred languages that URL previews should be in when communicating with remote servers. Each value is a IETF language tag; a 2-3 letter identifier for a language, optionally followed by subtags separated by '-', specifying a country or region variant. Multiple values can be provided, and a weight can be added to each by using quality value syntax (;q=). '*' translates to any language. Defaults to \"en\". Example configuration: url_preview_accept_language: - 'en-UK' - 'en-US;q=0.9' - 'fr;q=0.8' - '*;q=0.7'","breadcrumbs":"Configuration » Configuration Manual » url_preview_accept_language","id":"408","title":"url_preview_accept_language"},"409":{"body":"oEmbed allows for easier embedding content from a website. It can be used for generating URLs previews of services which support it. A default list of oEmbed providers is included with Synapse. Set disable_default_providers to true to disable using these default oEmbed URLs. Use additional_providers to specify additional files with oEmbed configuration (each should be in the form of providers.json). By default this list is empty. Example configuration: oembed: disable_default_providers: true additional_providers: - oembed/my_providers.json","breadcrumbs":"Configuration » Configuration Manual » oembed","id":"409","title":"oembed"},"41":{"body":"Endpoints for administering your Synapse instance are placed under /_synapse/admin. These require authentication through an access token of an admin user. However as access to these endpoints grants the caller a lot of power, we do not recommend exposing them to the public internet without good reason.","breadcrumbs":"Configuring a Reverse Proxy » Synapse administration endpoints","id":"41","title":"Synapse administration endpoints"},"410":{"body":"See here for full details on setting up captcha.","breadcrumbs":"Configuration » Configuration Manual » Captcha","id":"410","title":"Captcha"},"411":{"body":"This homeserver's ReCAPTCHA public key. Must be specified if enable_registration_captcha is enabled. Example configuration: recaptcha_public_key: \"YOUR_PUBLIC_KEY\"","breadcrumbs":"Configuration » Configuration Manual » recaptcha_public_key","id":"411","title":"recaptcha_public_key"},"412":{"body":"This homeserver's ReCAPTCHA private key. Must be specified if enable_registration_captcha is enabled. Example configuration: recaptcha_private_key: \"YOUR_PRIVATE_KEY\"","breadcrumbs":"Configuration » Configuration Manual » recaptcha_private_key","id":"412","title":"recaptcha_private_key"},"413":{"body":"Set to true to require users to complete a CAPTCHA test when registering an account. Requires a valid ReCaptcha public/private key. Defaults to false. Note that enable_registration must also be set to allow account registration. Example configuration: enable_registration_captcha: true","breadcrumbs":"Configuration » Configuration Manual » enable_registration_captcha","id":"413","title":"enable_registration_captcha"},"414":{"body":"The API endpoint to use for verifying m.login.recaptcha responses. Defaults to https://www.recaptcha.net/recaptcha/api/siteverify. Example configuration: recaptcha_siteverify_api: \"https://my.recaptcha.site\"","breadcrumbs":"Configuration » Configuration Manual » recaptcha_siteverify_api","id":"414","title":"recaptcha_siteverify_api"},"415":{"body":"Options related to adding a TURN server to Synapse.","breadcrumbs":"Configuration » Configuration Manual » TURN","id":"415","title":"TURN"},"416":{"body":"The public URIs of the TURN server to give to clients. Example configuration: turn_uris: [turn:example.org]","breadcrumbs":"Configuration » Configuration Manual » turn_uris","id":"416","title":"turn_uris"},"417":{"body":"The shared secret used to compute passwords for the TURN server. Example configuration: turn_shared_secret: \"YOUR_SHARED_SECRET\"","breadcrumbs":"Configuration » Configuration Manual » turn_shared_secret","id":"417","title":"turn_shared_secret"},"418":{"body":"An alternative to turn_shared_secret : allows the shared secret to be specified in an external file. The file should be a plain text file, containing only the shared secret. Synapse reads the shared secret from the given file once at startup. Example configuration: turn_shared_secret_path: /path/to/secrets/file Added in Synapse 1.116.0.","breadcrumbs":"Configuration » Configuration Manual » turn_shared_secret_path","id":"418","title":"turn_shared_secret_path"},"419":{"body":"The Username and password if the TURN server needs them and does not use a token. Example configuration: turn_username: \"TURNSERVER_USERNAME\"\nturn_password: \"TURNSERVER_PASSWORD\"","breadcrumbs":"Configuration » Configuration Manual » turn_username and turn_password","id":"419","title":"turn_username and turn_password"},"42":{"body":"You can use Synapse with a forward or outbound proxy. An example of when this is necessary is in corporate environments behind a DMZ (demilitarized zone). Synapse supports routing outbound HTTP(S) requests via a proxy. Only HTTP(S) proxy is supported, not SOCKS proxy or anything else.","breadcrumbs":"Configuring a Forward/Outbound Proxy » Using a forward proxy with Synapse","id":"42","title":"Using a forward proxy with Synapse"},"420":{"body":"How long generated TURN credentials last. Defaults to 1h. Example configuration: turn_user_lifetime: 2h","breadcrumbs":"Configuration » Configuration Manual » turn_user_lifetime","id":"420","title":"turn_user_lifetime"},"421":{"body":"Whether guests should be allowed to use the TURN server. This defaults to true, otherwise VoIP will be unreliable for guests. However, it does introduce a slight security risk as it allows users to connect to arbitrary endpoints without having first signed up for a valid account (e.g. by passing a CAPTCHA). Example configuration: turn_allow_guests: false","breadcrumbs":"Configuration » Configuration Manual » turn_allow_guests","id":"421","title":"turn_allow_guests"},"422":{"body":"Registration can be rate-limited using the parameters in the Ratelimiting section of this manual.","breadcrumbs":"Configuration » Configuration Manual » Registration","id":"422","title":"Registration"},"423":{"body":"Enable registration for new users. Defaults to false. It is highly recommended that if you enable registration, you set one or more or the following options, to avoid abuse of your server by \"bots\": enable_registration_captcha registrations_require_3pid registration_requires_token (In order to enable registration without any verification, you must also set enable_registration_without_verification .) Note that even if this setting is disabled, new accounts can still be created via the admin API if registration_shared_secret is set. Example configuration: enable_registration: true","breadcrumbs":"Configuration » Configuration Manual » enable_registration","id":"423","title":"enable_registration"},"424":{"body":"Enable registration without email or captcha verification. Note: this option is not recommended, as registration without verification is a known vector for spam and abuse. Defaults to false. Has no effect unless enable_registration is also enabled. Example configuration: enable_registration_without_verification: true","breadcrumbs":"Configuration » Configuration Manual » enable_registration_without_verification","id":"424","title":"enable_registration_without_verification"},"425":{"body":"If this is set, users must provide all of the specified types of 3PID when registering an account. Note that enable_registration must also be set to allow account registration. Example configuration: registrations_require_3pid: - email - msisdn","breadcrumbs":"Configuration » Configuration Manual » registrations_require_3pid","id":"425","title":"registrations_require_3pid"},"426":{"body":"Explicitly disable asking for MSISDNs from the registration flow (overrides registrations_require_3pid if MSISDNs are set as required). Example configuration: disable_msisdn_registration: true","breadcrumbs":"Configuration » Configuration Manual » disable_msisdn_registration","id":"426","title":"disable_msisdn_registration"},"427":{"body":"Mandate that users are only allowed to associate certain formats of 3PIDs with accounts on this server, as specified by the medium and pattern sub-options. pattern is a Perl-like regular expression . More information about 3PIDs, allowed medium types and their address syntax can be found in the Matrix spec . Example configuration: allowed_local_3pids: - medium: email pattern: '^[^@]+@matrix\\.org$' - medium: email pattern: '^[^@]+@vector\\.im$' - medium: msisdn pattern: '^44\\d{10}$'","breadcrumbs":"Configuration » Configuration Manual » allowed_local_3pids","id":"427","title":"allowed_local_3pids"},"428":{"body":"Enable 3PIDs lookup requests to identity servers from this server. Defaults to true. Example configuration: enable_3pid_lookup: false","breadcrumbs":"Configuration » Configuration Manual » enable_3pid_lookup","id":"428","title":"enable_3pid_lookup"},"429":{"body":"Require users to submit a token during registration. Tokens can be managed using the admin API . Disabling this option will not delete any tokens previously generated. Defaults to false. Set to true to enable. Note that enable_registration must also be set to allow account registration. Example configuration: registration_requires_token: true","breadcrumbs":"Configuration » Configuration Manual » registration_requires_token","id":"429","title":"registration_requires_token"},"43":{"body":"The http_proxy, https_proxy, no_proxy environment variables are used to specify proxy settings. The environment variable is not case sensitive. http_proxy: Proxy server to use for HTTP requests. https_proxy: Proxy server to use for HTTPS requests. no_proxy: Comma-separated list of hosts, IP addresses, or IP ranges in CIDR format which should not use the proxy. Synapse will directly connect to these hosts. The http_proxy and https_proxy environment variables have the form: [scheme://][:@][:] Supported schemes are http:// and https://. The default scheme is http:// for compatibility reasons; it is recommended to set a scheme. If scheme is set to https:// the connection uses TLS between Synapse and the proxy. NOTE : Synapse validates the certificates. If the certificate is not valid, then the connection is dropped. Default port if not given is 1080. Username and password are optional and will be used to authenticate against the proxy. Examples HTTP_PROXY=http://USERNAME:PASSWORD@10.0.1.1:8080/ HTTPS_PROXY=http://USERNAME:PASSWORD@proxy.example.com:8080/ NO_PROXY=master.hostname.example.com,10.1.0.0/16,172.30.0.0/16 NOTE : Synapse does not apply the IP blacklist to connections through the proxy (since the DNS resolution is done by the proxy). It is expected that the proxy or firewall will apply blacklisting of IP addresses.","breadcrumbs":"Configuring a Forward/Outbound Proxy » Configure","id":"43","title":"Configure"},"430":{"body":"If set, allows registration of standard or admin accounts by anyone who has the shared secret, even if enable_registration is not set. This is primarily intended for use with the register_new_matrix_user script (see Registering a user ); however, the interface is documented . Replacing an existing registration_shared_secret with a new one requires users of the Shared-Secret Registration API to start using the new secret for requesting any further one-time nonces. ⚠️ Warning – The additional consequences of replacing macaroon_secret_key will apply in case it delegates to registration_shared_secret. See also registration_shared_secret_path . Example configuration: registration_shared_secret: ","breadcrumbs":"Configuration » Configuration Manual » registration_shared_secret","id":"430","title":"registration_shared_secret"},"431":{"body":"An alternative to registration_shared_secret : allows the shared secret to be specified in an external file. The file should be a plain text file, containing only the shared secret. If this file does not exist, Synapse will create a new shared secret on startup and store it in this file. Example configuration: registration_shared_secret_path: /path/to/secrets/file Added in Synapse 1.67.0.","breadcrumbs":"Configuration » Configuration Manual » registration_shared_secret_path","id":"431","title":"registration_shared_secret_path"},"432":{"body":"Set the number of bcrypt rounds used to generate password hash. Larger numbers increase the work factor needed to generate the hash. The default number is 12 (which equates to 2^12 rounds). N.B. that increasing this will exponentially increase the time required to register or login - e.g. 24 => 2^24 rounds which will take >20 mins. Example configuration: bcrypt_rounds: 14","breadcrumbs":"Configuration » Configuration Manual » bcrypt_rounds","id":"432","title":"bcrypt_rounds"},"433":{"body":"Allows users to register as guests without a password/email/etc, and participate in rooms hosted on this server which have been made accessible to anonymous users. Defaults to false. Example configuration: allow_guest_access: true","breadcrumbs":"Configuration » Configuration Manual » allow_guest_access","id":"433","title":"allow_guest_access"},"434":{"body":"The identity server which we suggest that clients should use when users log in on this server. (By default, no suggestion is made, so it is left up to the client. This setting is ignored unless public_baseurl is also explicitly set.) Example configuration: default_identity_server: https://matrix.org","breadcrumbs":"Configuration » Configuration Manual » default_identity_server","id":"434","title":"default_identity_server"},"435":{"body":"Delegate verification of phone numbers to an identity server. When a user wishes to add a phone number to their account, we need to verify that they actually own that phone number, which requires sending them a text message (SMS). Currently Synapse does not support sending those texts itself and instead delegates the task to an identity server. The base URI for the identity server to be used is specified by the account_threepid_delegates.msisdn option. If this is left unspecified, Synapse will not allow users to add phone numbers to their account. (Servers handling the these requests must answer the /requestToken endpoints defined by the Matrix Identity Service API specification .) Deprecated in Synapse 1.64.0 : The email option is deprecated. Removed in Synapse 1.66.0 : The email option has been removed. If present, Synapse will report a configuration error on startup. Example configuration: account_threepid_delegates: msisdn: http://localhost:8090 # Delegate SMS sending to this local process","breadcrumbs":"Configuration » Configuration Manual » account_threepid_delegates","id":"435","title":"account_threepid_delegates"},"436":{"body":"Whether users are allowed to change their displayname after it has been initially set. Useful when provisioning users based on the contents of a third-party directory. Does not apply to server administrators. Defaults to true. Example configuration: enable_set_displayname: false","breadcrumbs":"Configuration » Configuration Manual » enable_set_displayname","id":"436","title":"enable_set_displayname"},"437":{"body":"Whether users are allowed to change their avatar after it has been initially set. Useful when provisioning users based on the contents of a third-party directory. Does not apply to server administrators. Defaults to true. Example configuration: enable_set_avatar_url: false","breadcrumbs":"Configuration » Configuration Manual » enable_set_avatar_url","id":"437","title":"enable_set_avatar_url"},"438":{"body":"Whether users can change the third-party IDs associated with their accounts (email address and msisdn). Defaults to true. Example configuration: enable_3pid_changes: false","breadcrumbs":"Configuration » Configuration Manual » enable_3pid_changes","id":"438","title":"enable_3pid_changes"},"439":{"body":"Users who register on this homeserver will automatically be joined to the rooms listed under this option. By default, any room aliases included in this list will be created as a publicly joinable room when the first user registers for the homeserver. If the room already exists, make certain it is a publicly joinable room, i.e. the join rule of the room must be set to 'public'. You can find more options relating to auto-joining rooms below. As Spaces are just rooms under the hood, Space aliases may also be used. Example configuration: auto_join_rooms: - \"#exampleroom:example.com\" - \"#anotherexampleroom:example.com\"","breadcrumbs":"Configuration » Configuration Manual » auto_join_rooms","id":"439","title":"auto_join_rooms"},"44":{"body":"The proxy will be used for: push url previews phone-home stats recaptcha validation CAS auth validation OpenID Connect Outbound federation Federation (checking public key revocation) Fetching public keys of other servers Downloading remote media It will not be used for: Application Services Identity servers In worker configurations connections between workers connections from workers to Redis","breadcrumbs":"Configuring a Forward/Outbound Proxy » Connection types","id":"44","title":"Connection types"},"440":{"body":"Where auto_join_rooms are specified, setting this flag ensures that the rooms exist by creating them when the first user on the homeserver registers. This option will not create Spaces. By default the auto-created rooms are publicly joinable from any federated server. Use the autocreate_auto_join_rooms_federated and autocreate_auto_join_room_preset settings to customise this behaviour. Setting to false means that if the rooms are not manually created, users cannot be auto-joined since they do not exist. Defaults to true. Example configuration: autocreate_auto_join_rooms: false","breadcrumbs":"Configuration » Configuration Manual » autocreate_auto_join_rooms","id":"440","title":"autocreate_auto_join_rooms"},"441":{"body":"Whether the rooms listed in auto_join_rooms that are auto-created are available via federation. Only has an effect if autocreate_auto_join_rooms is true. Note that whether a room is federated cannot be modified after creation. Defaults to true: the room will be joinable from other servers. Set to false to prevent users from other homeservers from joining these rooms. Example configuration: autocreate_auto_join_rooms_federated: false","breadcrumbs":"Configuration » Configuration Manual » autocreate_auto_join_rooms_federated","id":"441","title":"autocreate_auto_join_rooms_federated"},"442":{"body":"The room preset to use when auto-creating one of auto_join_rooms. Only has an effect if autocreate_auto_join_rooms is true. Possible values for this option are: \"public_chat\": the room is joinable by anyone, including federated servers if autocreate_auto_join_rooms_federated is true (the default). \"private_chat\": an invitation is required to join these rooms. \"trusted_private_chat\": an invitation is required to join this room and the invitee is assigned a power level of 100 upon joining the room. Each preset will set up a room in the same manner as if it were provided as the preset parameter when calling the POST /_matrix/client/v3/createRoom Client-Server API endpoint. If a value of \"private_chat\" or \"trusted_private_chat\" is used then auto_join_mxid_localpart must also be configured. Defaults to \"public_chat\". Example configuration: autocreate_auto_join_room_preset: private_chat","breadcrumbs":"Configuration » Configuration Manual » autocreate_auto_join_room_preset","id":"442","title":"autocreate_auto_join_room_preset"},"443":{"body":"The local part of the user id which is used to create auto_join_rooms if autocreate_auto_join_rooms is true. If this is not provided then the initial user account that registers will be used to create the rooms. The user id is also used to invite new users to any auto-join rooms which are set to invite-only. It must be configured if autocreate_auto_join_room_preset is set to \"private_chat\" or \"trusted_private_chat\". Note that this must be specified in order for new users to be correctly invited to any auto-join rooms which have been set to invite-only (either at the time of creation or subsequently). Note that, if the room already exists, this user must be joined and have the appropriate permissions to invite new members. Example configuration: auto_join_mxid_localpart: system","breadcrumbs":"Configuration » Configuration Manual » auto_join_mxid_localpart","id":"443","title":"auto_join_mxid_localpart"},"444":{"body":"When auto_join_rooms is specified, setting this flag to false prevents guest accounts from being automatically joined to the rooms. Defaults to true. Example configuration: auto_join_rooms_for_guests: false","breadcrumbs":"Configuration » Configuration Manual » auto_join_rooms_for_guests","id":"444","title":"auto_join_rooms_for_guests"},"445":{"body":"Whether to inhibit errors raised when registering a new account if the user ID already exists. If turned on, requests to /register/available will always show a user ID as available, and Synapse won't raise an error when starting a registration with a user ID that already exists. However, Synapse will still raise an error if the registration completes and the username conflicts. Defaults to false. Example configuration: inhibit_user_in_use_error: true","breadcrumbs":"Configuration » Configuration Manual » inhibit_user_in_use_error","id":"445","title":"inhibit_user_in_use_error"},"446":{"body":"Whether users are allowed to register with a underscore-prefixed localpart. By default, AppServices use prefixes like _example to namespace their associated ghost users. If turned on, this may result in clashes or confusion. Useful when provisioning users from an external identity provider. Defaults to false. Example configuration: allow_underscore_prefixed_registration: false","breadcrumbs":"Configuration » Configuration Manual » allow_underscore_prefixed_registration","id":"446","title":"allow_underscore_prefixed_registration"},"447":{"body":"","breadcrumbs":"Configuration » Configuration Manual » User session management","id":"447","title":"User session management"},"448":{"body":"Time that a user's session remains valid for, after they log in. Note that this is not currently compatible with guest logins. Note also that this is calculated at login time: changes are not applied retrospectively to users who have already logged in. By default, this is infinite. Example configuration: session_lifetime: 24h","breadcrumbs":"Configuration » Configuration Manual » session_lifetime","id":"448","title":"session_lifetime"},"449":{"body":"Time that an access token remains valid for, if the session is using refresh tokens. For more information about refresh tokens, please see the manual . Note that this only applies to clients which advertise support for refresh tokens. Note also that this is calculated at login time and refresh time: changes are not applied to existing sessions until they are refreshed. By default, this is 5 minutes. Example configuration: refreshable_access_token_lifetime: 10m","breadcrumbs":"Configuration » Configuration Manual » refreshable_access_token_lifetime","id":"449","title":"refreshable_access_token_lifetime"},"45":{"body":"If a proxy server is used with TLS (HTTPS) and no connections are established, it is most likely due to the proxy's certificates. To test this, the validation in Synapse can be deactivated. NOTE : This has an impact on security and is for testing purposes only! To deactivate the certificate validation, the following setting must be added to your homeserver.yaml . use_insecure_ssl_client_just_for_testing_do_not_use: true","breadcrumbs":"Configuring a Forward/Outbound Proxy » Troubleshooting","id":"45","title":"Troubleshooting"},"450":{"body":"Time that a refresh token remains valid for (provided that it is not exchanged for another one first). This option can be used to automatically log-out inactive sessions. Please see the manual for more information. Note also that this is calculated at login time and refresh time: changes are not applied to existing sessions until they are refreshed. By default, this is infinite. Example configuration: refresh_token_lifetime: 24h","breadcrumbs":"Configuration » Configuration Manual » refresh_token_lifetime","id":"450","title":"refresh_token_lifetime"},"451":{"body":"Time that an access token remains valid for, if the session is NOT using refresh tokens. Please note that not all clients support refresh tokens, so setting this to a short value may be inconvenient for some users who will then be logged out frequently. Note also that this is calculated at login time: changes are not applied retrospectively to existing sessions for users that have already logged in. By default, this is infinite. Example configuration: nonrefreshable_access_token_lifetime: 24h","breadcrumbs":"Configuration » Configuration Manual » nonrefreshable_access_token_lifetime","id":"451","title":"nonrefreshable_access_token_lifetime"},"452":{"body":"The amount of time to allow a user-interactive authentication session to be active. This defaults to 0, meaning the user is queried for their credentials before every action, but this can be overridden to allow a single validation to be re-used. This weakens the protections afforded by the user-interactive authentication process, by allowing for multiple (and potentially different) operations to use the same validation session. This is ignored for potentially \"dangerous\" operations (including deactivating an account, modifying an account password, adding a 3PID, and minting additional login tokens). Use the session_timeout sub-option here to change the time allowed for credential validation. Example configuration: ui_auth: session_timeout: \"15s\"","breadcrumbs":"Configuration » Configuration Manual » ui_auth","id":"452","title":"ui_auth"},"453":{"body":"Matrix supports the ability of an existing session to mint a login token for another client. Synapse disables this by default as it has security ramifications -- a malicious client could use the mechanism to spawn more than one session. The duration of time the generated token is valid for can be configured with the token_timeout sub-option. User-interactive authentication is required when this is enabled unless the require_ui_auth sub-option is set to False. Example configuration: login_via_existing_session: enabled: true require_ui_auth: false token_timeout: \"5m\"","breadcrumbs":"Configuration » Configuration Manual » login_via_existing_session","id":"453","title":"login_via_existing_session"},"454":{"body":"Config options related to metrics.","breadcrumbs":"Configuration » Configuration Manual » Metrics","id":"454","title":"Metrics"},"455":{"body":"Set to true to enable collection and rendering of performance metrics. Defaults to false. Example configuration: enable_metrics: true","breadcrumbs":"Configuration » Configuration Manual » enable_metrics","id":"455","title":"enable_metrics"},"456":{"body":"Use this option to enable sentry integration. Provide the DSN assigned to you by sentry with the dsn setting. An optional environment field can be used to specify an environment. This allows for log maintenance based on different environments, ensuring better organization and analysis.. NOTE: While attempts are made to ensure that the logs don't contain any sensitive information, this cannot be guaranteed. By enabling this option the sentry server may therefore receive sensitive information, and it in turn may then disseminate sensitive information through insecure notification channels if so configured. Example configuration: sentry: environment: \"production\" dsn: \"...\"","breadcrumbs":"Configuration » Configuration Manual » sentry","id":"456","title":"sentry"},"457":{"body":"Flags to enable Prometheus metrics which are not suitable to be enabled by default, either for performance reasons or limited use. Currently the only option is known_servers, which publishes synapse_federation_known_servers, a gauge of the number of servers this homeserver knows about, including itself. May cause performance problems on large homeservers. Example configuration: metrics_flags: known_servers: true","breadcrumbs":"Configuration » Configuration Manual » metrics_flags","id":"457","title":"metrics_flags"},"458":{"body":"Whether or not to report homeserver usage statistics. This is originally set when generating the config. Set this option to true or false to change the current behavior. See Reporting Homeserver Usage Statistics for information on what data is reported. Statistics will be reported 5 minutes after Synapse starts, and then every 3 hours after that. Example configuration: report_stats: true","breadcrumbs":"Configuration » Configuration Manual » report_stats","id":"458","title":"report_stats"},"459":{"body":"The endpoint to report homeserver usage statistics to. Defaults to https://matrix.org/report-usage-stats/push Example configuration: report_stats_endpoint: https://example.com/report-usage-stats/push","breadcrumbs":"Configuration » Configuration Manual » report_stats_endpoint","id":"459","title":"report_stats_endpoint"},"46":{"body":"This document explains how to enable VoIP relaying on your homeserver with TURN. The synapse Matrix homeserver supports integration with TURN server via the TURN server REST API . This allows the homeserver to generate credentials that are valid for use on the TURN server through the use of a secret shared between the homeserver and the TURN server. This documentation provides two TURN server configuration examples: coturn eturnal","breadcrumbs":"Configuring a Turn Server » Overview","id":"46","title":"Overview"},"460":{"body":"Config settings related to the client/server API","breadcrumbs":"Configuration » Configuration Manual » API Configuration","id":"460","title":"API Configuration"},"461":{"body":"This setting controls the state that is shared with users upon receiving an invite to a room, or in reply to a knock on a room. By default, the following state events are shared with users: m.room.join_rules m.room.canonical_alias m.room.avatar m.room.encryption m.room.name m.room.create m.room.topic To change the default behavior, use the following sub-options: disable_default_event_types: boolean. Set to true to disable the above defaults. If this is enabled, only the event types listed in additional_event_types are shared. Defaults to false. additional_event_types: A list of additional state events to include in the events to be shared. By default, this list is empty (so only the default event types are shared). Each entry in this list should be either a single string or a list of two strings. A standalone string t represents all events with type t (i.e. with no restrictions on state keys). A pair of strings [t, s] represents a single event with type t and state key s. The same type can appear in two entries with different state keys: in this situation, both state keys are included in prejoin state. Example configuration: room_prejoin_state: disable_default_event_types: false additional_event_types: # Share all events of type `org.example.custom.event.typeA` - org.example.custom.event.typeA # Share only events of type `org.example.custom.event.typeB` whose # state_key is \"foo\" - [\"org.example.custom.event.typeB\", \"foo\"] # Share only events of type `org.example.custom.event.typeC` whose # state_key is \"bar\" or \"baz\" - [\"org.example.custom.event.typeC\", \"bar\"] - [\"org.example.custom.event.typeC\", \"baz\"] Changed in Synapse 1.74: admins can filter the events in prejoin state based on their state key.","breadcrumbs":"Configuration » Configuration Manual » room_prejoin_state","id":"461","title":"room_prejoin_state"},"462":{"body":"We record the IP address of clients used to access the API for various reasons, including displaying it to the user in the \"Where you're signed in\" dialog. By default, when puppeting another user via the admin API, the client IP address is recorded against the user who created the access token (ie, the admin user), and not the puppeted user. Set this option to true to also record the IP address against the puppeted user. (This also means that the puppeted user will count as an \"active\" user for the purpose of monthly active user tracking - see limit_usage_by_mau etc above.) Example configuration: track_puppeted_user_ips: true","breadcrumbs":"Configuration » Configuration Manual » track_puppeted_user_ips","id":"462","title":"track_puppeted_user_ips"},"463":{"body":"A list of application service config files to use. Example configuration: app_service_config_files: - app_service_1.yaml - app_service_2.yaml","breadcrumbs":"Configuration » Configuration Manual » app_service_config_files","id":"463","title":"app_service_config_files"},"464":{"body":"Defaults to false. Set to true to enable tracking of application service IP addresses. Implicitly enables MAU tracking for application service users. Example configuration: track_appservice_user_ips: true","breadcrumbs":"Configuration » Configuration Manual » track_appservice_user_ips","id":"464","title":"track_appservice_user_ips"},"465":{"body":"Whether to send the application service access tokens via the access_token query parameter per older versions of the Matrix specification. Defaults to false. Set to true to enable sending access tokens via a query parameter. **Enabling this option is considered insecure and is not recommended. ** Example configuration: use_appservice_legacy_authorization: true","breadcrumbs":"Configuration » Configuration Manual » use_appservice_legacy_authorization","id":"465","title":"use_appservice_legacy_authorization"},"466":{"body":"A secret which is used to sign access token for guest users, short-term login token used during SSO logins (OIDC or SAML2) and token used for unsubscribing from email notifications. If none is specified, the registration_shared_secret is used, if one is given; otherwise, a secret key is derived from the signing key. ⚠️ Warning – Replacing an existing macaroon_secret_key with a new one will lead to invalidation of access tokens for all guest users. It will also break unsubscribe links in emails sent before the change. An unlucky user might encounter a broken SSO login flow and would have to start again. Example configuration: macaroon_secret_key: ","breadcrumbs":"Configuration » Configuration Manual » macaroon_secret_key","id":"466","title":"macaroon_secret_key"},"467":{"body":"An alternative to macaroon_secret_key : allows the secret key to be specified in an external file. The file should be a plain text file, containing only the secret key. Synapse reads the secret key from the given file once at startup. Example configuration: macaroon_secret_key_path: /path/to/secrets/file Added in Synapse 1.121.0.","breadcrumbs":"Configuration » Configuration Manual » macaroon_secret_key_path","id":"467","title":"macaroon_secret_key_path"},"468":{"body":"A secret which is used to calculate HMACs for form values, to stop falsification of values. Must be specified for the User Consent forms to work. Replacing an existing form_secret with a new one might break the user consent page for an unlucky user and require them to reopen the page from a new link. Example configuration: form_secret: ","breadcrumbs":"Configuration » Configuration Manual » form_secret","id":"468","title":"form_secret"},"469":{"body":"An alternative to form_secret : allows the secret to be specified in an external file. The file should be a plain text file, containing only the secret. Synapse reads the secret from the given file once at startup. Example configuration: form_secret_path: /path/to/secrets/file Added in Synapse 1.126.0.","breadcrumbs":"Configuration » Configuration Manual » form_secret_path","id":"469","title":"form_secret_path"},"47":{"body":"For TURN relaying to work, the TURN service must be hosted on a server/endpoint with a public IP. Hosting TURN behind NAT requires port forwarding and for the NAT gateway to have a public IP. However, even with appropriate configuration, NAT is known to cause issues and to often not work. Afterwards, the homeserver needs some further configuration.","breadcrumbs":"Configuring a Turn Server » Requirements","id":"47","title":"Requirements"},"470":{"body":"Config options relating to signing keys","breadcrumbs":"Configuration » Configuration Manual » Signing Keys","id":"470","title":"Signing Keys"},"471":{"body":"Path to the signing key to sign events and federation requests with. New in Synapse 1.67 : If this file does not exist, Synapse will create a new signing key on startup and store it in this file. Example configuration: signing_key_path: \"CONFDIR/SERVERNAME.signing.key\"","breadcrumbs":"Configuration » Configuration Manual » signing_key_path","id":"471","title":"signing_key_path"},"472":{"body":"The keys that the server used to sign messages with but won't use to sign new messages. For each key, key should be the base64-encoded public key, and expired_tsshould be the time (in milliseconds since the unix epoch) that 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: old_signing_keys: \"ed25519:id\": { key: \"base64string\", expired_ts: 123456789123 }","breadcrumbs":"Configuration » Configuration Manual » old_signing_keys","id":"472","title":"old_signing_keys"},"473":{"body":"How long key response published by this server is valid for. Used to set the valid_until_ts in /key/v2 APIs. Determines how quickly servers will query to check which keys are still valid. Defaults to 1d. Example configuration: key_refresh_interval: 2d","breadcrumbs":"Configuration » Configuration Manual » key_refresh_interval","id":"473","title":"key_refresh_interval"},"474":{"body":"The trusted servers to download signing keys from. When we need to fetch a signing key, each server is tried in parallel. Normally, the connection to the key server is validated via TLS certificates. Additional security can be provided by configuring a verify key, which will make synapse check that the response is signed by that key. This setting supersedes an older setting named perspectives. The old format is still supported for backwards-compatibility, but it is deprecated. trusted_key_servers defaults to matrix.org, but using it will generate a warning on start-up. To suppress this warning, set suppress_key_server_warning to true. If the use of a trusted key server has to be deactivated, e.g. in a private federation or for privacy reasons, this can be realised by setting an empty array (trusted_key_servers: []). Then Synapse will request the keys directly from the server that owns the keys. If Synapse does not get keys directly from the server, the events of this server will be rejected. Options for each entry in the list include: server_name: the name of the server. Required. verify_keys: an optional map from key id to base64-encoded public key. If specified, we will check that the response is signed by at least one of the given keys. accept_keys_insecurely: a boolean. Normally, if verify_keys is unset, and federation_verify_certificates is not true, synapse will refuse to start, because this would allow anyone who can spoof DNS responses to masquerade as the trusted key server. If you know what you are doing and are sure that your network environment provides a secure connection to the key server, you can set this to true to override this behaviour. Example configuration #1: trusted_key_servers: - server_name: \"my_trusted_server.example.com\" verify_keys: \"ed25519:auto\": \"abcdefghijklmnopqrstuvwxyzabcdefghijklmopqr\" - server_name: \"my_other_trusted_server.example.com\" Example configuration #2: trusted_key_servers: - server_name: \"matrix.org\"","breadcrumbs":"Configuration » Configuration Manual » trusted_key_servers","id":"474","title":"trusted_key_servers"},"475":{"body":"Set the following to true to disable the warning that is emitted when the trusted_key_servers include 'matrix.org'. See above. Example configuration: suppress_key_server_warning: true","breadcrumbs":"Configuration » Configuration Manual » suppress_key_server_warning","id":"475","title":"suppress_key_server_warning"},"476":{"body":"The signing keys to use when acting as a trusted key server. If not specified defaults to the server signing key. Can contain multiple keys, one per line. Example configuration: key_server_signing_keys_path: \"key_server_signing_keys.key\"","breadcrumbs":"Configuration » Configuration Manual » key_server_signing_keys_path","id":"476","title":"key_server_signing_keys_path"},"477":{"body":"The following settings can be used to make Synapse use a single sign-on provider for authentication, instead of its internal password database. You will probably also want to set the following options to false to disable the regular login/registration flows: enable_registration password_config.enabled","breadcrumbs":"Configuration » Configuration Manual » Single sign-on integration","id":"477","title":"Single sign-on integration"},"478":{"body":"Enable SAML2 for registration and login. Uses pysaml2. To learn more about pysaml and to find a full list options for configuring pysaml, read the docs here . At least one of sp_config or config_path must be set in this section to enable SAML login. You can either put your entire pysaml config inline using the sp_config option, or you can specify a path to a psyaml config file with the sub-option config_path. This setting has the following sub-options: idp_name: A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms. idp_icon: An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format mxc:///. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the \"url\" from the source of the event.) idp_brand: An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the spec for possible options here. sp_config: the configuration for the pysaml2 Service Provider. See pysaml2 docs for format of config. Default values will be used for the entityid and service settings, so it is not normally necessary to specify them unless you need to override them. Here are a few useful sub-options for configuring pysaml: metadata: Point this to the IdP's metadata. You must provide either a local file via the local attribute or (preferably) a URL via the remote attribute. accepted_time_diff: 3: Allowed clock difference in seconds between the homeserver and IdP. Defaults to 0. service: By default, the user has to go to our login page first. If you'd like to allow IdP-initiated login, set allow_unsolicited to true under sp in the service section. config_path: specify a separate pysaml2 configuration file thusly: config_path: \"CONFDIR/sp_conf.py\" saml_session_lifetime: The lifetime of a SAML session. This defines how long a user has to complete the authentication process, if allow_unsolicited is unset. The default is 15 minutes. user_mapping_provider: Using this option, an external module can be provided as a custom solution to mapping attributes returned from a saml provider onto a matrix user. The user_mapping_provider has the following attributes: module: The custom module's class. config: Custom configuration values for the module. Use the values provided in the example if you are using the built-in user_mapping_provider, or provide your own config values for a custom class if you are using one. This section will be passed as a Python dictionary to the module's parse_config method. The built-in provider takes the following two options: mxid_source_attribute: The SAML attribute (after mapping via the attribute maps) to use to derive the Matrix ID from. It is 'uid' by default. Note: This used to be configured by the saml2_config.mxid_source_attribute option. If that is still defined, its value will be used instead. mxid_mapping: The mapping system to use for mapping the saml attribute onto a matrix ID. Options include: hexencode (which maps unpermitted characters to '=xx') and dotreplace (which replaces unpermitted characters with '.'). The default is hexencode. Note: This used to be configured by the saml2_config.mxid_mapping option. If that is still defined, its value will be used instead. grandfathered_mxid_source_attribute: In previous versions of synapse, the mapping from SAML attribute to MXID was always calculated dynamically rather than stored in a table. For backwards- compatibility, we will look for user_ids matching such a pattern before creating a new account. This setting controls the SAML attribute which will be used for this backwards-compatibility lookup. Typically it should be 'uid', but if the attribute maps are changed, it may be necessary to change it. The default is 'uid'. attribute_requirements: It is possible to configure Synapse to only allow logins if SAML attributes match particular values. The requirements can be listed under attribute_requirements as shown in the example. All of the listed attributes must match for the login to be permitted. Values can be specified in a one_of list to allow multiple values for an attribute. idp_entityid: If the metadata XML contains multiple IdP entities then the idp_entityid option must be set to the entity to redirect users to. Most deployments only have a single IdP entity and so should omit this option. Once SAML support is enabled, a metadata file will be exposed at https://:/_synapse/client/saml2/metadata.xml, which you may be able to use to configure your SAML IdP with. Alternatively, you can manually configure the IdP to use an ACS location of https://:/_synapse/client/saml2/authn_response. Example configuration: saml2_config: sp_config: metadata: local: [\"saml2/idp.xml\"] remote: - url: https://our_idp/metadata.xml accepted_time_diff: 3 service: sp: allow_unsolicited: true # The examples below are just used to generate our metadata xml, and you # may well not need them, depending on your setup. Alternatively you # may need a whole lot more detail - see the pysaml2 docs! description: [\"My awesome SP\", \"en\"] name: [\"Test SP\", \"en\"] ui_info: display_name: - lang: en text: \"Display Name is the descriptive name of your service.\" description: - lang: en text: \"Description should be a short paragraph explaining the purpose of the service.\" information_url: - lang: en text: \"https://example.com/terms-of-service\" privacy_statement_url: - lang: en text: \"https://example.com/privacy-policy\" keywords: - lang: en text: [\"Matrix\", \"Element\"] logo: - lang: en text: \"https://example.com/logo.svg\" width: \"200\" height: \"80\" organization: name: Example com display_name: - [\"Example co\", \"en\"] url: \"http://example.com\" contact_person: - given_name: Bob sur_name: \"the Sysadmin\" email_address: [\"admin@example.com\"] contact_type: technical saml_session_lifetime: 5m user_mapping_provider: # Below options are intended for the built-in provider, they should be # changed if using a custom module. config: mxid_source_attribute: displayName mxid_mapping: dotreplace grandfathered_mxid_source_attribute: upn attribute_requirements: - attribute: userGroup value: \"staff\" - attribute: department one_of: - \"sales\" - \"admins\" idp_entityid: 'https://our_idp/entityid'","breadcrumbs":"Configuration » Configuration Manual » saml2_config","id":"478","title":"saml2_config"},"479":{"body":"List of OpenID Connect (OIDC) / OAuth 2.0 identity providers, for registration and login. See here for information on how to configure these options. For backwards compatibility, it is also possible to configure a single OIDC provider via an oidc_config setting. This is now deprecated and admins are advised to migrate to the oidc_providers format. (When doing that migration, use oidc for the idp_id to ensure that existing users continue to be recognised.) Options for each entry include: idp_id: a unique identifier for this identity provider. Used internally by Synapse; should be a single word such as 'github'. Note that, if this is changed, users authenticating via that provider will no longer be recognised as the same user! (Use \"oidc\" here if you are migrating from an old oidc_config configuration.) idp_name: A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms. idp_icon: An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format mxc:///. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the \"url\" from the source of the event.) idp_brand: An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the spec for possible options here. discover: set to false to disable the use of the OIDC discovery mechanism to discover endpoints. Defaults to true. issuer: Required. The OIDC issuer. Used to validate tokens and (if discovery is enabled) to discover the provider's endpoints. client_id: Required. oauth2 client id to use. client_secret: oauth2 client secret to use. May be omitted if client_secret_jwt_key is given, or if client_auth_method is 'none'. Must be omitted if client_secret_path is specified. client_secret_path: path to the oauth2 client secret to use. With that it's not necessary to leak secrets into the config file itself. Mutually exclusive with client_secret. Can be omitted if client_secret_jwt_key is specified. Added in Synapse 1.91.0. client_secret_jwt_key: Alternative to client_secret: details of a key used to create a JSON Web Token to be used as an OAuth2 client secret. If given, must be a dictionary with the following properties: key: a pem-encoded signing key. Must be a suitable key for the algorithm specified. Required unless key_file is given. key_file: the path to file containing a pem-encoded signing key file. Required unless key is given. jwt_header: a dictionary giving properties to include in the JWT header. Must include the key alg, giving the algorithm used to sign the JWT, such as \"ES256\", using the JWA identifiers in RFC7518. jwt_payload: an optional dictionary giving properties to include in the JWT payload. Normally this should include an iss key. client_auth_method: auth method to use when exchanging the token. Valid values are client_secret_basic (default), client_secret_post and none. pkce_method: Whether to use proof key for code exchange when requesting and exchanging the token. Valid values are: auto, always, or never. Defaults to auto, which uses PKCE if supported during metadata discovery. Set to always to force enable PKCE or never to force disable PKCE. id_token_signing_alg_values_supported: List of the JWS signing algorithms (alg values) that are supported for signing the id_token. This is not required if discovery is disabled. We default to supporting RS256 in the downstream usage if no algorithms are configured here or in the discovery document. According to the spec, the algorithm \"RS256\" MUST be included. The absolute rigid approach would be to reject this provider as non-compliant if it's not included but we simply allow whatever and see what happens (you're the one that configured the value and cooperating with the identity provider). The alg value \"none\" MAY be supported but can only be used if the Authorization Endpoint does not include id_token in the response_type (ex. /authorize?response_type=code where none can apply, /authorize?response_type=code%20id_token where none can't apply) (such as when using the Authorization Code Flow). scopes: list of scopes to request. This should normally include the \"openid\" scope. Defaults to [\"openid\"]. authorization_endpoint: the oauth2 authorization endpoint. Required if provider discovery is disabled. token_endpoint: the oauth2 token endpoint. Required if provider discovery is disabled. userinfo_endpoint: the OIDC userinfo endpoint. Required if discovery is disabled and the 'openid' scope is not requested. jwks_uri: URI where to fetch the JWKS. Required if discovery is disabled and the 'openid' scope is used. skip_verification: set to 'true' to skip metadata verification. Use this if you are connecting to a provider that is not OpenID Connect compliant. Defaults to false. Avoid this in production. user_profile_method: Whether to fetch the user profile from the userinfo endpoint, or to rely on the data returned in the id_token from the token_endpoint. Valid values are: auto or userinfo_endpoint. Defaults to auto, which uses the userinfo endpoint if openid is not included in scopes. Set to userinfo_endpoint to always use the userinfo endpoint. redirect_uri: An optional string, that if set will override the redirect_uri parameter sent in the requests to the authorization and token endpoints. Useful if you want to redirect the client to another endpoint as part of the OIDC login. Be aware that the client must then call Synapse's OIDC callback URL (/_synapse/client/oidc/callback) manually afterwards. Must be a valid URL including scheme and path. additional_authorization_parameters: String to string dictionary that will be passed as additional parameters to the authorization grant URL. passthrough_authorization_parameters: List of parameters that will be passed through from the redirect endpoint to the authorization grant URL. allow_existing_users: set to true to allow a user logging in via OIDC to match a pre-existing account instead of failing. This could be used if switching from password logins to OIDC. Defaults to false. enable_registration: set to 'false' to disable automatic registration of new users. This allows the OIDC SSO flow to be limited to sign in only, rather than automatically registering users that have a valid SSO login but do not have a pre-registered account. Defaults to true. user_mapping_provider: Configuration for how attributes returned from a OIDC provider are mapped onto a matrix user. This setting has the following sub-properties: module: The class name of a custom mapping module. Default is synapse.handlers.oidc.JinjaOidcMappingProvider. See OpenID Mapping Providers for information on implementing a custom mapping provider. config: Configuration for the mapping provider module. This section will be passed as a Python dictionary to the user mapping provider module's parse_config method. For the default provider, the following settings are available: subject_template: Jinja2 template for a unique identifier for the user. Defaults to {{ user.sub }}, which OpenID Connect compliant providers should provide. This replaces and overrides subject_claim. subject_claim: name of the claim containing a unique identifier for the user. Defaults to 'sub', which OpenID Connect compliant providers should provide. Deprecated in Synapse v1.75.0. picture_template: Jinja2 template for an url for the user's profile picture. Defaults to {{ user.picture }}, which OpenID Connect compliant providers should provide and has to refer to a direct image file such as PNG, JPEG, or GIF image file. This replaces and overrides picture_claim. Currently only supported in monolithic (single-process) server configurations where the media repository runs within the Synapse process. picture_claim: name of the claim containing an url for the user's profile picture. Defaults to 'picture', which OpenID Connect compliant providers should provide and has to refer to a direct image file such as PNG, JPEG, or GIF image file. Currently only supported in monolithic (single-process) server configurations where the media repository runs within the Synapse process. Deprecated in Synapse v1.75.0. localpart_template: Jinja2 template for the localpart of the MXID. If this is not set, the user will be prompted to choose their own username (see the documentation for the sso_auth_account_details.html template). This template can use the localpart_from_email filter. confirm_localpart: Whether to prompt the user to validate (or change) the generated localpart (see the documentation for the 'sso_auth_account_details.html' template), instead of registering the account right away. display_name_template: Jinja2 template for the display name to set on first login. If unset, no displayname will be set. email_template: Jinja2 template for the email address of the user. If unset, no email address will be added to the account. extra_attributes: a map of Jinja2 templates for extra attributes to send back to the client during login. Note that these are non-standard and clients will ignore them without modifications. When rendering, the Jinja2 templates are given a 'user' variable, which is set to the claims returned by the UserInfo Endpoint and/or in the ID Token. backchannel_logout_enabled: set to true to process OIDC Back-Channel Logout notifications. Those notifications are expected to be received on /_synapse/client/oidc/backchannel_logout. Defaults to false. backchannel_logout_ignore_sub: by default, the OIDC Back-Channel Logout feature checks that the sub claim matches the subject claim received during login. This check can be disabled by setting this to true. Defaults to false. You might want to disable this if the subject_claim returned by the mapping provider is not sub. It is possible to configure Synapse to only allow logins if certain attributes match particular values in the OIDC userinfo. The requirements can be listed under attribute_requirements as shown here: attribute_requirements: - attribute: family_name one_of: [\"Stephensson\", \"Smith\"] - attribute: groups value: \"admin\" # If `value` or `one_of` are not specified, the attribute only needs # to exist, regardless of value. - attribute: picture attribute is a required field, while value and one_of are optional. All of the listed attributes must match for the login to be permitted. Additional attributes can be added to userinfo by expanding the scopes section of the OIDC config to retrieve additional information from the OIDC provider. If the OIDC claim is a list, then the attribute must match any value in the list. Otherwise, it must exactly match the value of the claim. Using the example above, the family_name claim MUST be either \"Stephensson\" or \"Smith\", but the groups claim MUST contain \"admin\". Example configuration: oidc_providers: # Generic example # - idp_id: my_idp idp_name: \"My OpenID provider\" idp_icon: \"mxc://example.com/mediaid\" discover: false issuer: \"https://accounts.example.com/\" client_id: \"provided-by-your-issuer\" client_secret: \"provided-by-your-issuer\" client_auth_method: client_secret_post scopes: [\"openid\", \"profile\"] authorization_endpoint: \"https://accounts.example.com/oauth2/auth\" token_endpoint: \"https://accounts.example.com/oauth2/token\" userinfo_endpoint: \"https://accounts.example.com/userinfo\" jwks_uri: \"https://accounts.example.com/.well-known/jwks.json\" additional_authorization_parameters: acr_values: 2fa passthrough_authorization_parameters: [\"login_hint\"] skip_verification: true enable_registration: true user_mapping_provider: config: subject_claim: \"id\" localpart_template: \"{{ user.login }}\" display_name_template: \"{{ user.name }}\" email_template: \"{{ user.email }}\" attribute_requirements: - attribute: userGroup value: \"synapseUsers\"","breadcrumbs":"Configuration » Configuration Manual » oidc_providers","id":"479","title":"oidc_providers"},"48":{"body":"Your homeserver configuration file needs the following extra keys: turn_uris turn_shared_secret turn_user_lifetime turn_allow_guests As an example, here is the relevant section of the config file for matrix.org. The turn_uris are appropriate for TURN servers listening on the default ports, with no TLS. turn_uris: [ \"turn:turn.matrix.org?transport=udp\", \"turn:turn.matrix.org?transport=tcp\" ]\nturn_shared_secret: \"n0t4ctuAllymatr1Xd0TorgSshar3d5ecret4obvIousreAsons\"\nturn_user_lifetime: 86400000\nturn_allow_guests: true After updating the homeserver configuration, you must restart synapse: If you use synctl: # Depending on how Synapse is installed, synctl may already be on\n# your PATH. If not, you may need to activate a virtual environment.\nsynctl restart If you use systemd: systemctl restart matrix-synapse.service ... and then reload any clients (or wait an hour for them to refresh their settings).","breadcrumbs":"Configuring a Turn Server » Synapse setup","id":"48","title":"Synapse setup"},"480":{"body":"Enable Central Authentication Service (CAS) for registration and login. Has the following sub-options: enabled: Set this to true to enable authorization against a CAS server. Defaults to false. idp_name: A user-facing name for this identity provider, which is used to offer the user a choice of login mechanisms. idp_icon: An optional icon for this identity provider, which is presented by clients and Synapse's own IdP picker page. If given, must be an MXC URI of the format mxc:///. (An easy way to obtain such an MXC URI is to upload an image to an (unencrypted) room and then copy the \"url\" from the source of the event.) idp_brand: An optional brand for this identity provider, allowing clients to style the login flow according to the identity provider in question. See the spec for possible options here. server_url: The URL of the CAS authorization endpoint. protocol_version: The CAS protocol version, defaults to none (version 3 is required if you want to use \"required_attributes\"). displayname_attribute: The attribute of the CAS response to use as the display name. If no name is given here, no displayname will be set. required_attributes: It is possible to configure Synapse to only allow logins if CAS attributes match particular values. All of the keys given below must exist and the values must match the given value. Alternately if the given value is None then any value is allowed (the attribute just must exist). All of the listed attributes must match for the login to be permitted. enable_registration: set to 'false' to disable automatic registration of new users. This allows the CAS SSO flow to be limited to sign in only, rather than automatically registering users that have a valid SSO login but do not have a pre-registered account. Defaults to true. allow_numeric_ids: set to 'true' allow numeric user IDs (default false). This allows CAS SSO flow to provide user IDs composed of numbers only. These identifiers will be prefixed by the letter \"u\" by default. The prefix can be configured using the \"numeric_ids_prefix\" option. Be careful to choose the prefix correctly to avoid any possible conflicts (e.g. user 1234 becomes u1234 when a user u1234 already exists). numeric_ids_prefix: the prefix you wish to add in front of a numeric user ID when the \"allow_numeric_ids\" option is set to \"true\". By default, the prefix is the letter \"u\" and only alphanumeric characters are allowed. Added in Synapse 1.93.0. Example configuration: cas_config: enabled: true server_url: \"https://cas-server.com\" protocol_version: 3 displayname_attribute: name required_attributes: userGroup: \"staff\" department: None enable_registration: true allow_numeric_ids: true numeric_ids_prefix: \"numericuser\"","breadcrumbs":"Configuration » Configuration Manual » cas_config","id":"480","title":"cas_config"},"481":{"body":"Additional settings to use with single-sign on systems such as OpenID Connect, SAML2 and CAS. Server admins can configure custom templates for pages related to SSO. See here for more information. Options include: client_whitelist: A list of client URLs which are whitelisted so that the user does not have to confirm giving access to their account to the URL. Any client whose URL starts with an entry in the following list will not be subject to an additional confirmation step after the SSO login is completed. WARNING: An entry such as \"https://my.client\" is insecure, because it will also match \"https://my.client.evil.site\", exposing your users to phishing attacks from evil.site. To avoid this, include a slash after the hostname: \"https://my.client/\". The login fallback page (used by clients that don't natively support the required login flows) is whitelisted in addition to any URLs in this list. By default, this list contains only the login fallback page. update_profile_information: Use this setting to keep a user's profile fields in sync with information from the identity provider. Currently only syncing the displayname is supported. Fields are checked on every SSO login, and are updated if necessary. Note that enabling this option will override user profile information, regardless of whether users have opted-out of syncing that information when first signing in. Defaults to false. Example configuration: sso: client_whitelist: - https://riot.im/develop - https://my.custom.client/ update_profile_information: true","breadcrumbs":"Configuration » Configuration Manual » sso","id":"481","title":"sso"},"482":{"body":"JSON web token integration. The following settings can be used to make Synapse JSON web tokens for authentication, instead of its internal password database. Each JSON Web Token needs to contain a \"sub\" (subject) claim, which is used as the localpart of the mxid. Additionally, the expiration time (\"exp\"), not before time (\"nbf\"), and issued at (\"iat\") claims are validated if present. Note that this is a non-standard login type and client support is expected to be non-existent. See here for more. Additional sub-options for this setting include: enabled: Set to true to enable authorization using JSON web tokens. Defaults to false. secret: This is either the private shared secret or the public key used to decode the contents of the JSON web token. Required if enabled is set to true. algorithm: The algorithm used to sign (or HMAC) the JSON web token. Supported algorithms are listed here (section JWS) . Required if enabled is set to true. subject_claim: Name of the claim containing a unique identifier for the user. Optional, defaults to sub. display_name_claim: Name of the claim containing the display name for the user. Optional. If provided, the display name will be set to the value of this claim upon first login. issuer: The issuer to validate the \"iss\" claim against. Optional. If provided the \"iss\" claim will be required and validated for all JSON web tokens. audiences: A list of audiences to validate the \"aud\" claim against. Optional. If provided the \"aud\" claim will be required and validated for all JSON web tokens. Note that if the \"aud\" claim is included in a JSON web token then validation will fail without configuring audiences. Example configuration: jwt_config: enabled: true secret: \"provided-by-your-issuer\" algorithm: \"provided-by-your-issuer\" subject_claim: \"name_of_claim\" display_name_claim: \"name_of_claim\" issuer: \"provided-by-your-issuer\" audiences: - \"provided-by-your-issuer\"","breadcrumbs":"Configuration » Configuration Manual » jwt_config","id":"482","title":"jwt_config"},"483":{"body":"Use this setting to enable password-based logins. This setting has the following sub-options: enabled: Defaults to true. Set to false to disable password authentication. Set to only_for_reauth to allow users with existing passwords to use them to reauthenticate (not log in), whilst preventing new users from setting passwords. localdb_enabled: Set to false to disable authentication against the local password database. This is ignored if enabled is false, and is only useful if you have other password_providers. Defaults to true. pepper: Set the value here to a secret random string for extra security. DO NOT CHANGE THIS AFTER INITIAL SETUP! policy: Define and enforce a password policy, such as minimum lengths for passwords, etc. Each parameter is optional. This is an implementation of MSC2000. Parameters are as follows: enabled: Defaults to false. Set to true to enable. minimum_length: Minimum accepted length for a password. Defaults to 0. require_digit: Whether a password must contain at least one digit. Defaults to false. require_symbol: Whether a password must contain at least one symbol. A symbol is any character that's not a number or a letter. Defaults to false. require_lowercase: Whether a password must contain at least one lowercase letter. Defaults to false. require_uppercase: Whether a password must contain at least one uppercase letter. Defaults to false. Example configuration: password_config: enabled: false localdb_enabled: false pepper: \"EVEN_MORE_SECRET\" policy: enabled: true minimum_length: 15 require_digit: true require_symbol: true require_lowercase: true require_uppercase: true","breadcrumbs":"Configuration » Configuration Manual » password_config","id":"483","title":"password_config"},"484":{"body":"Configuration settings related to push notifications","breadcrumbs":"Configuration » Configuration Manual » Push","id":"484","title":"Push"},"485":{"body":"This setting defines options for push notifications. This option has a number of sub-options. They are as follows: enabled: Enables or disables push notification calculation. Note, disabling this will also stop unread counts being calculated for rooms. This mode of operation is intended for homeservers which may only have bots or appservice users connected, or are otherwise not interested in push/unread counters. This is enabled by default. include_content: Clients requesting push notifications can either have the body of the message sent in the notification poke along with other details like the sender, or just the event ID and room ID (event_id_only). If clients choose to have the body sent, this option controls whether the notification request includes the content of the event (other details like the sender are still included). If event_id_only is enabled, it has no effect. For modern android devices the notification content will still appear because it is loaded by the app. iPhone, however will send a notification saying only that a message arrived and who it came from. Defaults to true. Set to false to only include the event ID and room ID in push notification payloads. group_unread_count_by_room: false: When a push notification is received, an unread count is also sent. This number can either be calculated as the number of unread messages for the user, or the number of rooms the user has unread messages in. Defaults to true, meaning push clients will see the number of rooms with unread messages in them. Set to false to instead send the number of unread messages. jitter_delay: Delays push notifications by a random amount up to the given duration. Useful for mitigating timing attacks. Optional, defaults to no delay. Added in Synapse 1.84.0. Example configuration: push: enabled: true include_content: false group_unread_count_by_room: false jitter_delay: \"10s\"","breadcrumbs":"Configuration » Configuration Manual » push","id":"485","title":"push"},"486":{"body":"Config options relating to rooms.","breadcrumbs":"Configuration » Configuration Manual » Rooms","id":"486","title":"Rooms"},"487":{"body":"Controls whether locally-created rooms should be end-to-end encrypted by default. Possible options are \"all\", \"invite\", and \"off\". They are defined as: \"all\": any locally-created room \"invite\": any room created with the private_chat or trusted_private_chat room creation presets \"off\": this option will take no effect The default value is \"off\". Note that this option will only affect rooms created after it is set. It will also not affect rooms created by other servers. Example configuration: encryption_enabled_by_default_for_room_type: invite","breadcrumbs":"Configuration » Configuration Manual » encryption_enabled_by_default_for_room_type","id":"487","title":"encryption_enabled_by_default_for_room_type"},"488":{"body":"This setting defines options related to the user directory. This option has the following sub-options: enabled: Defines whether users can search the user directory. If false then empty responses are returned to all queries. Defaults to true. search_all_users: Defines whether to search all users visible to your homeserver at the time the search is performed. If set to true, will return all users known to the homeserver matching the search query. If false, search results will only contain users visible in public rooms and users sharing a room with the requester. Defaults to false. NB. If you set this to true, and the last time the user_directory search indexes were (re)built was before Synapse 1.44, you'll have to rebuild the indexes in order to search through all known users. These indexes are built the first time Synapse starts; admins can manually trigger a rebuild via the API following the instructions for running background updates , set to true to return search results containing all known users, even if that user does not share a room with the requester. prefer_local_users: Defines whether to prefer local users in search query results. If set to true, local users are more likely to appear above remote users when searching the user directory. Defaults to false. exclude_remote_users: If set to true, the search will only return local users. Defaults to false. show_locked_users: Defines whether to show locked users in search query results. Defaults to false. Example configuration: user_directory: enabled: false search_all_users: true prefer_local_users: true exclude_remote_users: false show_locked_users: true","breadcrumbs":"Configuration » Configuration Manual » user_directory","id":"488","title":"user_directory"},"489":{"body":"For detailed instructions on user consent configuration, see here . Parts of this section are required if enabling the consent resource under listeners , in particular template_dir and version. template_dir: gives the location of the templates for the HTML forms. This directory should contain one subdirectory per language (eg, en, fr), and each language directory should contain the policy document (named as .html) and a success page (success.html). version: specifies the 'current' version of the policy document. It defines the version to be served by the consent resource if there is no 'v' parameter. server_notice_content: if enabled, will send a user a \"Server Notice\" asking them to consent to the privacy policy. The server_notices section must also be configured for this to work. Notices will not be sent to guest users unless send_server_notice_to_guests is set to true. block_events_error, if set, will block any attempts to send events until the user consents to the privacy policy. The value of the setting is used as the text of the error. require_at_registration, if enabled, will add a step to the registration process, similar to how captcha works. Users will be required to accept the policy before their account is created. policy_name is the display name of the policy users will see when registering for an account. Has no effect unless require_at_registration is enabled. Defaults to \"Privacy Policy\". Example configuration: user_consent: template_dir: res/templates/privacy version: 1.0 server_notice_content: msgtype: m.text body: >- To continue using this homeserver you must review and agree to the terms and conditions at %(consent_uri)s send_server_notice_to_guests: true block_events_error: >- To continue using this homeserver you must review and agree to the terms and conditions at %(consent_uri)s require_at_registration: false policy_name: Privacy Policy","breadcrumbs":"Configuration » Configuration Manual » user_consent","id":"489","title":"user_consent"},"49":{"body":"The normal symptoms of a misconfigured TURN server are that calls between devices on different networks ring, but get stuck at \"call connecting\". Unfortunately, troubleshooting this can be tricky. Here are a few things to try: Check that you have opened your firewall to allow TCP and UDP traffic to the TURN ports (normally 3478 and 5349). Check that you have opened your firewall to allow UDP traffic to the UDP relay ports (49152-65535 by default). Try disabling TLS/DTLS listeners and enable only its (unencrypted) TCP/UDP listeners. (This will only leave signaling traffic unencrypted; voice & video WebRTC traffic is always encrypted.) Some WebRTC implementations (notably, that of Google Chrome) appear to get confused by TURN servers which are reachable over IPv6 (this appears to be an unexpected side-effect of its handling of multiple IP addresses as defined by draft-ietf-rtcweb-ip-handling ). Try removing any AAAA records for your TURN server, so that it is only reachable over IPv4. If your TURN server is behind NAT: double-check that your NAT gateway is correctly forwarding all TURN ports (normally 3478 & 5349 for TCP & UDP TURN traffic, and 49152-65535 for the UDP relay) to the NAT-internal address of your TURN server. If advertising both IPv4 and IPv6 external addresses via the external-ip option, ensure that the NAT is forwarding both IPv4 and IPv6 traffic to the IPv4 and IPv6 internal addresses of your TURN server. When in doubt, remove AAAA records for your TURN server and specify only an IPv4 address as your external-ip. ensure that your TURN server uses the NAT gateway as its default route. Enable more verbose logging, in coturn via the verbose setting: verbose or with eturnal with the shell command eturnalctl loglevel debug or in the configuration file (the service needs to reload for it to become effective): ## Logging configuration: log_level: debug ... and then see if there are any clues in its logs. If you are using a browser-based client under Chrome, check chrome://webrtc-internals/ for insights into the internals of the negotiation. On Firefox, check the \"Connection Log\" on about:webrtc. (Understanding the output is beyond the scope of this document!) You can test your Matrix homeserver TURN setup with https://test.voip.librepush.net/ . Note that this test is not fully reliable yet, so don't be discouraged if the test fails. Here is the github repo of the source of the tester, where you can file bug reports. There is a WebRTC test tool at https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ . To use it, you will need a username/password for your TURN server. You can either: look for the GET /_matrix/client/r0/voip/turnServer request made by a matrix client to your homeserver in your browser's network inspector. In the response you should see username and password. Or: Use the following shell commands for coturn: secret=staticAuthSecretHere u=$((`date +%s` + 3600)):test\np=$(echo -n $u | openssl dgst -hmac $secret -sha1 -binary | base64)\necho -e \"username: $u\\npassword: $p\" or for eturnal eturnalctl credentials Or ( coturn only ): Temporarily configure coturn to accept a static username/password. To do this, comment out use-auth-secret and static-auth-secret and add the following: lt-cred-mech\nuser=username:password Note : these settings will not take effect unless use-auth-secret and static-auth-secret are disabled. Restart coturn after changing the configuration file. Remember to restore the original settings to go back to testing with Matrix clients! If the TURN server is working correctly, you should see at least one relay entry in the results.","breadcrumbs":"Configuring a Turn Server » Troubleshooting","id":"49","title":"Troubleshooting"},"490":{"body":"Settings for local room and user statistics collection. See here for more. enabled: Set to false to disable room and user statistics. Note that doing so may cause certain features (such as the room directory) not to work correctly. Defaults to true. Example configuration: stats: enabled: false","breadcrumbs":"Configuration » Configuration Manual » stats","id":"490","title":"stats"},"491":{"body":"Use this setting to enable a room which can be used to send notices from the server to users. It is a special room which users cannot leave; notices in the room come from a special \"notices\" user id. If you use this setting, you must define the system_mxid_localpart sub-setting, which defines the id of the user which will be used to send the notices. Sub-options for this setting include: system_mxid_display_name: set the display name of the \"notices\" user system_mxid_avatar_url: set the avatar for the \"notices\" user room_name: set the room name of the server notices room room_avatar_url: optional string. The room avatar to use for server notice rooms. If set to the empty string \"\", notice rooms will not be given an avatar. Defaults to the empty string. Added in Synapse 1.99.0. room_topic: optional string. The topic to use for server notice rooms. If set to the empty string \"\", notice rooms will not be given a topic. Defaults to the empty string. Added in Synapse 1.99.0. auto_join: boolean. If true, the user will be automatically joined to the room instead of being invited. Defaults to false. Added in Synapse 1.98.0. Note that the name, topic and avatar of existing server notice rooms will only be updated when a new notice event is sent. Example configuration: server_notices: system_mxid_localpart: notices system_mxid_display_name: \"Server Notices\" system_mxid_avatar_url: \"mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ\" room_name: \"Server Notices\" room_avatar_url: \"mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ\" room_topic: \"Room used by your server admin to notice you of important information\" auto_join: true","breadcrumbs":"Configuration » Configuration Manual » server_notices","id":"491","title":"server_notices"},"492":{"body":"Set to false to disable searching the public room list. When disabled blocks searching local and remote room lists for local and remote users by always returning an empty list for all queries. Defaults to true. Example configuration: enable_room_list_search: false","breadcrumbs":"Configuration » Configuration Manual » enable_room_list_search","id":"492","title":"enable_room_list_search"},"493":{"body":"The alias_creation_rules option allows server admins to prevent unwanted alias creation on this server. This setting is an optional list of 0 or more rules. By default, no list is provided, meaning that all alias creations are permitted. Otherwise, requests to create aliases are matched against each rule in order. The first rule that matches decides if the request is allowed or denied. If no rule matches, the request is denied. In particular, this means that configuring an empty list of rules will deny every alias creation request. Each rule is a YAML object containing four fields, each of which is an optional string: user_id: a glob pattern that matches against the creator of the alias. alias: a glob pattern that matches against the alias being created. room_id: a glob pattern that matches against the room ID the alias is being pointed at. action: either allow or deny. What to do with the request if the rule matches. Defaults to allow. Each of the glob patterns is optional, defaulting to * (\"match anything\"). Note that the patterns match against fully qualified IDs, e.g. against @alice:example.com, #room:example.com and !abcdefghijk:example.com instead of alice, room and abcedgghijk. Example configuration: # No rule list specified. All alias creations are allowed.\n# This is the default behaviour.\nalias_creation_rules: # A list of one rule which allows everything.\n# This has the same effect as the previous example.\nalias_creation_rules: - \"action\": \"allow\" # An empty list of rules. All alias creations are denied.\nalias_creation_rules: [] # A list of one rule which denies everything.\n# This has the same effect as the previous example.\nalias_creation_rules: - \"action\": \"deny\" # Prevent a specific user from creating aliases.\n# Allow other users to create any alias\nalias_creation_rules: - user_id: \"@bad_user:example.com\" action: deny - action: allow # Prevent aliases being created which point to a specific room.\nalias_creation_rules: - room_id: \"!forbiddenRoom:example.com\" action: deny - action: allow","breadcrumbs":"Configuration » Configuration Manual » alias_creation_rules","id":"493","title":"alias_creation_rules"},"494":{"body":"The room_list_publication_rules option allows server admins to prevent unwanted entries from being published in the public room list. The format of this option is the same as that for alias_creation_rules : an optional list of 0 or more rules. By default, no list is provided, meaning that no one may publish to the room list (except server admins). Otherwise, requests to publish a room are matched against each rule in order. The first rule that matches decides if the request is allowed or denied. If no rule matches, the request is denied. In particular, this means that configuring an empty list of rules will deny every alias creation request. Requests to create a public (public as in published to the room directory) room which violates the configured rules will result in the room being created but not published to the room directory. Each rule is a YAML object containing four fields, each of which is an optional string: user_id: a glob pattern that matches against the user publishing the room. alias: a glob pattern that matches against one of published room's aliases. If the room has no aliases, the alias match fails unless alias is unspecified or *. If the room has exactly one alias, the alias match succeeds if the alias pattern matches that alias. If the room has two or more aliases, the alias match succeeds if the pattern matches at least one of the aliases. room_id: a glob pattern that matches against the room ID of the room being published. action: either allow or deny. What to do with the request if the rule matches. Defaults to allow. Each of the glob patterns is optional, defaulting to * (\"match anything\"). Note that the patterns match against fully qualified IDs, e.g. against @alice:example.com, #room:example.com and !abcdefghijk:example.com instead of alice, room and abcedgghijk. Changed in Synapse 1.126.0: The default was changed to deny publishing to the room list by default Example configuration: # No rule list specified. No one may publish any room to the public list, except server admins.\n# This is the default behaviour.\nroom_list_publication_rules: # A list of one rule which denies everything.\n# This has the same effect as the previous example.\nroom_list_publication_rules: - \"action\": \"deny\" # An empty list of rules.\n# This has the same effect as the previous example.\nroom_list_publication_rules: [] # A list of one rule which allows everything.\n# This was the default behaviour pre v1.126.0.\nroom_list_publication_rules: - \"action\": \"allow\" # Prevent a specific user from publishing rooms.\n# Allow other users to publish anything.\nroom_list_publication_rules: - user_id: \"@bad_user:example.com\" action: deny - action: allow # Prevent publication of a specific room.\nroom_list_publication_rules: - room_id: \"!forbiddenRoom:example.com\" action: deny - action: allow # Prevent publication of rooms with at least one alias containing the word \"potato\".\nroom_list_publication_rules: - alias: \"#*potato*:example.com\" action: deny - action: allow","breadcrumbs":"Configuration » Configuration Manual » room_list_publication_rules","id":"494","title":"room_list_publication_rules"},"495":{"body":"The default_power_level_content_override option controls the default power levels for rooms. Useful if you know that your users need special permissions in rooms that they create (e.g. to send particular types of state events without needing an elevated power level). This takes the same shape as the power_level_content_override parameter in the /createRoom API, but is applied before that parameter. Note that each key provided inside a preset (for example events in the example below) will overwrite all existing defaults inside that key. So in the example below, newly-created private_chat rooms will have no rules for any event types except com.example.foo. Example configuration: default_power_level_content_override: private_chat: { \"events\": { \"com.example.foo\" : 0 } } trusted_private_chat: null public_chat: null The default power levels for each preset are: \"m.room.name\": 50\n\"m.room.power_levels\": 100\n\"m.room.history_visibility\": 100\n\"m.room.canonical_alias\": 50\n\"m.room.avatar\": 50\n\"m.room.tombstone\": 100\n\"m.room.server_acl\": 100\n\"m.room.encryption\": 100 So a complete example where the default power-levels for a preset are maintained but the power level for a new key is set is: default_power_level_content_override: private_chat: events: \"com.example.foo\": 0 \"m.room.name\": 50 \"m.room.power_levels\": 100 \"m.room.history_visibility\": 100 \"m.room.canonical_alias\": 50 \"m.room.avatar\": 50 \"m.room.tombstone\": 100 \"m.room.server_acl\": 100 \"m.room.encryption\": 100 trusted_private_chat: null public_chat: null","breadcrumbs":"Configuration » Configuration Manual » default_power_level_content_override","id":"495","title":"default_power_level_content_override"},"496":{"body":"Set to true to automatically forget rooms for users when they leave them, either normally or via a kick or ban. Defaults to false. Example configuration: forget_rooms_on_leave: false","breadcrumbs":"Configuration » Configuration Manual » forget_rooms_on_leave","id":"496","title":"forget_rooms_on_leave"},"497":{"body":"A list of rooms to exclude from sync responses. This is useful for server administrators wishing to group users into a room without these users being able to see it from their client. By default, no room is excluded. Example configuration: exclude_rooms_from_sync: - \"!foo:example.com\"","breadcrumbs":"Configuration » Configuration Manual » exclude_rooms_from_sync","id":"497","title":"exclude_rooms_from_sync"},"498":{"body":"Configuration options related to Opentracing support.","breadcrumbs":"Configuration » Configuration Manual » Opentracing","id":"498","title":"Opentracing"},"499":{"body":"These settings enable and configure opentracing, which implements distributed tracing. This allows you to observe the causal chains of events across servers including requests, key lookups etc., across any server running synapse or any other services which support opentracing (specifically those implemented with Jaeger). Sub-options include: enabled: whether tracing is enabled. Set to true to enable. Disabled by default. homeserver_whitelist: The list of homeservers we wish to send and receive span contexts and span baggage. See here for more. This is a list of regexes which are matched against the server_name of the homeserver. By default, it is empty, so no servers are matched. force_tracing_for_users: # A list of the matrix IDs of users whose requests will always be traced, even if the tracing system would otherwise drop the traces due to probabilistic sampling. By default, the list is empty. jaeger_config: Jaeger can be configured to sample traces at different rates. All configuration options provided by Jaeger can be set here. Jaeger's configuration is mostly related to trace sampling which is documented here . Example configuration: opentracing: enabled: true homeserver_whitelist: - \".*\" force_tracing_for_users: - \"@user1:server_name\" - \"@user2:server_name\" jaeger_config: sampler: type: const param: 1 logging: false","breadcrumbs":"Configuration » Configuration Manual » opentracing","id":"499","title":"opentracing"},"5":{"body":"It is important to choose the name for your server before you install Synapse, because it cannot be changed later. The server name determines the \"domain\" part of user-ids for users on your server: these will all be of the format @user:my.domain.name. It also determines how other matrix servers will reach yours for federation. For a test configuration, set this to the hostname of your server. For a more production-ready setup, you will probably want to specify your domain (example.com) rather than a matrix-specific hostname here (in the same way that your email address is probably user@example.com rather than user@email.example.com) - but doing so may require more advanced setup: see Setting up Federation .","breadcrumbs":"Installation » Choosing your server name","id":"5","title":"Choosing your server name"},"50":{"body":"The following sections describe how to install coturn (which implements the TURN REST API).","breadcrumbs":"Configuring a Turn Server » coturn TURN server » coturn TURN server","id":"50","title":"coturn TURN server"},"500":{"body":"Configuration options related to workers which belong in the main config file (usually called homeserver.yaml). A Synapse deployment can scale horizontally by running multiple Synapse processes called workers . Incoming requests are distributed between workers to handle higher loads. Some workers are privileged and can accept requests from other workers. As a result, the worker configuration is divided into two parts. The first part (in this section of the manual) defines which shardable tasks are delegated to privileged workers. This allows unprivileged workers to make requests to a privileged worker to act on their behalf. The second part controls the behaviour of individual workers in isolation. For guidance on setting up workers, see the worker documentation .","breadcrumbs":"Configuration » Configuration Manual » Coordinating workers","id":"500","title":"Coordinating workers"},"501":{"body":"A shared secret used by the replication APIs on the main process to authenticate HTTP requests from workers. The default, this value is omitted (equivalently null), which means that traffic between the workers and the main process is not authenticated. Replacing an existing worker_replication_secret with a new one will break communication with all workers that have not yet updated their secret. Example configuration: worker_replication_secret: \"secret_secret\"","breadcrumbs":"Configuration » Configuration Manual » worker_replication_secret","id":"501","title":"worker_replication_secret"},"502":{"body":"An alternative to worker_replication_secret : allows the secret to be specified in an external file. The file should be a plain text file, containing only the secret. Synapse reads the secret from the given file once at startup. Example configuration: worker_replication_secret_path: /path/to/secrets/file Added in Synapse 1.126.0.","breadcrumbs":"Configuration » Configuration Manual » worker_replication_secret_path","id":"502","title":"worker_replication_secret_path"},"503":{"body":"Unnecessary to set if using pusher_instances with generic_workers . Controls sending of push notifications on the main process. Set to false if using a pusher worker . Defaults to true. Example configuration: start_pushers: false","breadcrumbs":"Configuration » Configuration Manual » start_pushers","id":"503","title":"start_pushers"},"504":{"body":"It is possible to scale the processes that handle sending push notifications to sygnal and email by running a generic_worker and adding it's worker_name to a pusher_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. Ensure the main process and all pusher workers are restarted after changing this option. Example configuration for a single worker: pusher_instances: - pusher_worker1 And for multiple workers: pusher_instances: - pusher_worker1 - pusher_worker2","breadcrumbs":"Configuration » Configuration Manual » pusher_instances","id":"504","title":"pusher_instances"},"505":{"body":"Unnecessary to set if using federation_sender_instances with generic_workers . Controls sending of outbound federation transactions on the main process. Set to false if using a federation sender worker . Defaults to true. Example configuration: send_federation: false","breadcrumbs":"Configuration » Configuration Manual » send_federation","id":"505","title":"send_federation"},"506":{"body":"It is possible to scale the processes that handle sending outbound federation requests by running a generic_worker and adding it's 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. 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 with multiple servers. This configuration setting must be shared between all workers handling federation sending, and if changed all federation sender workers must be stopped at the same time and then started, to ensure that all instances are running with the same config (otherwise events may be dropped). Example configuration for a single worker: federation_sender_instances: - federation_sender1 And for multiple workers: federation_sender_instances: - federation_sender1 - federation_sender2","breadcrumbs":"Configuration » Configuration Manual » federation_sender_instances","id":"506","title":"federation_sender_instances"},"507":{"body":"When using workers this should be a map from worker_name to the HTTP replication listener of the worker, if configured, and to the main process. Each worker declared under stream_writers and outbound_federation_restricted_to needs a HTTP replication listener, and that listener should be included in the instance_map. The main process also needs an entry on the instance_map, and it should be listed under main if even one other worker exists . Ensure the port matches with what is declared inside the listener block for a replication listener. Example configuration: instance_map: main: host: localhost port: 8030 worker1: host: localhost port: 8034 other: host: localhost port: 8035 tls: true Example configuration(#2, for UNIX sockets): instance_map: main: path: /run/synapse/main_replication.sock worker1: path: /run/synapse/worker1_replication.sock","breadcrumbs":"Configuration » Configuration Manual » instance_map","id":"507","title":"instance_map"},"508":{"body":"Experimental: When using workers you can define which workers should handle writing to streams such as event persistence and typing notifications. Any worker specified here must also be in the instance_map . See the list of available streams in the worker documentation . Example configuration: stream_writers: events: worker1 typing: worker1","breadcrumbs":"Configuration » Configuration Manual » stream_writers","id":"508","title":"stream_writers"},"509":{"body":"When using workers, you can restrict outbound federation traffic to only go through a specific subset of workers. Any worker specified here must also be in the instance_map . worker_replication_secret must also be configured to authorize inter-worker communication. outbound_federation_restricted_to: - federation_sender1 - federation_sender2 Also see the worker documentation for more info. Added in Synapse 1.89.0.","breadcrumbs":"Configuration » Configuration Manual » outbound_federation_restricted_to","id":"509","title":"outbound_federation_restricted_to"},"51":{"body":"","breadcrumbs":"Configuring a Turn Server » coturn TURN server » coturn setup","id":"51","title":"coturn setup"},"510":{"body":"The worker that is used to run background tasks (e.g. cleaning up expired data). If not provided this defaults to the main process. Example configuration: run_background_tasks_on: worker1","breadcrumbs":"Configuration » Configuration Manual » run_background_tasks_on","id":"510","title":"run_background_tasks_on"},"511":{"body":"The worker that is used to update the user directory. If not provided this defaults to the main process. Example configuration: update_user_directory_from_worker: worker1 Added in Synapse 1.59.0.","breadcrumbs":"Configuration » Configuration Manual » update_user_directory_from_worker","id":"511","title":"update_user_directory_from_worker"},"512":{"body":"The worker that is used to send output traffic to Application Services. If not provided this defaults to the main process. Example configuration: notify_appservices_from_worker: worker1 Added in Synapse 1.59.0.","breadcrumbs":"Configuration » Configuration Manual » notify_appservices_from_worker","id":"512","title":"notify_appservices_from_worker"},"513":{"body":"The worker that is used to run background tasks for media repository. If running multiple media repositories you must configure a single instance to run the background tasks. If not provided this defaults to the main process or your single media_repository worker. Example configuration: media_instance_running_background_jobs: worker1 Added in Synapse 1.16.0.","breadcrumbs":"Configuration » Configuration Manual » media_instance_running_background_jobs","id":"513","title":"media_instance_running_background_jobs"},"514":{"body":"Configuration for Redis when using workers. This must be enabled when using workers. This setting has the following sub-options: enabled: whether to use Redis support. Defaults to false. host and port: Optional host and port to use to connect to redis. Defaults to localhost and 6379 path: The full path to a local Unix socket file. If this is used, host and port are ignored. Defaults to `/tmp/redis.sock' password: Optional password if configured on the Redis instance. password_path: Alternative to password, reading the password from an external file. The file should be a plain text file, containing only the password. Synapse reads the password from the given file once at startup. dbid: Optional redis dbid if needs to connect to specific redis logical db. use_tls: Whether to use tls connection. Defaults to false. certificate_file: Optional path to the certificate file private_key_file: Optional path to the private key file ca_file: Optional path to the CA certificate file. Use this one or: ca_path: Optional path to the folder containing the CA certificate file Added in Synapse 1.78.0. Changed in Synapse 1.84.0: Added use_tls, certificate_file, private_key_file, ca_file and ca_path attributes Changed in Synapse 1.85.0: Added path option to use a local Unix socket Changed in Synapse 1.116.0: Added password_path Example configuration: redis: enabled: true host: localhost port: 6379 password_path: # OR password: dbid: #use_tls: True #certificate_file: #private_key_file: #ca_file: ","breadcrumbs":"Configuration » Configuration Manual » redis","id":"514","title":"redis"},"515":{"body":"These options configure an individual worker, in its worker configuration file. They should be not be provided when configuring the main process. Note also the configuration above for coordinating a cluster of workers . For guidance on setting up workers, see the worker documentation .","breadcrumbs":"Configuration » Configuration Manual » Individual worker configuration","id":"515","title":"Individual worker configuration"},"516":{"body":"The type of worker. The currently available worker applications are listed in worker documentation . The most common worker is the synapse.app.generic_worker . Example configuration: worker_app: synapse.app.generic_worker","breadcrumbs":"Configuration » Configuration Manual » worker_app","id":"516","title":"worker_app"},"517":{"body":"A unique name for the worker. The worker needs a name to be addressed in further parameters and identification in log files. We strongly recommend giving each worker a unique worker_name. Example configuration: worker_name: generic_worker1","breadcrumbs":"Configuration » Configuration Manual » worker_name","id":"517","title":"worker_name"},"518":{"body":"A worker can handle HTTP requests. To do so, a worker_listeners option must be declared, in the same way as the listeners option in the shared config. Workers declared in stream_writers and instance_map will need to include a replication listener here, in order to accept internal HTTP requests from other workers. Example configuration: worker_listeners: - type: http port: 8083 resources: - names: [client, federation] Example configuration(#2, using UNIX sockets with a replication listener): worker_listeners: - type: http path: /run/synapse/worker_replication.sock resources: - names: [replication] - type: http path: /run/synapse/worker_public.sock resources: - names: [client, federation]","breadcrumbs":"Configuration » Configuration Manual » worker_listeners","id":"518","title":"worker_listeners"},"519":{"body":"A worker may have a listener for manhole . It allows server administrators to access a Python shell on the worker. Example configuration: worker_manhole: 9000 This is a short form for: worker_listeners: - port: 9000 bind_addresses: ['127.0.0.1'] type: manhole It needs also an additional manhole_settings configuration.","breadcrumbs":"Configuration » Configuration Manual » worker_manhole","id":"519","title":"worker_manhole"},"52":{"body":"The TURN daemon coturn is available from a variety of sources such as native package managers, or installation from source. Debian and Ubuntu based distributions Just install the debian package: sudo apt install coturn This will install and start a systemd service called coturn. Source installation Download the latest release from github. Unpack it and cd into the directory. Configure it: ./configure You may need to install libevent2: if so, you should do so in the way recommended by your operating system. You can ignore warnings about lack of database support: a database is unnecessary for this purpose. Build and install it: make\nsudo make install","breadcrumbs":"Configuring a Turn Server » coturn TURN server » Initial installation","id":"52","title":"Initial installation"},"520":{"body":"Specifies whether the worker should be started as a daemon process. If Synapse is being managed by systemd , this option must be omitted or set to false. Defaults to false. Example configuration: worker_daemonize: true","breadcrumbs":"Configuration » Configuration Manual » worker_daemonize","id":"520","title":"worker_daemonize"},"521":{"body":"When running a worker as a daemon, we need a place to store the PID of the worker. This option defines the location of that \"pid file\". This option is required if worker_daemonize is true and ignored otherwise. It has no default. See also the pid_file option option for the main Synapse process. Example configuration: worker_pid_file: DATADIR/generic_worker1.pid","breadcrumbs":"Configuration » Configuration Manual » worker_pid_file","id":"521","title":"worker_pid_file"},"522":{"body":"This option specifies a yaml python logging config file as described here . See also the log_config option option for the main Synapse process. Example configuration: worker_log_config: /etc/matrix-synapse/generic-worker-log.yaml","breadcrumbs":"Configuration » Configuration Manual » worker_log_config","id":"522","title":"worker_log_config"},"523":{"body":"Configuration settings related to background updates.","breadcrumbs":"Configuration » Configuration Manual » Background Updates","id":"523","title":"Background Updates"},"524":{"body":"Background updates are database updates that are run in the background in batches. The duration, minimum batch size, default batch size, whether to sleep between batches and if so, how long to sleep can all be configured. This is helpful to speed up or slow down the updates. This setting has the following sub-options: background_update_duration_ms: How long in milliseconds to run a batch of background updates for. Defaults to 100. Set a different time to change the default. sleep_enabled: Whether to sleep between updates. Defaults to true. Set to false to change the default. sleep_duration_ms: If sleeping between updates, how long in milliseconds to sleep for. Defaults to 1000. Set a duration to change the default. min_batch_size: Minimum size a batch of background updates can be. Must be greater than 0. Defaults to 1. Set a size to change the default. default_batch_size: The batch size to use for the first iteration of a new background update. The default is 100. Set a size to change the default. Example configuration: background_updates: background_update_duration_ms: 500 sleep_enabled: false sleep_duration_ms: 300 min_batch_size: 10 default_batch_size: 50","breadcrumbs":"Configuration » Configuration Manual » background_updates","id":"524","title":"background_updates"},"525":{"body":"Configuration settings related to automatically accepting invites.","breadcrumbs":"Configuration » Configuration Manual » Auto Accept Invites","id":"525","title":"Auto Accept Invites"},"526":{"body":"Automatically accepting invites controls whether users are presented with an invite request or if they are instead automatically joined to a room when receiving an invite. Set the enabled sub-option to true to enable auto-accepting invites. Defaults to false. This setting has the following sub-options: enabled: Whether to run the auto-accept invites logic. Defaults to false. 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 the \"worker_name\". If not set or null, invites will be accepted on the main process. NOTE: Care should be taken not to enable this setting if the synapse_auto_accept_invite module is enabled and installed. The two modules will compete to perform the same task and may result in undesired behaviour. For example, multiple join events could be generated from a single invite. Example configuration: auto_accept_invites: enabled: true only_for_direct_messages: true only_from_local_users: true worker_to_run_on: \"worker_1\"","breadcrumbs":"Configuration » Configuration Manual » auto_accept_invites","id":"526","title":"auto_accept_invites"},"527":{"body":"Below is a sample homeserver configuration file. The homeserver configuration file can be tweaked to change the behaviour of your homeserver. A restart of the server is generally required to apply any changes made to this file. Note that the contents below are not intended to be copied and used as the basis for a real homeserver.yaml. Instead, if you are starting from scratch, please generate a fresh config using Synapse by following the instructions in Installation . Documentation for all configuration options can be found in the Configuration Manual . # This file is maintained as an up-to-date snapshot of the default\n# homeserver.yaml configuration generated by Synapse. You can find a\n# complete accounting of possible configuration options at\n# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html\n#\n# It is *not* intended to be copied and used as the basis for a real\n# homeserver.yaml. Instead, if you are starting from scratch, please generate\n# a fresh config using Synapse by following the instructions in\n# https://element-hq.github.io/synapse/latest/setup/installation.html.\n#\n################################################################################ # Configuration file for Synapse.\n#\n# This is a YAML file: see [1] for a quick introduction. Note in particular\n# that *indentation is important*: all the elements of a list or dictionary\n# should have the same indentation.\n#\n# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html\n#\n# For more information on how to configure Synapse, including a complete accounting of\n# each option, go to docs/usage/configuration/config_documentation.md or\n# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html\nserver_name: \"SERVERNAME\"\npid_file: DATADIR/homeserver.pid\nlisteners: - port: 8008 tls: false type: http x_forwarded: true bind_addresses: ['::1', '127.0.0.1'] resources: - names: [client, federation] compress: false\ndatabase: name: sqlite3 args: database: DATADIR/homeserver.db\nlog_config: \"CONFDIR/SERVERNAME.log.config\"\nmedia_store_path: DATADIR/media_store\nsigning_key_path: \"CONFDIR/SERVERNAME.signing.key\"\ntrusted_key_servers: - server_name: \"matrix.org\"","breadcrumbs":"Configuration » Homeserver Sample Config File » Homeserver Sample Configuration File","id":"527","title":"Homeserver Sample Configuration File"},"528":{"body":"Below is a sample logging configuration file. This file can be tweaked to control how your homeserver will output logs. The value of the log_config option in your homeserver config should be the path to this file. To apply changes made to this file, send Synapse a SIGHUP signal (or, if using systemd, run systemctl reload on the Synapse service). Note that a default logging configuration (shown below) is created automatically alongside the homeserver config when following the installation instructions . It should be named .log.config by default. Hint: If you're looking for a guide on what each of the fields in the \"Processed request\" log lines mean, see Request log format . # Log configuration for Synapse.\n#\n# This is a YAML file containing a standard Python logging configuration\n# dictionary. See [1] for details on the valid settings.\n#\n# Synapse also supports structured logging for machine readable logs which can\n# be ingested by ELK stacks. See [2] for details.\n#\n# [1]: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema\n# [2]: https://element-hq.github.io/synapse/latest/structured_logging.html version: 1 formatters: precise: format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' handlers: file: class: logging.handlers.TimedRotatingFileHandler formatter: precise filename: /var/log/matrix-synapse/homeserver.log when: midnight backupCount: 3 # Does not include the current log file. encoding: utf8 # Default to buffering writes to log file for efficiency. # WARNING/ERROR logs will still be flushed immediately, but there will be a # delay (of up to `period` seconds, or until the buffer is full with # `capacity` messages) before INFO/DEBUG logs get written. buffer: class: synapse.logging.handlers.PeriodicallyFlushingMemoryHandler target: file # The capacity is the maximum number of log lines that are buffered # before being written to disk. Increasing this will lead to better # performance, at the expensive of it taking longer for log lines to # be written to disk. # This parameter is required. capacity: 10 # Logs with a level at or above the flush level will cause the buffer to # be flushed immediately. # Default value: 40 (ERROR) # Other values: 50 (CRITICAL), 30 (WARNING), 20 (INFO), 10 (DEBUG) flushLevel: 30 # Flush immediately for WARNING logs and higher # The period of time, in seconds, between forced flushes. # Messages will not be delayed for longer than this time. # Default value: 5 seconds period: 5 # A handler that writes logs to stderr. Unused by default, but can be used # instead of \"buffer\" and \"file\" in the logger handlers. console: class: logging.StreamHandler formatter: precise loggers: synapse.storage.SQL: # beware: increasing this to DEBUG will make synapse log sensitive # information such as access tokens. level: INFO root: level: INFO # Write logs to the `buffer` handler, which will buffer them together in memory, # then write them to a file. # # Replace \"buffer\" with \"console\" to log to stderr instead. # handlers: [buffer] disable_existing_loggers: false","breadcrumbs":"Configuration » Logging Sample Config File » Logging Sample Configuration File","id":"528","title":"Logging Sample Configuration File"},"529":{"body":"A structured logging system can be useful when your logs are destined for a machine to parse and process. By maintaining its machine-readable characteristics, it enables more efficient searching and aggregations when consumed by software such as the ELK stack . Synapse's structured logging system is configured via the file that Synapse's log_config config option points to. The file should include a formatter which uses the synapse.logging.TerseJsonFormatter class included with Synapse and a handler which uses the above formatter. There is also a synapse.logging.JsonFormatter option which does not include a timestamp in the resulting JSON. This is useful if the log ingester adds its own timestamp. A structured logging configuration looks similar to the following: version: 1 formatters: structured: class: synapse.logging.TerseJsonFormatter handlers: file: class: logging.handlers.TimedRotatingFileHandler formatter: structured filename: /path/to/my/logs/homeserver.log when: midnight backupCount: 3 # Does not include the current log file. encoding: utf8 loggers: synapse: level: INFO handlers: [remote] synapse.storage.SQL: level: WARNING The above logging config will set Synapse as 'INFO' logging level by default, with the SQL layer at 'WARNING', and will log to a file, stored as JSON. It is also possible to configure Synapse to log to a remote endpoint by using the synapse.logging.RemoteHandler class included with Synapse. It takes the following arguments: host: Hostname or IP address of the log aggregator. port: Numerical port to contact on the host. maximum_buffer: (Optional, defaults to 1000) The maximum buffer size to allow. A remote structured logging configuration looks similar to the following: version: 1 formatters: structured: class: synapse.logging.TerseJsonFormatter handlers: remote: class: synapse.logging.RemoteHandler formatter: structured host: 10.1.2.3 port: 9999 loggers: synapse: level: INFO handlers: [remote] synapse.storage.SQL: level: WARNING The above logging config will set Synapse as 'INFO' logging level by default, with the SQL layer at 'WARNING', and will log JSON formatted messages to a remote endpoint at 10.1.2.3:9999.","breadcrumbs":"Configuration » Structured Logging » Structured Logging","id":"529","title":"Structured Logging"},"53":{"body":"Create or edit the config file in /etc/turnserver.conf. The relevant lines, with example values, are: use-auth-secret\nstatic-auth-secret=[your secret key here]\nrealm=turn.myserver.org See turnserver.conf for explanations of the options. One way to generate the static-auth-secret is with pwgen: pwgen -s 64 1 A realm must be specified, but its value is somewhat arbitrary. (It is sent to clients as part of the authentication flow.) It is conventional to set it to be your server name. You will most likely want to configure coturn to write logs somewhere. The easiest way is normally to send them to the syslog: syslog (in which case, the logs will be available via journalctl -u coturn on a systemd system). Alternatively, coturn can be configured to write to a logfile - check the example config file supplied with coturn. Consider your security settings. TURN lets users request a relay which will connect to arbitrary IP addresses and ports. The following configuration is suggested as a minimum starting point: # VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.\nno-tcp-relay # don't let the relay ever try to connect to private IP address ranges within your network (if any)\n# given the turn server is likely behind your firewall, remember to include any privileged public IPs too.\ndenied-peer-ip=10.0.0.0-10.255.255.255\ndenied-peer-ip=192.168.0.0-192.168.255.255\ndenied-peer-ip=172.16.0.0-172.31.255.255 # recommended additional local peers to block, to mitigate external access to internal services.\n# https://www.rtcsec.com/article/slack-webrtc-turn-compromise-and-bug-bounty/#how-to-fix-an-open-turn-relay-to-address-this-vulnerability\nno-multicast-peers\ndenied-peer-ip=0.0.0.0-0.255.255.255\ndenied-peer-ip=100.64.0.0-100.127.255.255\ndenied-peer-ip=127.0.0.0-127.255.255.255\ndenied-peer-ip=169.254.0.0-169.254.255.255\ndenied-peer-ip=192.0.0.0-192.0.0.255\ndenied-peer-ip=192.0.2.0-192.0.2.255\ndenied-peer-ip=192.88.99.0-192.88.99.255\ndenied-peer-ip=198.18.0.0-198.19.255.255\ndenied-peer-ip=198.51.100.0-198.51.100.255\ndenied-peer-ip=203.0.113.0-203.0.113.255\ndenied-peer-ip=240.0.0.0-255.255.255.255 # special case the turn server itself so that client->TURN->TURN->client flows work\n# this should be one of the turn server's listening IPs\nallowed-peer-ip=10.0.0.1 # consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS.\nuser-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.\ntotal-quota=1200 Also consider supporting TLS/DTLS. To do this, add the following settings to turnserver.conf: # TLS certificates, including intermediate certs.\n# For Let's Encrypt certificates, use `fullchain.pem` here.\ncert=/path/to/fullchain.pem # TLS private key file\npkey=/path/to/privkey.pem # Ensure the configuration lines that disable TLS/DTLS are commented-out or removed\n#no-tls\n#no-dtls In this case, replace the turn: schemes in the turn_uris settings below with turns:. We recommend that you only try to set up TLS/DTLS once you have set up a basic installation and got it working. NB: If your TLS certificate was provided by Let's Encrypt, TLS/DTLS will not work with any Matrix client that uses Chromium's WebRTC library. This currently includes Element Android & iOS; for more details, see their respective issues as well as the underlying WebRTC issue . Consider using a ZeroSSL certificate for your TURN server as a working alternative. Ensure your firewall allows traffic into the TURN server on the ports you've configured it to listen on (By default: 3478 and 5349 for TURN traffic (remember to allow both TCP and UDP traffic), and ports 49152-65535 for the UDP relay.) If your TURN server is behind NAT, the NAT gateway must have an external, publicly-reachable IP address. You must configure coturn to advertise that address to connecting clients: external-ip=EXTERNAL_NAT_IPv4_ADDRESS You may optionally limit the TURN server to listen only on the local address that is mapped by NAT to the external address: listening-ip=INTERNAL_TURNSERVER_IPv4_ADDRESS If your NAT gateway is reachable over both IPv4 and IPv6, you may configure coturn to advertise each available address: external-ip=EXTERNAL_NAT_IPv4_ADDRESS\nexternal-ip=EXTERNAL_NAT_IPv6_ADDRESS When advertising an external IPv6 address, ensure that the firewall and network settings of the system running your TURN server are configured to accept IPv6 traffic, and that the TURN server is listening on the local IPv6 address that is mapped by NAT to the external IPv6 address. (Re)start the turn server: If you used the Debian package (or have set up a systemd unit yourself): sudo systemctl restart coturn If you built from source: /usr/local/bin/turnserver -o","breadcrumbs":"Configuring a Turn Server » coturn TURN server » Configuration","id":"53","title":"Configuration"},"530":{"body":"Synapse uses parametrised templates to generate the content of emails it sends and webpages it shows to users. By default, Synapse will use the templates listed here . Server admins can configure an additional directory for Synapse to look for templates in, allowing them to specify custom templates: templates: custom_template_directory: /path/to/custom/templates/ If this setting is not set, or the files named below are not found within the directory, default templates from within the Synapse package will be used. Templates that are given variables when being rendered are rendered using Jinja 2 . Templates rendered by Jinja 2 can also access two functions on top of the functions already available as part of Jinja 2: format_ts(value: int, format: str) -> str Formats a timestamp in milliseconds. Example: reason.last_sent_ts|format_ts(\"%c\") mxc_to_http(value: str, width: int, height: int, resize_method: str = \"crop\") -> str Turns a mxc:// URL for media content into an HTTP(S) one using the homeserver's public_baseurl configuration setting as the URL's base. Example: message.sender_avatar_url|mxc_to_http(32,32) localpart_from_email(address: str) -> str Returns the local part of an email address (e.g. alice in alice@example.com). Example: user.email_address|localpart_from_email","breadcrumbs":"Configuration » Templates » Templates","id":"530","title":"Templates"},"531":{"body":"Below are the templates Synapse will look for when generating the content of an email: notif_mail.html and notif_mail.txt: The contents of email notifications of missed events. When rendering, this template is given the following variables: user_display_name: the display name for the user receiving the notification unsubscribe_link: the link users can click to unsubscribe from email notifications summary_text: a summary of the notification(s). The text used can be customised by configuring the various settings in the email.subjects section of the configuration file. rooms: a list of rooms containing events to include in the email. Each element is an object with the following attributes: title: a human-readable name for the room hash: a hash of the ID of the room invite: a boolean, which is True if the room is an invite the user hasn't accepted yet, False otherwise notifs: a list of events, or an empty list if invite is True. Each element is an object with the following attributes: link: a matrix.to link to the event ts: the time in milliseconds at which the event was received messages: a list of messages containing one message before the event, the message in the event, and one message after the event. Each element is an object with the following attributes: event_type: the type of the event is_historical: a boolean, which is False if the message is the one that triggered the notification, True otherwise id: the ID of the event ts: the time in milliseconds at which the event was sent sender_name: the display name for the event's sender sender_avatar_url: the avatar URL (as a mxc:// URL) for the event's sender sender_hash: a hash of the user ID of the sender msgtype: the type of the message body_text_html: html representation of the message body_text_plain: plaintext representation of the message image_url: mxc url of an image, when \"msgtype\" is \"m.image\" link: a matrix.to link to the room avator_url: url to the room's avator reason: information on the event that triggered the email to be sent. It's an object with the following attributes: room_id: the ID of the room the event was sent in room_name: a human-readable name for the room the event was sent in now: the current time in milliseconds received_at: the time in milliseconds at which the event was received delay_before_mail_ms: the amount of time in milliseconds Synapse always waits before ever emailing about a notification (to give the user a chance to respond to other push or notice the window) last_sent_ts: the time in milliseconds at which a notification was last sent for an event in this room throttle_ms: the minimum amount of time in milliseconds between two notifications can be sent for this room password_reset.html and password_reset.txt: The contents of password reset emails sent by the homeserver. When rendering, these templates are given a link variable which contains the link the user must click in order to reset their password. registration.html and registration.txt: The contents of address verification emails sent during registration. When rendering, these templates are given a link variable which contains the link the user must click in order to validate their email address. add_threepid.html and add_threepid.txt: The contents of address verification emails sent when an address is added to a Matrix account. When rendering, these templates are given a link variable which contains the link the user must click in order to validate their email address.","breadcrumbs":"Configuration » Templates » Email templates","id":"531","title":"Email templates"},"532":{"body":"Below are the templates Synapse will look for when generating pages related to registration and password reset: password_reset_confirmation.html: An HTML page that a user will see when they follow the link in the password reset email. The user will be asked to confirm the action before their password is reset. When rendering, this template is given the following variables: sid: the session ID for the password reset token: the token for the password reset client_secret: the client secret for the password reset password_reset_success.html and password_reset_failure.html: HTML pages for success and failure that a user will see when they confirm the password reset flow using the page above. When rendering, password_reset_success.html is given no variable, and password_reset_failure.html is given a failure_reason, which contains the reason for the password reset failure. registration_success.html and registration_failure.html: HTML pages for success and failure that a user will see when they follow the link in an address verification email sent during registration. When rendering, registration_success.html is given no variable, and registration_failure.html is given a failure_reason, which contains the reason for the registration failure. add_threepid_success.html and add_threepid_failure.html: HTML pages for success and failure that a user will see when they follow the link in an address verification email sent when an address is added to a Matrix account. When rendering, add_threepid_success.html is given no variable, and add_threepid_failure.html is given a failure_reason, which contains the reason for the registration failure.","breadcrumbs":"Configuration » Templates » HTML page templates for registration and password reset","id":"532","title":"HTML page templates for registration and password reset"},"533":{"body":"Below are the templates Synapse will look for when generating pages related to SSO: sso_login_idp_picker.html: HTML page to prompt the user to choose an Identity Provider during login. This is only used if multiple SSO Identity Providers are configured. When rendering, this template is given the following variables: redirect_url: the URL that the user will be redirected to after login. server_name: the homeserver's name. providers: a list of available Identity Providers. Each element is an object with the following attributes: idp_id: unique identifier for the IdP idp_name: user-facing name for the IdP idp_icon: if specified in the IdP config, an MXC URI for an icon for the IdP idp_brand: if specified in the IdP config, a textual identifier for the brand of the IdP The rendered HTML page should contain a form which submits its results back as a GET request, with the following query parameters: redirectUrl: the client redirect URI (ie, the redirect_url passed to the template) idp: the 'idp_id' of the chosen IDP. sso_auth_account_details.html: HTML page to prompt new users to enter a userid and confirm other details. This is only shown if the SSO implementation (with any user_mapping_provider) does not return a localpart. When rendering, this template is given the following variables: server_name: the homeserver's name. idp: details of the SSO Identity Provider that the user logged in with: an object with the following attributes: idp_id: unique identifier for the IdP idp_name: user-facing name for the IdP idp_icon: if specified in the IdP config, an MXC URI for an icon for the IdP idp_brand: if specified in the IdP config, a textual identifier for the brand of the IdP user_attributes: an object containing details about the user that we received from the IdP. May have the following attributes: display_name: the user's display name emails: a list of email addresses localpart: the local part of the Matrix user ID to register, if localpart_template is set in the mapping provider configuration (empty string if not) The template should render a form which submits the following fields: username: the localpart of the user's chosen user id sso_new_user_consent.html: HTML page allowing the user to consent to the server's terms and conditions. This is only shown for new users, and only if user_consent.require_at_registration is set. When rendering, this template is given the following variables: server_name: the homeserver's name. user_id: the user's matrix proposed ID. user_profile.display_name: the user's proposed display name, if any. consent_version: the version of the terms that the user will be shown terms_url: a link to the page showing the terms. The template should render a form which submits the following fields: accepted_version: the version of the terms accepted by the user (ie, 'consent_version' from the input variables). sso_redirect_confirm.html: HTML page for a confirmation step before redirecting back to the client with the login token. When rendering, this template is given the following variables: redirect_url: the URL the user is about to be redirected to. display_url: the same as redirect_url, but with the query parameters stripped. The intention is to have a human-readable URL to show to users, not to use it as the final address to redirect to. server_name: the homeserver's name. new_user: a boolean indicating whether this is the user's first time logging in. user_id: the user's matrix ID. user_profile.avatar_url: an MXC URI for the user's avatar, if any. None if the user has not set an avatar. user_profile.display_name: the user's display name. None if the user has not set a display name. sso_auth_confirm.html: HTML page which notifies the user that they are authenticating to confirm an operation on their account during the user interactive authentication process. When rendering, this template is given the following variables: redirect_url: the URL the user is about to be redirected to. description: the operation which the user is being asked to confirm idp: details of the Identity Provider that we will use to confirm the user's identity: an object with the following attributes: idp_id: unique identifier for the IdP idp_name: user-facing name for the IdP idp_icon: if specified in the IdP config, an MXC URI for an icon for the IdP idp_brand: if specified in the IdP config, a textual identifier for the brand of the IdP sso_auth_success.html: HTML page shown after a successful user interactive authentication session. Note that this page must include the JavaScript which notifies of a successful authentication (see https://matrix.org/docs/spec/client_server/r0.6.0#fallback). This template has no additional variables. sso_auth_bad_user.html: HTML page shown after a user-interactive authentication session which does not map correctly onto the expected user. When rendering, this template is given the following variables: server_name: the homeserver's name. user_id_to_verify: the MXID of the user that we are trying to validate. sso_account_deactivated.html: HTML page shown during single sign-on if a deactivated user (according to Synapse's database) attempts to login. This template has no additional variables. sso_error.html: HTML page to display to users if something goes wrong during the OpenID Connect authentication process. When rendering, this template is given two variables: error: the technical name of the error error_description: a human-readable message for the error","breadcrumbs":"Configuration » Templates » HTML page templates for Single Sign-On (SSO)","id":"533","title":"HTML page templates for Single Sign-On (SSO)"},"534":{"body":"Synapse supports multiple methods of authenticating users, either out-of-the-box or through custom pluggable authentication modules. Included in Synapse is support for authenticating users via: A username and password. An email address and password. Single Sign-On through the SAML, Open ID Connect or CAS protocols. JSON Web Tokens. An administrator's shared secret. Synapse can additionally be extended to support custom authentication schemes through optional \"password auth provider\" modules.","breadcrumbs":"Configuration » User Authentication » User Authentication","id":"534","title":"User Authentication"},"535":{"body":"Synapse supports single sign-on through the SAML, Open ID Connect or CAS protocols. LDAP and other login methods are supported through first and third-party password auth provider modules.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » Single Sign-On","id":"535","title":"Single Sign-On"},"536":{"body":"Synapse can be configured to use an OpenID Connect Provider (OP) for authentication, instead of its own local password database. Any OP should work with Synapse, as long as it supports the authorization code flow. There are a few options for that: start a local OP. Synapse has been tested with Hydra and Dex . Note that for an OP to work, it should be served under a secure (HTTPS) origin. A certificate signed with a self-signed, locally trusted CA should work. In that case, start Synapse with a SSL_CERT_FILE environment variable set to the path of the CA. set up a SaaS OP, like Google , Auth0 or Okta . Synapse has been tested with Auth0 and Google. It may also be possible to use other OAuth2 providers which provide the authorization code grant type , such as Github .","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Configuring Synapse to authenticate against an OpenID Connect provider","id":"536","title":"Configuring Synapse to authenticate against an OpenID Connect provider"},"537":{"body":"The OpenID integration in Synapse uses the authlib library, which must be installed as follows: The relevant libraries are included in the Docker images and Debian packages provided by matrix.org so no further action is needed. If you installed Synapse into a virtualenv, run /path/to/env/bin/pip install matrix-synapse[oidc] to install the necessary dependencies. For other installation mechanisms, see the documentation provided by the maintainer. To enable the OpenID integration, you should then add a section to the oidc_providers setting in your configuration file. See the configuration manual for some sample settings, as well as the text below for example configurations for specific providers.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Preparing Synapse","id":"537","title":"Preparing Synapse"},"538":{"body":"Synapse supports receiving OpenID Connect Back-Channel Logout notifications. This lets the OpenID Connect Provider notify Synapse when a user logs out, so that Synapse can end that user session. This feature can be enabled by setting the backchannel_logout_enabled property to true in the provider configuration, and setting the following URL as destination for Back-Channel Logout notifications in your OpenID Connect Provider: [synapse public baseurl]/_synapse/client/oidc/backchannel_logout","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » OIDC Back-Channel Logout","id":"538","title":"OIDC Back-Channel Logout"},"539":{"body":"Here are a few configs for providers that should work with Synapse.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Sample configs","id":"539","title":"Sample configs"},"54":{"body":"The following sections describe how to install eturnal (which implements the TURN REST API).","breadcrumbs":"Configuring a Turn Server » eturnal TURN server » eturnal TURN server","id":"54","title":"eturnal TURN server"},"540":{"body":"Azure AD can act as an OpenID Connect Provider. Register a new application under App registrations in the Azure AD management console. The RedirectURI for your application should point to your matrix server: [synapse public baseurl]/_synapse/client/oidc/callback Go to Certificates & secrets and register a new client secret. Make note of your Directory (tenant) ID as it will be used in the Azure links. Edit your Synapse config file and change the oidc_config section: oidc_providers: - idp_id: microsoft idp_name: Microsoft issuer: \"https://login.microsoftonline.com//v2.0\" client_id: \"\" client_secret: \"\" scopes: [\"openid\", \"profile\"] authorization_endpoint: \"https://login.microsoftonline.com//oauth2/v2.0/authorize\" token_endpoint: \"https://login.microsoftonline.com//oauth2/v2.0/token\" userinfo_endpoint: \"https://graph.microsoft.com/oidc/userinfo\" user_mapping_provider: config: localpart_template: \"{{ user.preferred_username.split('@')[0] }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Microsoft Azure Active Directory","id":"540","title":"Microsoft Azure Active Directory"},"541":{"body":"Configuring \"Sign in with Apple\" (SiWA) requires an Apple Developer account. You will need to create a new \"Services ID\" for SiWA, and create and download a private key with \"SiWA\" enabled. As well as the private key file, you will need: Client ID: the \"identifier\" you gave the \"Services ID\" Team ID: a 10-character ID associated with your developer account. Key ID: the 10-character identifier for the key. Apple's developer documentation has more information on setting up SiWA. The synapse config will look like this: - idp_id: apple idp_name: Apple issuer: \"https://appleid.apple.com\" client_id: \"your-client-id\" # Set to the \"identifier\" for your \"ServicesID\" client_auth_method: \"client_secret_post\" client_secret_jwt_key: key_file: \"/path/to/AuthKey_KEYIDCODE.p8\" # point to your key file jwt_header: alg: ES256 kid: \"KEYIDCODE\" # Set to the 10-char Key ID jwt_payload: iss: TEAMIDCODE # Set to the 10-char Team ID scopes: [\"name\", \"email\", \"openid\"] authorization_endpoint: https://appleid.apple.com/auth/authorize?response_mode=form_post user_mapping_provider: config: email_template: \"{{ user.email }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Apple","id":"541","title":"Apple"},"542":{"body":"Auth0 is a hosted SaaS IdP solution. Create a regular web application for Synapse Set the Allowed Callback URLs to [synapse public baseurl]/_synapse/client/oidc/callback Add a rule with any name to add the preferred_username claim. (See https://auth0.com/docs/customize/rules/create-rules for more information on how to create rules.) Code sample function addPersistenceAttribute(user, context, callback) { user.user_metadata = user.user_metadata || {}; user.user_metadata.preferred_username = user.user_metadata.preferred_username || user.user_id; context.idToken.preferred_username = user.user_metadata.preferred_username; auth0.users.updateUserMetadata(user.user_id, user.user_metadata) .then(function(){ callback(null, user, context); }) .catch(function(err){ callback(err); });\n} Synapse config: oidc_providers: - idp_id: auth0 idp_name: Auth0 issuer: \"https://your-tier.eu.auth0.com/\" # TO BE FILLED client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED scopes: [\"openid\", \"profile\"] user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Auth0","id":"542","title":"Auth0"},"543":{"body":"Authentik is an open-source IdP solution. Create a provider in Authentik, with type OAuth2/OpenID. The parameters are: Client Type: Confidential JWT Algorithm: RS256 Scopes: OpenID, Email and Profile RSA Key: Select any available key Redirect URIs: [synapse public baseurl]/_synapse/client/oidc/callback Create an application for synapse in Authentik and link it to the provider. Note the slug of your application, Client ID and Client Secret. Note: RSA keys must be used for signing for Authentik, ECC keys do not work. Synapse config: oidc_providers: - idp_id: authentik idp_name: authentik discover: true issuer: \"https://your.authentik.example.org/application/o/your-app-slug/\" # TO BE FILLED: domain and slug client_id: \"your client id\" # TO BE FILLED client_secret: \"your client secret\" # TO BE FILLED scopes: - \"openid\" - \"profile\" - \"email\" user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.preferred_username|capitalize }}\" # TO BE FILLED: If your users have names in Authentik and you want those in Synapse, this should be replaced with user.name|capitalize.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Authentik","id":"543","title":"Authentik"},"544":{"body":"Dex is a simple, open-source OpenID Connect Provider. Although it is designed to help building a full-blown provider with an external database, it can be configured with static passwords in a config file. Follow the Getting Started guide to install Dex. Edit examples/config-dev.yaml config file from the Dex repo to add a client: staticClients:\n- id: synapse secret: secret redirectURIs: - '[synapse public baseurl]/_synapse/client/oidc/callback' name: 'Synapse' Run with dex serve examples/config-dev.yaml. Synapse config: oidc_providers: - idp_id: dex idp_name: \"My Dex server\" skip_verification: true # This is needed as Dex is served on an insecure endpoint issuer: \"http://127.0.0.1:5556/dex\" client_id: \"synapse\" client_secret: \"secret\" scopes: [\"openid\", \"profile\"] user_mapping_provider: config: localpart_template: \"{{ user.name }}\" display_name_template: \"{{ user.name|capitalize }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Dex","id":"544","title":"Dex"},"545":{"body":"django-oauth-toolkit is a Django application providing out of the box all the endpoints, data and logic needed to add OAuth2 capabilities to your Django projects. It supports OpenID Connect too . Configuration on Django's side: Add an application: https://example.com/admin/oauth2_provider/application/add/ and choose parameters like this: Redirect uris: https://synapse.example.com/_synapse/client/oidc/callback Client type: Confidential Authorization grant type: Authorization code Algorithm: HMAC with SHA-2 256 You can customize the claims Django gives to synapse (optional): Code sample class CustomOAuth2Validator(OAuth2Validator): def get_additional_claims(self, request): return { \"sub\": request.user.email, \"email\": request.user.email, \"first_name\": request.user.first_name, \"last_name\": request.user.last_name, } Your synapse config is then: oidc_providers: - idp_id: django_example idp_name: \"Django Example\" issuer: \"https://example.com/o/\" client_id: \"your-client-id\" # CHANGE ME client_secret: \"your-client-secret\" # CHANGE ME scopes: [\"openid\"] user_profile_method: \"userinfo_endpoint\" # needed because oauth-toolkit does not include user information in the authorization response user_mapping_provider: config: localpart_template: \"{{ user.email.split('@')[0] }}\" display_name_template: \"{{ user.first_name }} {{ user.last_name }}\" email_template: \"{{ user.email }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Django OAuth Toolkit","id":"545","title":"Django OAuth Toolkit"},"546":{"body":"You will need a Facebook developer account. You can register for one here . On the apps page of the developer console, \"Create App\", and choose \"Build Connected Experiences\". Once the app is created, add \"Facebook Login\" and choose \"Web\". You don't need to go through the whole form here. In the left-hand menu, open \"Products\"/\"Facebook Login\"/\"Settings\". Add [synapse public baseurl]/_synapse/client/oidc/callback as an OAuth Redirect URL. In the left-hand menu, open \"Settings/Basic\". Here you can copy the \"App ID\" and \"App Secret\" for use below. Synapse config: - idp_id: facebook idp_name: Facebook idp_brand: \"facebook\" # optional: styling hint for clients discover: false issuer: \"https://www.facebook.com\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED scopes: [\"openid\", \"email\"] authorization_endpoint: \"https://facebook.com/dialog/oauth\" token_endpoint: \"https://graph.facebook.com/v9.0/oauth/access_token\" jwks_uri: \"https://www.facebook.com/.well-known/oauth/openid/jwks/\" user_mapping_provider: config: display_name_template: \"{{ user.name }}\" email_template: \"{{ user.email }}\" Relevant documents: Manually Build a Login Flow Using Facebook's Graph API Reference to the User endpoint Facebook do have an OIDC discovery endpoint , but it has a response_types_supported which excludes \"code\" (which we rely on, and is even mentioned in their documentation ), so we have to disable discovery and configure the URIs manually.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Facebook","id":"546","title":"Facebook"},"547":{"body":"Forgejo is a fork of Gitea that can act as an OAuth2 provider. The implementation of OAuth2 is improved compared to Gitea, as it provides a correctly defined subject_claim and scopes. Synapse config: oidc_providers: - idp_id: forgejo idp_name: Forgejo discover: false issuer: \"https://your-forgejo.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED client_auth_method: client_secret_post scopes: [\"openid\", \"profile\", \"email\", \"groups\"] authorization_endpoint: \"https://your-forgejo.com/login/oauth/authorize\" token_endpoint: \"https://your-forgejo.com/login/oauth/access_token\" userinfo_endpoint: \"https://your-forgejo.com/api/v1/user\" user_mapping_provider: config: subject_claim: \"sub\" picture_claim: \"picture\" localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\" email_template: \"{{ user.email }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Forgejo","id":"547","title":"Forgejo"},"548":{"body":"GitHub is a bit special as it is not an OpenID Connect compliant provider, but just a regular OAuth2 provider. The /user API endpoint can be used to retrieve information on the authenticated user. As the Synapse login mechanism needs an attribute to uniquely identify users, and that endpoint does not return a sub property, an alternative subject_claim has to be set. Create a new OAuth application: https://github.com/settings/applications/new . Set the callback URL to [synapse public baseurl]/_synapse/client/oidc/callback. Synapse config: oidc_providers: - idp_id: github idp_name: Github idp_brand: \"github\" # optional: styling hint for clients discover: false issuer: \"https://github.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED authorization_endpoint: \"https://github.com/login/oauth/authorize\" token_endpoint: \"https://github.com/login/oauth/access_token\" userinfo_endpoint: \"https://api.github.com/user\" scopes: [\"read:user\"] user_mapping_provider: config: subject_claim: \"id\" localpart_template: \"{{ user.login }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » GitHub","id":"548","title":"GitHub"},"549":{"body":"Create a new application . Add the read_user and openid scopes. Add this Callback URL: [synapse public baseurl]/_synapse/client/oidc/callback Synapse config: oidc_providers: - idp_id: gitlab idp_name: Gitlab idp_brand: \"gitlab\" # optional: styling hint for clients issuer: \"https://gitlab.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED client_auth_method: \"client_secret_post\" scopes: [\"openid\", \"read_user\"] user_profile_method: \"userinfo_endpoint\" user_mapping_provider: config: localpart_template: '{{ user.nickname }}' display_name_template: '{{ user.name }}'","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » GitLab","id":"549","title":"GitLab"},"55":{"body":"","breadcrumbs":"Configuring a Turn Server » eturnal TURN server » eturnal setup","id":"55","title":"eturnal setup"},"550":{"body":"Gitea is, like Github, not an OpenID provider, but just an OAuth2 provider. The /user API endpoint can be used to retrieve information on the authenticated user. As the Synapse login mechanism needs an attribute to uniquely identify users, and that endpoint does not return a sub property, an alternative subject_claim has to be set. Create a new application. Add this Callback URL: [synapse public baseurl]/_synapse/client/oidc/callback Synapse config: oidc_providers: - idp_id: gitea idp_name: Gitea discover: false issuer: \"https://your-gitea.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED client_auth_method: client_secret_post scopes: [] # Gitea doesn't support Scopes authorization_endpoint: \"https://your-gitea.com/login/oauth/authorize\" token_endpoint: \"https://your-gitea.com/login/oauth/access_token\" userinfo_endpoint: \"https://your-gitea.com/api/v1/user\" user_mapping_provider: config: subject_claim: \"id\" localpart_template: \"{{ user.login }}\" display_name_template: \"{{ user.full_name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Gitea","id":"550","title":"Gitea"},"551":{"body":"Google is an OpenID certified authentication and authorisation provider. Set up a project in the Google API Console (see documentation ). Add an \"OAuth Client ID\" for a Web Application under \"Credentials\". Copy the Client ID and Client Secret, and add the following to your synapse config: oidc_providers: - idp_id: google idp_name: Google idp_brand: \"google\" # optional: styling hint for clients issuer: \"https://accounts.google.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED scopes: [\"openid\", \"profile\", \"email\"] # email is optional, read below user_mapping_provider: config: localpart_template: \"{{ user.given_name|lower }}\" display_name_template: \"{{ user.name }}\" email_template: \"{{ user.email }}\" # needs \"email\" in scopes above Back in the Google console, add this Authorized redirect URI: [synapse public baseurl]/_synapse/client/oidc/callback.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Google","id":"551","title":"Google"},"552":{"body":"Keycloak is an opensource IdP maintained by Red Hat. Keycloak supports OIDC Back-Channel Logout, which sends logout notification to Synapse, so that Synapse users get logged out when they log out from Keycloak. This can be optionally enabled by setting backchannel_logout_enabled to true in the Synapse configuration, and by setting the \"Backchannel Logout URL\" in Keycloak. Follow the Getting Started Guide to install Keycloak and set up a realm. Click Clients in the sidebar and click Create Fill in the fields as below: Field Value Client ID synapse Client Protocol openid-connect Click Save Fill in the fields as below: Field Value Client ID synapse Enabled On Client Protocol openid-connect Access Type confidential Valid Redirect URIs [synapse public baseurl]/_synapse/client/oidc/callback Backchannel Logout URL (optional) [synapse public baseurl]/_synapse/client/oidc/backchannel_logout Backchannel Logout Session Required (optional) On Click Save On the Credentials tab, update the fields: Field Value Client Authenticator Client ID and Secret Click Regenerate Secret Copy Secret oidc_providers: - idp_id: keycloak idp_name: \"My KeyCloak server\" issuer: \"https://127.0.0.1:8443/realms/{realm_name}\" client_id: \"synapse\" client_secret: \"copy secret generated from above\" scopes: [\"openid\", \"profile\"] user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\" backchannel_logout_enabled: true # Optional","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Keycloak","id":"552","title":"Keycloak"},"553":{"body":"LemonLDAP::NG is an open-source IdP solution. Create an OpenID Connect Relying Parties in LemonLDAP::NG The parameters are: Client ID under the basic menu of the new Relying Parties (Options > Basic > Client ID) Client secret (Options > Basic > Client secret) JWT Algorithm: RS256 within the security menu of the new Relying Parties (Options > Security > ID Token signature algorithm and Options > Security > Access Token signature algorithm) Scopes: OpenID, Email and Profile Force claims into id_token (Options > Advanced > Force claims to be returned in ID Token) Allowed redirection addresses for login (Options > Basic > Allowed redirection addresses for login ) : [synapse public baseurl]/_synapse/client/oidc/callback Synapse config: oidc_providers: - idp_id: lemonldap idp_name: lemonldap discover: true issuer: \"https://auth.example.org/\" # TO BE FILLED: replace with your domain client_id: \"your client id\" # TO BE FILLED client_secret: \"your client secret\" # TO BE FILLED scopes: - \"openid\" - \"profile\" - \"email\" user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}}\" # TO BE FILLED: If your users have names in LemonLDAP::NG and you want those in Synapse, this should be replaced with user.name|capitalize or any valid filter. display_name_template: \"{{ user.preferred_username|capitalize }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » LemonLDAP","id":"553","title":"LemonLDAP"},"554":{"body":"Mastodon instances provide an OAuth API , allowing those instances to be used as a single sign-on provider for Synapse. The first step is to register Synapse as an application with your Mastodon instance, using the Create an application API (see also here ). There are several ways to do this, but in the example below we are using CURL. This example assumes that: the Mastodon instance website URL is https://your.mastodon.instance.url, and Synapse will be registered as an app named my_synapse_app. Send the following request, substituting the value of synapse_public_baseurl from your Synapse installation. curl -d \"client_name=my_synapse_app&redirect_uris=https://[synapse_public_baseurl]/_synapse/client/oidc/callback\" -X POST https://your.mastodon.instance.url/api/v1/apps You should receive a response similar to the following. Make sure to save it. {\"client_id\":\"someclientid_123\",\"client_secret\":\"someclientsecret_123\",\"id\":\"12345\",\"name\":\"my_synapse_app\",\"redirect_uri\":\"https://[synapse_public_baseurl]/_synapse/client/oidc/callback\",\"website\":null,\"vapid_key\":\"somerandomvapidkey_123\"} As the Synapse login mechanism needs an attribute to uniquely identify users, and Mastodon's endpoint does not return a sub property, an alternative subject_template has to be set. Your Synapse configuration should include the following: oidc_providers: - idp_id: my_mastodon idp_name: \"Mastodon Instance Example\" discover: false issuer: \"https://your.mastodon.instance.url/@admin\" client_id: \"someclientid_123\" client_secret: \"someclientsecret_123\" authorization_endpoint: \"https://your.mastodon.instance.url/oauth/authorize\" token_endpoint: \"https://your.mastodon.instance.url/oauth/token\" userinfo_endpoint: \"https://your.mastodon.instance.url/api/v1/accounts/verify_credentials\" scopes: [\"read\"] user_mapping_provider: config: subject_template: \"{{ user.id }}\" localpart_template: \"{{ user.username }}\" display_name_template: \"{{ user.display_name }}\" Note that the fields client_id and client_secret are taken from the CURL response above.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Mastodon","id":"554","title":"Mastodon"},"555":{"body":"Pocket ID is a simple OIDC provider that allows users to authenticate with their passkeys. Go to OIDC Clients Click on Add OIDC Client Add a name, for example Synapse Add \"https://auth.example.org/_synapse/client/oidc/callback to Callback URLs # Replace auth.example.org with your domain Click on Save Note down your Client ID and Client secret, these will be used later Synapse config: oidc_providers: - idp_id: pocket_id idp_name: Pocket ID issuer: \"https://auth.example.org/\" # Replace with your domain client_id: \"your-client-id\" # Replace with the \"Client ID\" you noted down before client_secret: \"your-client-secret\" # Replace with the \"Client secret\" you noted down before scopes: [\"openid\", \"profile\"] user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Pocket ID","id":"555","title":"Pocket ID"},"556":{"body":"Shibboleth is an open Standard IdP solution widely used by Universities. Shibboleth needs the OIDC Plugin installed and working correctly. Create a new config on the IdP Side, ensure that the client_id and client_secret are randomly generated data. { \"client_id\": \"SOME-CLIENT-ID\", \"client_secret\": \"SOME-SUPER-SECRET-SECRET\", \"response_types\": [\"code\"], \"grant_types\": [\"authorization_code\"], \"scope\": \"openid profile email\", \"redirect_uris\": [\"https://[synapse public baseurl]/_synapse/client/oidc/callback\"]\n} Synapse config: oidc_providers: # Shibboleth IDP # - idp_id: shibboleth idp_name: \"Shibboleth Login\" discover: true issuer: \"https://YOUR-IDP-URL.TLD\" client_id: \"YOUR_CLIENT_ID\" client_secret: \"YOUR-CLIENT-SECRECT-FROM-YOUR-IDP\" scopes: [\"openid\", \"profile\", \"email\"] allow_existing_users: true user_profile_method: \"userinfo_endpoint\" user_mapping_provider: config: subject_claim: \"sub\" localpart_template: \"{{ user.sub.split('@')[0] }}\" display_name_template: \"{{ user.name }}\" email_template: \"{{ user.email }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Shibboleth with OIDC Plugin","id":"556","title":"Shibboleth with OIDC Plugin"},"557":{"body":"Setup a developer account on Twitch Obtain the OAuth 2.0 credentials by creating an app Add this OAuth Redirect URL: [synapse public baseurl]/_synapse/client/oidc/callback Synapse config: oidc_providers: - idp_id: twitch idp_name: Twitch issuer: \"https://id.twitch.tv/oauth2/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED client_auth_method: \"client_secret_post\" user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Twitch","id":"557","title":"Twitch"},"558":{"body":"Using Twitter as an identity provider requires using Synapse 1.75.0 or later. Setup a developer account on Twitter Create a project & app. Enable user authentication and under \"Type of App\" choose \"Web App, Automated App or Bot\". Under \"App info\" set the callback URL to [synapse public baseurl]/_synapse/client/oidc/callback. Obtain the OAuth 2.0 credentials under the \"Keys and tokens\" tab, copy the \"OAuth 2.0 Client ID and Client Secret\" Synapse config: oidc_providers: - idp_id: twitter idp_name: Twitter idp_brand: \"twitter\" # optional: styling hint for clients discover: false # Twitter is not OpenID compliant. issuer: \"https://twitter.com/\" client_id: \"your-client-id\" # TO BE FILLED client_secret: \"your-client-secret\" # TO BE FILLED pkce_method: \"always\" # offline.access providers refresh tokens, tweet.read and users.read needed for userinfo request. scopes: [\"offline.access\", \"tweet.read\", \"users.read\"] authorization_endpoint: https://twitter.com/i/oauth2/authorize token_endpoint: https://api.twitter.com/2/oauth2/token userinfo_endpoint: https://api.twitter.com/2/users/me?user.fields=profile_image_url user_mapping_provider: config: subject_template: \"{{ user.data.id }}\" localpart_template: \"{{ user.data.username }}\" display_name_template: \"{{ user.data.name }}\" picture_template: \"{{ user.data.profile_image_url }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » Twitter","id":"558","title":"Twitter"},"559":{"body":"Install OpenID Connect Provider extension in your XWiki instance. Synapse config: oidc_providers: - idp_id: xwiki idp_name: \"XWiki\" issuer: \"https://myxwikihost/xwiki/oidc/\" client_id: \"your-client-id\" # TO BE FILLED client_auth_method: none scopes: [\"openid\", \"profile\"] user_profile_method: \"userinfo_endpoint\" user_mapping_provider: config: localpart_template: \"{{ user.preferred_username }}\" display_name_template: \"{{ user.name }}\"","breadcrumbs":"Configuration » User Authentication » Single-Sign On » OpenID Connect » XWiki","id":"559","title":"XWiki"},"56":{"body":"The eturnal TURN server implementation is available from a variety of sources such as native package managers, binary packages, installation from source or container image . They are all described here . Quick-Test instructions in a Linux Shell or with Docker are available as well.","breadcrumbs":"Configuring a Turn Server » eturnal TURN server » Initial installation","id":"56","title":"Initial installation"},"560":{"body":"Synapse supports authenticating users via the Security Assertion Markup Language (SAML) protocol natively. Please see the saml2_config and sso sections of the Synapse configuration file for more details.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SAML » SAML","id":"560","title":"SAML"},"561":{"body":"Synapse supports authenticating users via the Central Authentication Service protocol (CAS) natively. Please see the cas_config and sso sections of the configuration manual for more details.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » CAS » CAS","id":"561","title":"CAS"},"562":{"body":"A mapping provider is a Python class (loaded via a Python module) that works out how to map attributes of a SSO response to Matrix-specific user attributes. Details such as user ID localpart, displayname, and even avatar URLs are all things that can be mapped from talking to a SSO service. As an example, a SSO service may return the email address \"john.smith@example.com\" for a user, whereas Synapse will need to figure out how to turn that into a displayname when creating a Matrix user for this individual. It may choose John Smith, or Smith, John [Example.com] or any number of variations. As each Synapse configuration may want something different, this is where SSO mapping providers come into play. SSO mapping providers are currently supported for OpenID and SAML SSO configurations. Please see the details below for how to implement your own. It is up to the mapping provider whether the user should be assigned a predefined Matrix ID based on the SSO attributes, or if the user should be allowed to choose their own username. In the first case - where users are automatically allocated a Matrix ID - it is the responsibility of the mapping provider to normalise the SSO attributes and map them to a valid Matrix ID. The specification for Matrix IDs has some information about what is considered valid. If the mapping provider does not assign a Matrix ID, then Synapse will automatically serve an HTML page allowing the user to pick their own username. External mapping providers are provided to Synapse in the form of an external Python module. You can retrieve this module from PyPI or elsewhere, but it must be importable via Synapse (e.g. it must be in the same virtualenv as Synapse). The Synapse config is then modified to point to the mapping provider (and optionally provide additional configuration for it).","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » SSO Mapping Providers","id":"562","title":"SSO Mapping Providers"},"563":{"body":"The OpenID mapping provider can be customized by editing the oidc_providers.user_mapping_provider.module config option. oidc_providers.user_mapping_provider.config allows you to provide custom configuration options to the module. Check with the module's documentation for what options it provides (if any). The options listed by default are for the user mapping provider built in to Synapse. If using a custom module, you should comment these options out and use those specified by the module instead.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » OpenID Mapping Providers","id":"563","title":"OpenID Mapping Providers"},"564":{"body":"A custom mapping provider must specify the following methods: def __init__(self, parsed_config, module_api) Arguments: parsed_config - A configuration object that is the return value of the parse_config method. You should set any configuration options needed by the module here. module_api - a synapse.module_api.ModuleApi object which provides the stable API available for extension modules. def parse_config(config) This method should have the @staticmethod decoration. Arguments: config - A dict representing the parsed content of the oidc_providers.user_mapping_provider.config homeserver config option. Runs on homeserver startup. Providers should extract and validate any option values they need here. Whatever is returned will be passed back to the user mapping provider module's __init__ method during construction. def get_remote_user_id(self, userinfo) Arguments: userinfo - A authlib.oidc.core.claims.UserInfo object to extract user information from. This method must return a string, which is the unique, immutable identifier for the user. Commonly the sub claim of the response. async def map_user_attributes(self, userinfo, token, failures) This method must be async. Arguments: userinfo - An authlib.oidc.core.claims.UserInfo object to extract user information from. token - A dictionary which includes information necessary to make further requests to the OpenID provider. failures - An int that represents the amount of times the returned mxid localpart mapping has failed. This should be used to create a deduplicated mxid localpart which should be returned instead. For example, if this method returns john.doe as the value of localpart in the returned dict, and that is already taken on the homeserver, this method will be called again with the same parameters but with failures=1. The method should then return a different localpart value, such as john.doe1. Returns a dictionary with two keys: localpart: A string, used to generate the Matrix ID. If this is None, the user is prompted to pick their own username. This is only used during a user's first login. Once a localpart has been associated with a remote user ID (see get_remote_user_id) it cannot be updated. confirm_localpart: A boolean. If set to True, when a localpart string is returned from this method, Synapse will prompt the user to either accept this localpart or pick their own username. Otherwise this option has no effect. If omitted, defaults to False. display_name: An optional string, the display name for the user. picture: An optional string, the avatar url for the user. emails: A list of strings, the email address(es) to associate with this user. If omitted, defaults to an empty list. async def get_extra_attributes(self, userinfo, token) This method must be async. Arguments: userinfo - A authlib.oidc.core.claims.UserInfo object to extract user information from. token - A dictionary which includes information necessary to make further requests to the OpenID provider. Returns a dictionary that is suitable to be serialized to JSON. This will be returned as part of the response during a successful login. Note that care should be taken to not overwrite any of the parameters usually returned as part of the login response .","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » Building a Custom OpenID Mapping Provider","id":"564","title":"Building a Custom OpenID Mapping Provider"},"565":{"body":"Synapse has a built-in OpenID mapping provider if a custom provider isn't specified in the config. It is located at synapse.handlers.oidc.JinjaOidcMappingProvider .","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » Default OpenID Mapping Provider","id":"565","title":"Default OpenID Mapping Provider"},"566":{"body":"The SAML mapping provider can be customized by editing the saml2_config.user_mapping_provider.module config option. saml2_config.user_mapping_provider.config allows you to provide custom configuration options to the module. Check with the module's documentation for what options it provides (if any). The options listed by default are for the user mapping provider built in to Synapse. If using a custom module, you should comment these options out and use those specified by the module instead.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » SAML Mapping Providers","id":"566","title":"SAML Mapping Providers"},"567":{"body":"A custom mapping provider must specify the following methods: def __init__(self, parsed_config, module_api) Arguments: parsed_config - A configuration object that is the return value of the parse_config method. You should set any configuration options needed by the module here. module_api - a synapse.module_api.ModuleApi object which provides the stable API available for extension modules. def parse_config(config) This method should have the @staticmethod decoration. Arguments: config - A dict representing the parsed content of the saml_config.user_mapping_provider.config homeserver config option. Runs on homeserver startup. Providers should extract and validate any option values they need here. Whatever is returned will be passed back to the user mapping provider module's __init__ method during construction. def get_saml_attributes(config) This method should have the @staticmethod decoration. Arguments: config - A object resulting from a call to parse_config. Returns a tuple of two sets. The first set equates to the SAML auth response attributes that are required for the module to function, whereas the second set consists of those attributes which can be used if available, but are not necessary. def get_remote_user_id(self, saml_response, client_redirect_url) Arguments: saml_response - A saml2.response.AuthnResponse object to extract user information from. client_redirect_url - A string, the URL that the client will be redirected to. This method must return a string, which is the unique, immutable identifier for the user. Commonly the uid claim of the response. def saml_response_to_user_attributes(self, saml_response, failures, client_redirect_url) Arguments: saml_response - A saml2.response.AuthnResponse object to extract user information from. failures - An int that represents the amount of times the returned mxid localpart mapping has failed. This should be used to create a deduplicated mxid localpart which should be returned instead. For example, if this method returns john.doe as the value of mxid_localpart in the returned dict, and that is already taken on the homeserver, this method will be called again with the same parameters but with failures=1. The method should then return a different mxid_localpart value, such as john.doe1. client_redirect_url - A string, the URL that the client will be redirected to. This method must return a dictionary, which will then be used by Synapse to build a new user. The following keys are allowed: mxid_localpart - A string, the mxid localpart of the new user. If this is None, the user is prompted to pick their own username. This is only used during a user's first login. Once a localpart has been associated with a remote user ID (see get_remote_user_id) it cannot be updated. displayname - The displayname of the new user. If not provided, will default to the value of mxid_localpart. emails - A list of emails for the new user. If not provided, will default to an empty list. Alternatively it can raise a synapse.api.errors.RedirectException to redirect the user to another page. This is useful to prompt the user for additional information, e.g. if you want them to provide their own username. It is the responsibility of the mapping provider to either redirect back to client_redirect_url (including any additional information) or to complete registration using methods from the ModuleApi.","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » Building a Custom SAML Mapping Provider","id":"567","title":"Building a Custom SAML Mapping Provider"},"568":{"body":"Synapse has a built-in SAML mapping provider if a custom provider isn't specified in the config. It is located at synapse.handlers.saml.DefaultSamlMappingProvider .","breadcrumbs":"Configuration » User Authentication » Single-Sign On » SSO Mapping Providers » Default SAML Mapping Provider","id":"568","title":"Default SAML Mapping Provider"},"569":{"body":"This page of the Synapse documentation is now deprecated. For up to date\ndocumentation on setting up or writing a password auth provider module, please see\nthis page. Password auth providers offer a way for server administrators to integrate their Synapse installation with an existing authentication system. A password auth provider is a Python class which is dynamically loaded into Synapse, and provides a number of methods by which it can integrate with the authentication system. This document serves as a reference for those looking to implement their own password auth providers. Additionally, here is a list of known password auth provider module implementations: matrix-synapse-ldap3 matrix-synapse-shared-secret-auth matrix-synapse-rest-password-provider","breadcrumbs":"Configuration » User Authentication » Password Auth Providers » Password auth provider modules","id":"569","title":"Password auth provider modules"},"57":{"body":"After installation, eturnal usually ships a default configuration file here: /etc/eturnal.yml (and, if not found there, there is a backup file here: /opt/eturnal/etc/eturnal.yml). It uses the (indentation-sensitive!) YAML format. The file contains further explanations. Here are some hints how to configure eturnal on your host machine or when using e.g. Docker . You may also further deep dive into the reference documentation . eturnal runs out of the box with the default configuration. To enable TURN and to integrate it with your homeserver, some aspects in eturnal's default configuration file must be edited: Homeserver's turn_shared_secret and eturnal's shared secret for authentication Both need to have the same value. Uncomment and adjust this line in eturnal's configuration file: secret: \"long-and-cryptic\" # Shared secret, CHANGE THIS. One way to generate a secret is with pwgen: pwgen -s 64 1 Public IP address If your TURN server is behind NAT, the NAT gateway must have an external, publicly-reachable IP address. eturnal tries to autodetect the public IP address, however, it may also be configured by uncommenting and adjusting this line, so eturnal advertises that address to connecting clients: relay_ipv4_addr: \"203.0.113.4\" # The server's public IPv4 address. If your NAT gateway is reachable over both IPv4 and IPv6, you may configure eturnal to advertise each available address: relay_ipv4_addr: \"203.0.113.4\" # The server's public IPv4 address.\nrelay_ipv6_addr: \"2001:db8::4\" # The server's public IPv6 address (optional). When advertising an external IPv6 address, ensure that the firewall and network settings of the system running your TURN server are configured to accept IPv6 traffic, and that the TURN server is listening on the local IPv6 address that is mapped by NAT to the external IPv6 address. Logging If eturnal was started by systemd, log files are written into the /var/log/eturnal directory by default. In order to log to the journal instead, the log_dir option can be set to stdout in the configuration file. Security considerations Consider your security settings. TURN lets users request a relay which will connect to arbitrary IP addresses and ports. The following configuration is suggested as a minimum starting point, see also the official documentation : ## Reject TURN relaying from/to the following addresses/networks:\nblacklist: # This is the default blacklist. - \"127.0.0.0/8\" # IPv4 loopback. - \"::1\" # IPv6 loopback. - recommended # Expands to a number of networks recommended to be # blocked, but includes private networks. Those # would have to be 'whitelist'ed if eturnal serves # local clients/peers within such networks. To whitelist IP addresses or specific (private) networks, you need to add a whitelist part into the configuration file, e.g.: whitelist: - \"192.168.0.0/16\" - \"203.0.113.113\" - \"2001:db8::/64\" The more specific, the better. TURNS (TURN via TLS/DTLS) Also consider supporting TLS/DTLS. To do this, adjust the following settings in the eturnal.yml configuration file (TLS parts should not be commented anymore): listen: - ip: \"::\" port: 3478 transport: udp - ip: \"::\" port: 3478 transport: tcp - ip: \"::\" port: 5349 transport: tls ## TLS certificate/key files (must be readable by 'eturnal' user!):\ntls_crt_file: /etc/eturnal/tls/crt.pem\ntls_key_file: /etc/eturnal/tls/key.pem In this case, replace the turn: schemes in homeserver's turn_uris settings with turns:. More is described here . We recommend that you only try to set up TLS/DTLS once you have set up a basic installation and got it working. NB: If your TLS certificate was provided by Let's Encrypt, TLS/DTLS will not work with any Matrix client that uses Chromium's WebRTC library. This currently includes Element Android & iOS; for more details, see their respective issues as well as the underlying WebRTC issue . Consider using a ZeroSSL certificate for your TURN server as a working alternative. Firewall Ensure your firewall allows traffic into the TURN server on the ports you've configured it to listen on (By default: 3478 and 5349 for TURN traffic (remember to allow both TCP and UDP traffic), and ports 49152-65535 for the UDP relay.) Reload/ restarting eturnal Changes in the configuration file require eturnal to reload/ restart, this can be achieved by: eturnalctl reload eturnal performs a configuration check before actually reloading/ restarting and provides hints, if something is not correctly configured.","breadcrumbs":"Configuring a Turn Server » eturnal TURN server » Configuration","id":"57","title":"Configuration"},"570":{"body":"Password auth provider classes must provide the following methods: parse_config(config) This method is passed the config object for this module from the homeserver configuration file. It should perform any appropriate sanity checks on the provided configuration, and return an object which is then passed into __init__. This method should have the @staticmethod decoration. __init__(self, config, account_handler) The constructor is passed the config object returned by parse_config, and a synapse.module_api.ModuleApi object which allows the password provider to check if accounts exist and/or create new ones.","breadcrumbs":"Configuration » User Authentication » Password Auth Providers » Required methods","id":"570","title":"Required methods"},"571":{"body":"Password auth provider classes may optionally provide the following methods: get_db_schema_files(self) This method, if implemented, should return an Iterable of (name, stream) pairs of database schema files. Each file is applied in turn at initialisation, and a record is then made in the database so that it is not re-applied on the next start. get_supported_login_types(self) This method, if implemented, should return a dict mapping from a login type identifier (such as m.login.password) to an iterable giving the fields which must be provided by the user in the submission to the /login API . These fields are passed in the login_dict dictionary to check_auth. For example, if a password auth provider wants to implement a custom login type of com.example.custom_login, where the client is expected to pass the fields secret1 and secret2, the provider should implement this method and return the following dict: {\"com.example.custom_login\": (\"secret1\", \"secret2\")} check_auth(self, username, login_type, login_dict) This method does the real work. If implemented, it will be called for each login attempt where the login type matches one of the keys returned by get_supported_login_types. It is passed the (possibly unqualified) user field provided by the client, the login type, and a dictionary of login secrets passed by the client. The method should return an Awaitable object, which resolves to the canonical @localpart:domain user ID if authentication is successful, and None if not. Alternatively, the Awaitable can resolve to a (str, func) tuple, in which case the second field is a callback which will be called with the result from the /login call (including access_token, device_id, etc.) check_3pid_auth(self, medium, address, password) This method, if implemented, is called when a user attempts to register or log in with a third party identifier, such as email. It is passed the medium (ex. \"email\"), an address (ex. \" jdoe@example.com \") and the user's password. The method should return an Awaitable object, which resolves to a str containing the user's (canonical) User id if authentication was successful, and None if not. As with check_auth, the Awaitable may alternatively resolve to a (user_id, callback) tuple. check_password(self, user_id, password) This method provides a simpler interface than get_supported_login_types and check_auth for password auth providers that just want to provide a mechanism for validating m.login.password logins. If implemented, it will be called to check logins with an m.login.password login type. It is passed a qualified @localpart:domain user id, and the password provided by the user. The method should return an Awaitable object, which resolves to True if authentication is successful, and False if not. on_logged_out(self, user_id, device_id, access_token) This method, if implemented, is called when a user logs out. It is passed the qualified user ID, the ID of the deactivated device (if any: access tokens are occasionally created without an associated device ID), and the (now deactivated) access token. It may return an Awaitable object; the logout request will wait for the Awaitable to complete, but the result is ignored.","breadcrumbs":"Configuration » User Authentication » Password Auth Providers » Optional methods","id":"571","title":"Optional methods"},"572":{"body":"Synapse comes with a non-standard login type to support JSON Web Tokens . In general the documentation for the login endpoint is still valid (and the mechanism works similarly to the token based login ). To log in using a JSON Web Token, clients should submit a /login request as follows: { \"type\": \"org.matrix.login.jwt\", \"token\": \"\"\n} The token field should include the JSON web token with the following claims: A claim that encodes the local part of the user ID is required. By default, the sub (subject) claim is used, or a custom claim can be set in the configuration file. The expiration time (exp), not before time (nbf), and issued at (iat) claims are optional, but validated if present. The issuer (iss) claim is optional, but required and validated if configured. The audience (aud) claim is optional, but required and validated if configured. Providing the audience claim when not configured will cause validation to fail. In the case that the token is not valid, the homeserver must respond with 403 Forbidden and an error code of M_FORBIDDEN. As with other login types, there are additional fields (e.g. device_id and initial_device_display_name) which can be included in the above request.","breadcrumbs":"Configuration » User Authentication » JSON Web Tokens » JWT Login Type","id":"572","title":"JWT Login Type"},"573":{"body":"The JSON Web Token integration in Synapse uses the Authlib library, which must be installed as follows: The relevant libraries are included in the Docker images and Debian packages provided by matrix.org so no further action is needed. If you installed Synapse into a virtualenv, run /path/to/env/bin/pip install synapse[jwt] to install the necessary dependencies. For other installation mechanisms, see the documentation provided by the maintainer. To enable the JSON web token integration, you should then add a jwt_config option to your configuration file. See the configuration manual for some sample settings.","breadcrumbs":"Configuration » User Authentication » JSON Web Tokens » Preparing Synapse","id":"573","title":"Preparing Synapse"},"574":{"body":"Although JSON Web Tokens are typically generated from an external server, the example below uses a locally generated JWT. Configure Synapse with JWT logins, note that this example uses a pre-shared secret and an algorithm of HS256: jwt_config: enabled: true secret: \"my-secret-token\" algorithm: \"HS256\" Generate a JSON web token: You can use the following short Python snippet to generate a JWT protected by an HMAC. Take care that the secret and the algorithm given in the header match the entries from jwt_config above. from authlib.jose import jwt header = {\"alg\": \"HS256\"}\npayload = {\"sub\": \"user1\", \"aud\": [\"audience\"]}\nsecret = \"my-secret-token\"\nresult = jwt.encode(header, payload, secret)\nprint(result.decode(\"ascii\")) Query for the login types and ensure org.matrix.login.jwt is there: curl http://localhost:8080/_matrix/client/r0/login Login used the generated JSON web token from above: $ curl http://localhost:8082/_matrix/client/r0/login -X POST \\ --data '{\"type\":\"org.matrix.login.jwt\",\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXVzZXIifQ.Ag71GT8v01UO3w80aqRPTeuVPBIBZkYhNTJJ-_-zQIc\"}'\n{ \"access_token\": \"\", \"device_id\": \"ACBDEFGHI\", \"home_server\": \"localhost:8080\", \"user_id\": \"@test-user:localhost:8480\"\n} You should now be able to use the returned access token to query the client API.","breadcrumbs":"Configuration » User Authentication » JSON Web Tokens » How to test JWT as a developer","id":"574","title":"How to test JWT as a developer"},"575":{"body":"Synapse supports refresh tokens since version 1.49 (some earlier versions had support for an earlier, experimental draft of MSC2918 which is not compatible).","breadcrumbs":"Configuration » User Authentication » Refresh Tokens » Refresh Tokens","id":"575","title":"Refresh Tokens"},"576":{"body":"Synapse users' sessions are identified by access tokens ; access tokens are issued to users on login. Each session gets a unique access token which identifies it; the access token must be kept secret as it grants access to the user's account. Traditionally, these access tokens were eternally valid (at least until the user explicitly chose to log out). In some cases, it may be desirable for these access tokens to expire so that the potential damage caused by leaking an access token is reduced. On the other hand, forcing a user to re-authenticate (log in again) often might be too much of an inconvenience. Refresh tokens are a mechanism to avoid some of this inconvenience whilst still getting most of the benefits of short access token lifetimes. Refresh tokens are also a concept present in OAuth 2 — further reading is available here . When refresh tokens are in use, both an access token and a refresh token will be issued to users on login. The access token will expire after a predetermined amount of time, but otherwise works in the same way as before. When the access token is close to expiring (or has expired), the user's client should present the homeserver (Synapse) with the refresh token. The homeserver will then generate a new access token and refresh token for the user and return them. The old refresh token is invalidated and can not be used again*. Finally, refresh tokens also make it possible for sessions to be logged out if they are inactive for too long, before the session naturally ends; see the configuration guide below. *To prevent issues if clients lose connection half-way through refreshing a token, the refresh token is only invalidated once the new access token has been used at least once. For all intents and purposes, the above simplification is sufficient.","breadcrumbs":"Configuration » User Authentication » Refresh Tokens » Background and motivation","id":"576","title":"Background and motivation"},"577":{"body":"There are some caveats: If a third party gets both your access token and refresh token, they will be able to continue to enjoy access to your session. This is still an improvement because you (the user) will notice when your session expires and you're not able to use your refresh token. That would be a giveaway that someone else has compromised your session. You would be able to log in again and terminate that session. Previously (with long-lived access tokens), a third party that has your access token could go undetected for a very long time. Clients need to implement support for refresh tokens in order for them to be a useful mechanism. It is up to homeserver administrators if they want to issue long-lived access tokens to clients not implementing refresh tokens. For compatibility, it is likely that they should, at least until client support is widespread. Users with clients that support refresh tokens will still benefit from the added security; it's not possible to downgrade a session to using long-lived access tokens so this effectively gives users the choice. In a closed environment where all users use known clients, this may not be an issue as the homeserver administrator can know if the clients have refresh token support. In that case, the non-refreshable access token lifetime may be set to a short duration so that a similar level of security is provided.","breadcrumbs":"Configuration » User Authentication » Refresh Tokens » Caveats","id":"577","title":"Caveats"},"578":{"body":"The following configuration options, in the registration section, are related: session_lifetime: maximum length of a session, even if it's refreshed. In other words, the client must log in again after this time period. In most cases, this can be unset (infinite) or set to a long time (years or months). refreshable_access_token_lifetime: lifetime of access tokens that are created by clients supporting refresh tokens. This should be short; a good value might be 5 minutes (5m). nonrefreshable_access_token_lifetime: lifetime of access tokens that are created by clients which don't support refresh tokens. Make this short if you want to effectively force use of refresh tokens. Make this long if you don't want to inconvenience users of clients which don't support refresh tokens (by forcing them to frequently re-authenticate using login credentials). refresh_token_lifetime: lifetime of refresh tokens. In other words, the client must refresh within this time period to maintain its session. Unless you want to log inactive sessions out, it is often fine to use a long value here or even leave it unset (infinite). Beware that making it too short will inconvenience clients that do not connect very often, including mobile clients and clients of infrequent users (by making it more difficult for them to refresh in time, which may force them to need to re-authenticate using login credentials). Note: All four options above only apply when tokens are created (by logging in or refreshing). Changes to these settings do not apply retroactively.","breadcrumbs":"Configuration » User Authentication » Refresh Tokens » Configuration Guide","id":"578","title":"Configuration Guide"},"579":{"body":"If you'd like to force sessions to be logged out upon inactivity, you can enable refreshable access token expiry and refresh token expiry. This works because a client must refresh at least once within a period of refresh_token_lifetime in order to maintain valid credentials to access the account. (It's suggested that refresh_token_lifetime should be longer than refreshable_access_token_lifetime and this section assumes that to be the case for simplicity.) Note: this will only affect sessions using refresh tokens. You may wish to set a short nonrefreshable_access_token_lifetime to prevent this being bypassed by clients that do not support refresh tokens. Choosing values that guarantee permitting some inactivity It may be desirable to permit some short periods of inactivity, for example to accommodate brief outages in client connectivity. The following model aims to provide guidance for choosing refresh_token_lifetime and refreshable_access_token_lifetime to satisfy requirements of the form: inactivity longer than L MUST cause the session to be logged out; and inactivity shorter than S MUST NOT cause the session to be logged out. This model makes the weakest assumption that all active clients will refresh as needed to maintain an active access token, but no sooner. In reality, clients may refresh more often than this model assumes, but the above requirements will still hold. To satisfy the above model, refresh_token_lifetime should be set to L; and refreshable_access_token_lifetime should be set to L - S.","breadcrumbs":"Configuration » User Authentication » Refresh Tokens » Using refresh token expiry to log out inactive sessions","id":"579","title":"Using refresh token expiry to log out inactive sessions"},"58":{"body":"eturnal offers a handy operations script which can be called e.g. to check, whether the service is up, to restart the service, to query how many active sessions exist, to change logging behaviour and so on. Hint: If eturnalctl is not part of your $PATH, consider either sym-linking it (e.g. ´ln -s /opt/eturnal/bin/eturnalctl /usr/local/bin/eturnalctl´) or call it from the default eturnal directory directly: e.g. /opt/eturnal/bin/eturnalctl info","breadcrumbs":"Configuring a Turn Server » eturnal TURN server » eturnalctl opterations script","id":"58","title":"eturnalctl opterations script"},"580":{"body":"A captcha can be enabled on your homeserver to help prevent bots from registering accounts. Synapse currently uses Google's reCAPTCHA service which requires API keys from Google.","breadcrumbs":"Configuration » Registration Captcha » Overview","id":"580","title":"Overview"},"581":{"body":"Create a new site at https://www.google.com/recaptcha/admin/create Set the label to anything you want Set the type to reCAPTCHA v2 using the \"I'm not a robot\" Checkbox option. This is the only type of captcha that works with Synapse. Add the public hostname for your server, as set in public_baseurl in homeserver.yaml, to the list of authorized domains. If you have not set public_baseurl, use server_name. Agree to the terms of service and submit. Copy your site key and secret key and add them to your homeserver.yaml configuration file recaptcha_public_key: YOUR_SITE_KEY\nrecaptcha_private_key: YOUR_SECRET_KEY Enable the CAPTCHA for new registrations enable_registration_captcha: true Go to the settings page for the CAPTCHA you just created Uncheck the \"Verify the origin of reCAPTCHA solutions\" checkbox so that the captcha can be displayed in any client. If you do not disable this option then you must specify the domains of every client that is allowed to display the CAPTCHA.","breadcrumbs":"Configuration » Registration Captcha » Getting API keys","id":"581","title":"Getting API keys"},"582":{"body":"The reCAPTCHA API requires that the IP address of the user who solved the CAPTCHA is sent. If the client is connecting through a proxy or load balancer, it may be required to use the X-Forwarded-For (XFF) header instead of the origin IP address. This can be configured using the x_forwarded directive in the listeners section of the homeserver.yaml configuration file.","breadcrumbs":"Configuration » Registration Captcha » Configuring IP used for auth","id":"582","title":"Configuring IP used for auth"},"583":{"body":"The registration of new application services depends on the homeserver used. In synapse, you need to create a new configuration file for your AS and add it to the list specified under the app_service_config_files config option in your synapse config. For example: app_service_config_files:\n- /home/matrix/.synapse/.yaml The format of the AS configuration file is as follows: id: \nurl: \nas_token: \nhs_token: \nsender_localpart: \nnamespaces: users: # List of users we're interested in - exclusive: regex: group_id: - ... aliases: [] # List of aliases we're interested in rooms: [] # List of room ids we're interested in exclusive: If enabled, only this application service is allowed to register users in its namespace(s). group_id: All users of this application service are dynamically joined to this group. This is useful for e.g user organisation or flairs. See the spec for further details on how application services work.","breadcrumbs":"Configuration » Application Services » Registering an Application Service","id":"583","title":"Registering an Application Service"},"584":{"body":"'Server Notices' are a new feature introduced in Synapse 0.30. They provide a channel whereby server administrators can send messages to users on the server. They are used as part of communication of the server polices (see Consent Tracking ), however the intention is that they may also find a use for features such as \"Message of the day\". This is a feature specific to Synapse, but it uses standard Matrix communication mechanisms, so should work with any Matrix client.","breadcrumbs":"Configuration » Server Notices » Server Notices","id":"584","title":"Server Notices"},"585":{"body":"When the user is first sent a server notice, they will get an invitation to a room (typically called 'Server Notices', though this is configurable in homeserver.yaml). They will be unable to reject this invitation - attempts to do so will receive an error. Once they accept the invitation, they will see the notice message in the room history; it will appear to have come from the 'server notices user' (see below). The user is prevented from sending any messages in this room by the power levels. Having joined the room, the user can leave the room if they want. Subsequent server notices will then cause a new room to be created.","breadcrumbs":"Configuration » Server Notices » User experience","id":"585","title":"User experience"},"586":{"body":"Server notices come from a specific user id on the server. Server administrators are free to choose the user id - something like server is suggested, meaning the notices will come from @server:. Once the Server Notices user is configured, that user id becomes a special, privileged user, so administrators should ensure that it is not already allocated . In order to support server notices, it is necessary to add some configuration to the homeserver.yaml file. In particular, you should add a server_notices section, which should look like this: server_notices: system_mxid_localpart: server system_mxid_display_name: \"Server Notices\" system_mxid_avatar_url: \"mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ\" room_name: \"Server Notices\" room_avatar_url: \"mxc://example.com/oumMVlgDnLYFaPVkExemNVVZ\" room_topic: \"Room used by your server admin to notice you of important information\" auto_join: true The only compulsory setting is system_mxid_localpart, which defines the user id of the Server Notices user, as above. room_name defines the name of the room which will be created, room_avatar_url its avatar and room_topic its topic. system_mxid_display_name and system_mxid_avatar_url can be used to set the displayname and avatar of the Server Notices user. auto_join will autojoin users to the notices room instead of sending an invite.","breadcrumbs":"Configuration » Server Notices » Synapse configuration","id":"586","title":"Synapse configuration"},"587":{"body":"To send server notices to users you can use the admin_api .","breadcrumbs":"Configuration » Server Notices » Sending notices","id":"587","title":"Sending notices"},"588":{"body":"Synapse 0.30 introduces support for tracking whether users have agreed to the terms and conditions set by the administrator of a server - and blocking access to the server until they have. There are several parts to this functionality; each requires some specific configuration in homeserver.yaml to be enabled. Note that various parts of the configuration and this document refer to the \"privacy policy\": agreement with a privacy policy is one particular use of this feature, but of course administrators can specify other terms and conditions unrelated to \"privacy\" per se.","breadcrumbs":"Configuration » Consent Tracking » Support in Synapse for tracking agreement to server terms and conditions","id":"588","title":"Support in Synapse for tracking agreement to server terms and conditions"},"589":{"body":"Synapse can be configured to serve the user a simple policy form with an \"accept\" button. Clicking \"Accept\" records the user's acceptance in the database and shows a success page. To enable this, first create templates for the policy and success pages. These should be stored on the local filesystem. These templates use the Jinja2 templating language, and docs/privacy_policy_templates gives examples of the sort of thing that can be done. Note that the templates must be stored under a name giving the language of the template - currently this must always be en (for \"English\"); internationalisation support is intended for the future. The template for the policy itself should be versioned and named according to the version: for example 1.0.html. The version of the policy which the user has agreed to is stored in the database. Once the templates are in place, make the following changes to homeserver.yaml: Add a user_consent section, which should look like: user_consent: template_dir: privacy_policy_templates version: 1.0 template_dir points to the directory containing the policy templates. version defines the version of the policy which will be served to the user. In the example above, Synapse will serve privacy_policy_templates/en/1.0.html. Add a form_secret setting at the top level: form_secret: \"\" This should be set to an arbitrary secret string (try pwgen -y 30 to generate suitable secrets). More on what this is used for below. Add consent wherever the client resource is currently enabled in the listeners configuration. For example: listeners: - port: 8008 resources: - names: - client - consent Finally, ensure that jinja2 is installed. If you are using a virtualenv, this should be a matter of pip install Jinja2. On debian, try apt-get install python-jinja2. Once this is complete, and the server has been restarted, try visiting https:///_matrix/consent. If correctly configured, this should give an error \"Missing string query parameter 'u'\". It is now possible to manually construct URIs where users can give their consent.","breadcrumbs":"Configuration » Consent Tracking » Collecting policy agreement from a user","id":"589","title":"Collecting policy agreement from a user"},"59":{"body":"In the following documentation, we use the term server_name to refer to that setting in your homeserver configuration file. It appears at the ends of user ids, and tells other homeservers where they can find your server. By default, other homeservers will expect to be able to reach yours via your server_name, on port 8448. For example, if you set your server_name to example.com (so that your user names look like @user:example.com), other servers will try to connect to yours at https://example.com:8448/. Delegation is a Matrix feature allowing a homeserver admin to retain a server_name of example.com so that user IDs, room aliases, etc continue to look like *:example.com, whilst having federation traffic routed to a different server and/or port (e.g. synapse.example.com:443).","breadcrumbs":"Delegation » Delegation of incoming federation traffic","id":"59","title":"Delegation of incoming federation traffic"},"590":{"body":"Add the following to your configuration: user_consent: require_at_registration: true policy_name: \"Privacy Policy\" # or whatever you'd like to call the policy In your consent templates, make use of the public_version variable to see if an unauthenticated user is viewing the page. This is typically wrapped around the form that would be used to actually agree to the document: {% if not public_version %} \n{% endif %} Restart Synapse to apply the changes. Visiting https:///_matrix/consent should now give you a view of the privacy document. This is what users will be able to see when registering for accounts.","breadcrumbs":"Configuration » Consent Tracking » Enabling consent tracking at registration","id":"590","title":"Enabling consent tracking at registration"},"591":{"body":"It may be useful to manually construct the \"consent URI\" for a given user - for instance, in order to send them an email asking them to consent. To do this, take the base https:///_matrix/consent URL and add the following query parameters: u: the user id of the user. This can either be a full MXID (@user:server.com) or just the localpart (user). h: hex-encoded HMAC-SHA256 of u using the form_secret as a key. It is possible to calculate this on the commandline with something like: echo -n '' | openssl sha256 -hmac '' This should result in a URI which looks something like: https:///_matrix/consent?u=&h=68a152465a4d.... Note that not providing a u parameter will be interpreted as wanting to view the document from an unauthenticated perspective, such as prior to registration. Therefore, the h parameter is not required in this scenario. To enable this behaviour, set require_at_registration to true in your user_consent config.","breadcrumbs":"Configuration » Consent Tracking » Constructing the consent URI","id":"591","title":"Constructing the consent URI"},"592":{"body":"It is possible to configure Synapse to send a server notice to anybody who has not yet agreed to the current version of the policy. To do so: ensure that the consent resource is configured, as in the previous section ensure that server notices are configured, as in the server notice documentation . Add server_notice_content under user_consent in homeserver.yaml. For example: user_consent: server_notice_content: msgtype: m.text body: >- Please give your consent to the privacy policy at %(consent_uri)s. Synapse automatically replaces the placeholder %(consent_uri)s with the consent uri for that user. ensure that public_baseurl is set in homeserver.yaml, and gives the base URI that clients use to connect to the server. (It is used to construct consent_uri in the server notice.)","breadcrumbs":"Configuration » Consent Tracking » Sending users a server notice asking them to agree to the policy","id":"592","title":"Sending users a server notice asking them to agree to the policy"},"593":{"body":"Synapse can be configured to block any attempts to join rooms or send messages until the user has given their agreement to the policy. (Joining the server notices room is exempted from this). To enable this, add block_events_error under user_consent. For example: user_consent: block_events_error: >- You can't send any messages until you consent to the privacy policy at %(consent_uri)s. Synapse automatically replaces the placeholder %(consent_uri)s with the consent uri for that user. ensure that public_baseurl is set in homeserver.yaml, and gives the base URI that clients use to connect to the server. (It is used to construct consent_uri in the error.)","breadcrumbs":"Configuration » Consent Tracking » Blocking users from using the server until they agree to the policy","id":"593","title":"Blocking users from using the server until they agree to the policy"},"594":{"body":"The user directory is maintained based on users that are 'visible' to the homeserver - i.e. ones which are local to the server and ones which any local user shares a room with. The directory info is stored in various tables, which can sometimes get out of sync (although this is considered a bug). If this happens, for now the solution to fix it is to use the admin API and execute the job regenerate_directory. This should then start a background task to flush the current tables and regenerate the directory. Depending on the size of your homeserver (number of users and rooms) this can take a while.","breadcrumbs":"Configuration » User Directory » User Directory API Implementation","id":"594","title":"User Directory API Implementation"},"595":{"body":"There are five relevant tables that collectively form the \"user directory\". Three of them track a list of all known users. The last two (collectively called the \"search tables\") track which users are visible to each other. From all of these tables we exclude three types of local user: support users appservice users deactivated users A description of each table follows: user_directory. This contains the user ID, display name and avatar of each user. Because there is only one directory entry per user, it is important that it only contain publicly visible information. Otherwise, this will leak the nickname or avatar used in a private room. Indexed on rooms. Indexed on users. user_directory_search. To be joined to user_directory. It contains an extra column that enables full text search based on user IDs and display names. Different schemas for SQLite and Postgres are used. Indexed on the full text search data. Indexed on users. user_directory_stream_pos. When the initial background update to populate the directory is complete, we record a stream position here. This indicates that synapse should now listen for room changes and incrementally update the directory where necessary. (See stream positions .) users_in_public_rooms. Contains associations between users and the public rooms they're in. Used to determine which users are in public rooms and should be publicly visible in the directory. Both local and remote users are tracked. users_who_share_private_rooms. Rows are triples (L, M, room id) where L is a local user and M is a local or remote user. L and M should be different, but this isn't enforced by a constraint. Note that if two local users share a room then there will be two entries: (user1, user2, !room_id) and (user2, user1, !room_id).","breadcrumbs":"Configuration » User Directory » Data model","id":"595","title":"Data model"},"596":{"body":"The exact way user search works can be tweaked via some server-level configuration options . The information is not repeated here, but the options are mentioned below.","breadcrumbs":"Configuration » User Directory » Configuration options","id":"596","title":"Configuration options"},"597":{"body":"If search_all_users is false, then results are limited to users who: Are found in the users_in_public_rooms table, or Are found in the users_who_share_private_rooms where L is the requesting user and M is the search result. Otherwise, if search_all_users is true, no such limits are placed and all users known to the server (matching the search query) will be returned. By default, locked users are not returned. If show_locked_users is true then no filtering on the locked status of a user is done. The user provided search term is lowercased and normalized using NFKC , this treats the string as case-insensitive, canonicalizes different forms of the same text, and maps some \"roughly equivalent\" characters together. The search term is then split into words: If ICU is available, then the system's default locale will be used to break the search term into words. (See the installation instructions for how to install ICU.) If unavailable, then runs of ASCII characters, numbers, underscores, and hyphens are considered words. The queries for PostgreSQL and SQLite are detailed below, but their overall goal is to find matching users, preferring users who are \"real\" (e.g. not bots, not deactivated). It is assumed that real users will have a display name and avatar set.","breadcrumbs":"Configuration » User Directory » Search algorithm","id":"597","title":"Search algorithm"},"598":{"body":"The above words are then transformed into two queries: \"exact\" which matches the parsed words exactly (using to_tsquery ); \"prefix\" which matches the parsed words as prefixes (using to_tsquery). Results are composed of all rows in the user_directory_search table whose information matches one (or both) of these queries. Results are ordered by calculating a weighted score for each result, higher scores are returned first: 4x if a user ID exists. 1.2x if the user has a display name set. 1.2x if the user has an avatar set. 0x-3x by the full text search results using the ts_rank_cd function against the \"exact\" search query; this has four variables with the following weightings: D: 0.1 for the user ID's domain C: 0.1 for unused B: 0.9 for the user's display name (or an empty string if it is not set) A: 0.1 for the user ID's localpart 0x-1x by the full text search results using the ts_rank_cd function against the \"prefix\" search query. (Using the same weightings as above.) If prefer_local_users is true, then 2x if the user is local to the homeserver. Note that ts_rank_cd returns a weight between 0 and 1. The initial weighting of all results is 1.","breadcrumbs":"Configuration » User Directory » PostgreSQL","id":"598","title":"PostgreSQL"},"599":{"body":"Results are composed of all rows in the user_directory_search whose information matches the query. Results are ordered by the following information, with each subsequent column used as a tiebreaker, for each result: By the rank of the full text search results using the matchinfo function . Higher ranks are returned first. If prefer_local_users is true, then users local to the homeserver are returned first. Users with a display name set are returned first. Users with an avatar set are returned first.","breadcrumbs":"Configuration » User Directory » SQLite","id":"599","title":"SQLite"},"6":{"body":"","breadcrumbs":"Installation » Installing Synapse","id":"6","title":"Installing Synapse"},"60":{"body":"To use this method, you need to be able to configure the server at https:// to serve a file at https:///.well-known/matrix/server. There are two ways to do this, shown below. Note that the .well-known file is hosted on the default port for https (port 443).","breadcrumbs":"Delegation » .well-known delegation","id":"60","title":".well-known delegation"},"600":{"body":"Synapse admins can enable support for message retention policies on their homeserver. Message retention policies exist at a room level, follow the semantics described in MSC1763 , and allow server and room admins to configure how long messages should be kept in a homeserver's database before being purged from it. Please note that, as this feature isn't part of the Matrix specification yet, the use of m.room.retention events for per-room retention policies is to be considered as experimental. However, the use of a default message retention policy is considered a stable feature in Synapse. A message retention policy is mainly defined by its max_lifetime parameter, which defines how long a message can be kept around after it was sent to the room. If a room doesn't have a message retention policy, and there's no default one for a given server, then no message sent in that room is ever purged on that server. MSC1763 also specifies semantics for a min_lifetime parameter which defines the amount of time after which an event can get purged (after it was sent to the room), but Synapse doesn't currently support it beyond registering it. Both max_lifetime and min_lifetime are optional parameters. Note that message retention policies don't apply to state events. Once an event reaches its expiry date (defined as the time it was sent plus the value for max_lifetime in the room), two things happen: Synapse stops serving the event to clients via any endpoint. The message gets picked up by the next purge job (see the \"Purge jobs\" section) and is removed from Synapse's database. Since purge jobs don't run continuously, this means that an event might stay in a server's database for longer than the value for max_lifetime in the room would allow, though hidden from clients. Similarly, if a server (with support for message retention policies enabled) receives from another server an event that should have been purged according to its room's policy, then the receiving server will process and store that event until it's picked up by the next purge job, though it will always hide it from clients. Synapse requires at least one message in each room, so it will never delete the last message in a room. It will, however, hide it from clients.","breadcrumbs":"Configuration » Message Retention Policies » Message retention policies","id":"600","title":"Message retention policies"},"601":{"body":"Support for this feature can be enabled and configured by adding the retention option in the Synapse configuration file (see configuration manual ). To enable support for message retention policies, set the setting enabled in this section to true.","breadcrumbs":"Configuration » Message Retention Policies » Server configuration","id":"601","title":"Server configuration"},"602":{"body":"A default message retention policy is a policy defined in Synapse's configuration that is used by Synapse for every room that doesn't have a message retention policy configured in its state. This allows server admins to ensure that messages are never kept indefinitely in a server's database. A default policy can be defined as such, by adding the retention option in the configuration file and adding these sub-options: default_policy: min_lifetime: 1d max_lifetime: 1y Here, min_lifetime and max_lifetime have the same meaning and level of support as previously described. They can be expressed either as a duration (using the units s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years)) or as a number of milliseconds.","breadcrumbs":"Configuration » Message Retention Policies » Default policy","id":"602","title":"Default policy"},"603":{"body":"Purge jobs are the jobs that Synapse runs in the background to purge expired events from the database. They are only run if support for message retention policies is enabled in the server's configuration. If no configuration for purge jobs is configured by the server admin, Synapse will use a default configuration, which is described here in the configuration manual . Some server admins might want a finer control on when events are removed depending on an event's room's policy. This can be done by setting the purge_jobs sub-section in the retention section of the configuration file. An example of such configuration could be: purge_jobs: - longest_max_lifetime: 3d interval: 12h - shortest_max_lifetime: 3d longest_max_lifetime: 1w interval: 1d - shortest_max_lifetime: 1w interval: 2d In this example, we define three jobs: one that runs twice a day (every 12 hours) and purges events in rooms which policy's max_lifetime is lower or equal to 3 days. one that runs once a day and purges events in rooms which policy's max_lifetime is between 3 days and a week. one that runs once every 2 days and purges events in rooms which policy's max_lifetime is greater than a week. Note that this example is tailored to show different configurations and features slightly more jobs than is probably necessary (in practice, a server admin would probably consider it better to replace the two last jobs with one that runs once a day and handles rooms which policy's max_lifetime is greater than 3 days). Keep in mind, when configuring these jobs, that a purge job can become quite heavy on the server if it targets many rooms, therefore prefer having jobs with a low interval that target a limited set of rooms. Also make sure to include a job with no minimum and one with no maximum to make sure your configuration handles every policy. As previously mentioned in this documentation, while a purge job that runs e.g. every day means that an expired event might stay in the database for up to a day after its expiry, Synapse hides expired events from clients as soon as they expire, so the event is not visible to local users between its expiry date and the moment it gets purged from the server's database.","breadcrumbs":"Configuration » Message Retention Policies » Purge jobs","id":"603","title":"Purge jobs"},"604":{"body":"Server admins can set limits on the values of max_lifetime to use when purging old events in a room. These limits can be defined under the retention option in the configuration file: allowed_lifetime_min: 1d\nallowed_lifetime_max: 1y The limits are considered when running purge jobs. If necessary, the effective value of max_lifetime will be brought between allowed_lifetime_min and allowed_lifetime_max (inclusive). This means that, if the value of max_lifetime defined in the room's state is lower than allowed_lifetime_min, the value of allowed_lifetime_min will be used instead. Likewise, if the value of max_lifetime is higher than allowed_lifetime_max, the value of allowed_lifetime_max will be used instead. In the example above, we ensure Synapse never deletes events that are less than one day old, and that it always deletes events that are over a year old. If a default policy is set, and its max_lifetime value is lower than allowed_lifetime_min or higher than allowed_lifetime_max, the same process applies. Both parameters are optional; if one is omitted Synapse won't use it to adjust the effective value of max_lifetime. Like other settings in this section, these parameters can be expressed either as a duration or as a number of milliseconds.","breadcrumbs":"Configuration » Message Retention Policies » Lifetime limits","id":"604","title":"Lifetime limits"},"605":{"body":"To configure a room's message retention policy, a room's admin or moderator needs to send a state event in that room with the type m.room.retention and the following content: { \"max_lifetime\": ...\n} In this event's content, the max_lifetime parameter has the same meaning as previously described, and needs to be expressed in milliseconds. The event's content can also include a min_lifetime parameter, which has the same meaning and limited support as previously described. Note that over every server in the room, only the ones with support for message retention policies will actually remove expired events. This support is currently not enabled by default in Synapse.","breadcrumbs":"Configuration » Message Retention Policies » Room configuration","id":"605","title":"Room configuration"},"606":{"body":"While purge jobs actually delete data from the database, the disk space used by the database might not decrease immediately on the database's host. However, even though the database engine won't free up the disk space, it will start writing new data into where the purged data was. If you want to reclaim the freed disk space anyway and return it to the operating system, the server admin needs to run VACUUM FULL; (or VACUUM; for SQLite databases) on Synapse's database (see the related PostgreSQL documentation ).","breadcrumbs":"Configuration » Message Retention Policies » Note on reclaiming disk space","id":"606","title":"Note on reclaiming disk space"},"607":{"body":"Synapse supports extending its functionality by configuring external modules. Note : When using third-party modules, you effectively allow someone else to run custom code on your Synapse homeserver. Server admins are encouraged to verify the provenance of the modules they use on their homeserver and make sure the modules aren't running malicious code on their instance.","breadcrumbs":"Configuration » Pluggable Modules » Modules","id":"607","title":"Modules"},"608":{"body":"To use a module on Synapse, add it to the modules section of the configuration file: modules: - module: my_super_module.MySuperClass config: do_thing: true - module: my_other_super_module.SomeClass config: {} Each module is defined by a path to a Python class as well as a configuration. This information for a given module should be available in the module's own documentation.","breadcrumbs":"Configuration » Pluggable Modules » Using modules","id":"608","title":"Using modules"},"609":{"body":"The order in which modules are listed in this section is important. When processing an action that can be handled by several modules, Synapse will always prioritise the module that appears first (i.e. is the highest in the list). This means: If several modules register the same callback, the callback registered by the module that appears first is used. If several modules try to register a handler for the same HTTP path, only the handler registered by the module that appears first is used. Handlers registered by the other module(s) are ignored and Synapse will log a warning message about them. Note that Synapse doesn't allow multiple modules implementing authentication checkers via the password auth provider feature for the same login type with different fields. If this happens, Synapse will refuse to start.","breadcrumbs":"Configuration » Pluggable Modules » Using multiple modules","id":"609","title":"Using multiple modules"},"61":{"body":"For maximum flexibility, you need to configure an external server such as nginx, Apache or HAProxy to serve the https:///.well-known/matrix/server file. Setting up such a server is out of the scope of this documentation, but note that it is often possible to configure your reverse proxy for this. The URL https:///.well-known/matrix/server should be configured return a JSON structure containing the key m.server like this: { \"m.server\": \"[:]\"\n} In our example (where we want federation traffic to be routed to https://synapse.example.com, on port 443), this would mean that https://example.com/.well-known/matrix/server should return: { \"m.server\": \"synapse.example.com:443\"\n} Note, specifying a port is optional. If no port is specified, then it defaults to 8448.","breadcrumbs":"Delegation » External server","id":"61","title":"External server"},"610":{"body":"We are currently in the process of migrating module interfaces to this system. While some interfaces might be compatible with it, others still require configuring modules in another part of Synapse's configuration file. Currently, only the following pre-existing interfaces are compatible with this new system: spam checker third-party rules presence router password auth providers","breadcrumbs":"Configuration » Pluggable Modules » Current status","id":"610","title":"Current status"},"611":{"body":"A module is a Python class that uses Synapse's module API to interact with the homeserver. It can register callbacks that Synapse will call on specific operations, as well as web resources to attach to Synapse's web server. When instantiated, a module is given its parsed configuration as well as an instance of the synapse.module_api.ModuleApi class. The configuration is a dictionary, and is either the output of the module's parse_config static method (see below), or the configuration associated with the module in Synapse's configuration file. See the documentation for the ModuleApi class here .","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Writing a module","id":"611","title":"Writing a module"},"612":{"body":"If Synapse is running with other modules configured, the order each module appears in within the modules section of the Synapse configuration file might restrict what it can or cannot register. See this section for more information. On top of the rules listed in the link above, if a callback returns a value that should cause the current operation to fail (e.g. if a callback checking an event returns with a value that should cause the event to be denied), Synapse will fail the operation and ignore any subsequent callbacks that should have been run after this one. The documentation for each callback mentions how Synapse behaves when multiple modules implement it.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » When Synapse runs with several modules configured","id":"612","title":"When Synapse runs with several modules configured"},"613":{"body":"A module can implement the following static method: @staticmethod\ndef parse_config(config: dict) -> Any This method is given a dictionary resulting from parsing the YAML configuration for the module. It may modify it (for example by parsing durations expressed as strings (e.g. \"5d\") into milliseconds, etc.), and return the modified dictionary. It may also verify that the configuration is correct, and raise an instance of synapse.module_api.errors.ConfigError if not.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Handling the module's configuration","id":"613","title":"Handling the module's configuration"},"614":{"body":"Modules can register web resources onto Synapse's web server using the following module API method: def ModuleApi.register_web_resource(path: str, resource: IResource) -> None The path is the full absolute path to register the resource at. For example, if you register a resource for the path /_synapse/client/my_super_module/say_hello, Synapse will serve it at http(s)://[HS_URL]/_synapse/client/my_super_module/say_hello. Note that Synapse does not allow registering resources for several sub-paths in the /_matrix namespace (such as anything under /_matrix/client for example). It is strongly recommended that modules register their web resources under the /_synapse/client namespace. The provided resource is a Python class that implements Twisted's IResource interface (such as Resource ). Only one resource can be registered for a given path. If several modules attempt to register a resource for the same path, the module that appears first in Synapse's configuration file takes priority. Modules must register their web resources in their __init__ method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Registering a web resource","id":"614","title":"Registering a web resource"},"615":{"body":"Modules can use Synapse's module API to register callbacks. Callbacks are functions that Synapse will call when performing specific actions. Callbacks must be asynchronous (unless specified otherwise), and are split in categories. A single module may implement callbacks from multiple categories, and is under no obligation to implement all callbacks from the categories it registers callbacks for. Modules can register callbacks using one of the module API's register_[...]_callbacks methods. The callback functions are passed to these methods as keyword arguments, with the callback name as the argument name and the function as its value. A register_[...]_callbacks method exists for each category. Callbacks for each category can be found on their respective page of the Synapse documentation website .","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Registering a callback","id":"615","title":"Registering a callback"},"616":{"body":"Added in Synapse 1.74.0. Modules can leverage Synapse's caching tools to manage their own cached functions. This can be helpful for modules that need to repeatedly request the same data from the database or a remote service. Functions that need to be wrapped with a cache need to be decorated with a @cached() decorator (which can be imported from synapse.module_api) and registered with the ModuleApi.register_cached_function API when initialising the module. If the module needs to invalidate an entry in a cache, it needs to use the ModuleApi.invalidate_cache API, with the function to invalidate the cache of and the key(s) of the entry to invalidate. Below is an example of a simple module using a cached function: from typing import Any\nfrom synapse.module_api import cached, ModuleApi class MyModule: def __init__(self, config: Any, api: ModuleApi): self.api = api # Register the cached function so Synapse knows how to correctly invalidate # entries for it. self.api.register_cached_function(self.get_user_from_id) @cached() async def get_department_for_user(self, user_id: str) -> str: \"\"\"A function with a cache.\"\"\" # Request a department from an external service. return await self.http_client.get_json( \"https://int.example.com/users\", {\"user_id\": user_id) )[\"department\"] async def do_something_with_users(self) -> None: \"\"\"Calls the cached function and then invalidates an entry in its cache.\"\"\" user_id = \"@alice:example.com\" # Get the user. Since get_department_for_user is wrapped with a cache, # the return value for this user_id will be cached. department = await self.get_department_for_user(user_id) # Do something with `department`... # Let's say something has changed with our user, and the entry we have for # them in the cache is out of date, so we want to invalidate it. await self.api.invalidate_cache(self.get_department_for_user, (user_id,)) See the cached docstring for more details.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Caching","id":"616","title":"Caching"},"617":{"body":"Spam checker callbacks allow module developers to implement spam mitigation actions for Synapse instances. Spam checker callbacks can be registered using the module API's register_spam_checker_callbacks method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » Spam checker callbacks","id":"617","title":"Spam checker callbacks"},"618":{"body":"The available spam checker callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » Callbacks","id":"618","title":"Callbacks"},"619":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.60.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean or a string is now deprecated. async def check_event_for_spam(event: \"synapse.module_api.EventBase\") -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", str, bool] Called when receiving an event from a client or via federation. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) a non-Codes str to reject the operation and specify an error message. Note that clients typically will not localize the error message to the user's preferred locale. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » check_event_for_spam","id":"619","title":"check_event_for_spam"},"62":{"body":"If you are able to set up your domain so that https:// is routed to Synapse (i.e., the only change needed is to direct federation traffic to port 443 instead of port 8448), then it is possible to configure Synapse to serve a suitable .well-known/matrix/server file. To do so, add the following to your homeserver.yaml file: serve_server_wellknown: true Note : this only works if https:// is routed to Synapse, so is generally not suitable if Synapse is hosted at a subdomain such as https://synapse.example.com.","breadcrumbs":"Delegation » Serving a .well-known/matrix/server file with Synapse","id":"62","title":"Serving a .well-known/matrix/server file with Synapse"},"620":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.61.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_join_room(user: str, room: str, is_invited: bool) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when a user is trying to join a room. The user is represented by their Matrix user ID (e.g. @alice:example.com) and the room is represented by its Matrix ID (e.g. !room:example.com). The module is also given a boolean to indicate whether the user currently has a pending invite in the room. This callback isn't called if the join is performed by a server administrator, or in the context of a room creation. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_join_room","id":"620","title":"user_may_join_room"},"621":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_invite(inviter: str, invitee: str, room_id: str) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when processing an invitation, both when one is created locally or when receiving an invite over federation. Both inviter and invitee are represented by their Matrix user ID (e.g. @alice:example.com). The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_invite","id":"621","title":"user_may_invite"},"622":{"body":"First introduced in Synapse v1.45.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_send_3pid_invite( inviter: str, medium: str, address: str, room_id: str,\n) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when processing an invitation using a third-party identifier (also called a 3PID, e.g. an email address or a phone number). It is only called when a 3PID invite is created locally - not when one is received in a room over federation. If the 3PID is already associated with a Matrix ID, the spam check will go through the user_may_invite callback instead. The inviter is represented by their Matrix user ID (e.g. @alice:example.com), and the invitee is represented by its medium (e.g. \"email\") and its address (e.g. alice@example.com). See the Matrix specification for more information regarding third-party identifiers. For example, a call to this callback to send an invitation to the email address alice@example.com would look like this: await user_may_send_3pid_invite( \"@bob:example.com\", # The inviter's user ID \"email\", # The medium of the 3PID to invite \"alice@example.com\", # The address of the 3PID to invite \"!some_room:example.com\", # The ID of the room to send the invite into\n) Note : If the third-party identifier is already associated with a matrix user ID, user_may_invite will be used instead. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_send_3pid_invite","id":"622","title":"user_may_send_3pid_invite"},"623":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_create_room(user_id: str) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when processing a room creation request. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_create_room","id":"623","title":"user_may_create_room"},"624":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_create_room_alias(user_id: str, room_alias: \"synapse.module_api.RoomAlias\") -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when trying to associate an alias with an existing room. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_create_room_alias","id":"624","title":"user_may_create_room_alias"},"625":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def user_may_publish_room(user_id: str, room_id: str) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when trying to publish a room to the homeserver's public rooms directory. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » user_may_publish_room","id":"625","title":"user_may_publish_room"},"626":{"body":"First introduced in Synapse v1.37.0 async def check_username_for_spam(user_profile: synapse.module_api.UserProfile, requester_id: str) -> bool Called when computing search results in the user directory. The module must return a bool indicating whether the given user should be excluded from user directory searches. Return True to indicate that the user is spammy and exclude them from search results; otherwise return False. The profile is represented as a dictionary with the following keys: user_id: str. The Matrix ID for this user. display_name: Optional[str]. The user's display name, or None if this user has not set a display name. avatar_url: Optional[str]. The mxc:// URL to the user's avatar, or None if this user has not set an avatar. The module is given a copy of the original dictionary, so modifying it from within the module cannot modify a user's profile when included in user directory search results. The requester_id parameter is the ID of the user that called the user directory API. If multiple modules implement this callback, they will be considered in order. If a callback returns False, Synapse falls through to the next one. The value of the first callback that does not return False will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » check_username_for_spam","id":"626","title":"check_username_for_spam"},"627":{"body":"First introduced in Synapse v1.37.0 async def check_registration_for_spam( email_threepid: Optional[dict], username: Optional[str], request_info: Collection[Tuple[str, str]], auth_provider_id: Optional[str] = None,\n) -> \"synapse.spam_checker_api.RegistrationBehaviour\" Called when registering a new user. The module must return a RegistrationBehaviour indicating whether the registration can go through or must be denied, or whether the user may be allowed to register but will be shadow banned. The arguments passed to this callback are: email_threepid: The email address used for registering, if any. username: The username the user would like to register. Can be None, meaning that Synapse will generate one later. request_info: A collection of tuples, which first item is a user agent, and which second item is an IP address. These user agents and IP addresses are the ones that were used during the registration process. auth_provider_id: The identifier of the SSO authentication provider, if any. If multiple modules implement this callback, they will be considered in order. If a callback returns RegistrationBehaviour.ALLOW, Synapse falls through to the next one. The value of the first callback that does not return RegistrationBehaviour.ALLOW will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » check_registration_for_spam","id":"627","title":"check_registration_for_spam"},"628":{"body":"First introduced in Synapse v1.37.0 Changed in Synapse v1.62.0: synapse.module_api.NOT_SPAM and synapse.module_api.errors.Codes can be returned by this callback. Returning a boolean is now deprecated. async def check_media_file_for_spam( file_wrapper: \"synapse.media.media_storage.ReadableFileWrapper\", file_info: \"synapse.media._base.FileInfo\",\n) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\", bool] Called when storing a local or remote file. The callback must return one of: synapse.module_api.NOT_SPAM, to allow the operation. Other callbacks may still decide to reject it. synapse.module_api.errors.Codes to reject the operation with an error code. In case of doubt, synapse.module_api.errors.Codes.FORBIDDEN is a good error code. (deprecated) False, which is the same as returning synapse.module_api.NOT_SPAM. (deprecated) True, which is the same as returning synapse.module_api.errors.Codes.FORBIDDEN. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » check_media_file_for_spam","id":"628","title":"check_media_file_for_spam"},"629":{"body":"First introduced in Synapse v1.60.0 async def should_drop_federated_event(event: \"synapse.events.EventBase\") -> bool Called when checking whether a remote server can federate an event with us. Returning True from this function will silently drop a federated event and split-brain our view of a room's DAG, and thus you shouldn't use this callback unless you know what you are doing. If multiple modules implement this callback, they will be considered in order. If a callback returns False, Synapse falls through to the next one. The value of the first callback that does not return False will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback. Note that this check is applied to federation invites as of Synapse v1.130.0.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » should_drop_federated_event","id":"629","title":"should_drop_federated_event"},"63":{"body":"It is also possible to do delegation using a SRV DNS record. However, that is generally not recommended, as it can be difficult to configure the TLS certificates correctly in this case, and it offers little advantage over .well-known delegation. Please keep in mind that server delegation is a function of server-server communication, and as such using SRV DNS records will not cover use cases involving client-server comms. This means setting global client settings (such as a Jitsi endpoint, or disabling creating new rooms as encrypted by default, etc) will still require that you serve a file from the https:///.well-known/ endpoints defined in the spec! If you are considering using SRV DNS delegation to avoid serving files from this endpoint, consider the impact that you will not be able to change those client-based default values globally, and will be relegated to the featureset of the configuration of each individual client. However, if you really need it, you can find some documentation on what such a record should look like and how Synapse will use it in the Matrix specification .","breadcrumbs":"Delegation » SRV DNS record delegation","id":"63","title":"SRV DNS record delegation"},"630":{"body":"First introduced in Synapse v1.87.0 async def check_login_for_spam( user_id: str, device_id: Optional[str], initial_display_name: Optional[str], request_info: Collection[Tuple[Optional[str], str]], auth_provider_id: Optional[str] = None,\n) -> Union[\"synapse.module_api.NOT_SPAM\", \"synapse.module_api.errors.Codes\"] Called when a user logs in. The arguments passed to this callback are: user_id: The user ID the user is logging in with device_id: The device ID the user is re-logging into. initial_display_name: The device display name, if any. request_info: A collection of tuples, which first item is a user agent, and which second item is an IP address. These user agents and IP addresses are the ones that were used during the login process. auth_provider_id: The identifier of the SSO authentication provider, if any. If multiple modules implement this callback, they will be considered in order. If a callback returns synapse.module_api.NOT_SPAM, Synapse falls through to the next one. The value of the first callback that does not return synapse.module_api.NOT_SPAM will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback. Note: This will not be called when a user registers.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » check_login_for_spam","id":"630","title":"check_login_for_spam"},"631":{"body":"The example below is a module that implements the spam checker callback check_event_for_spam to deny any message sent by users whose Matrix user IDs are mentioned in a configured list, and registers a web resource to the path /_synapse/client/list_spam_checker/is_evil that returns a JSON object indicating whether the provided user appears in that list. import json\nfrom typing import Union from twisted.web.resource import Resource\nfrom twisted.web.server import Request from synapse.module_api import ModuleApi class IsUserEvilResource(Resource): def __init__(self, config): super(IsUserEvilResource, self).__init__() self.evil_users = config.get(\"evil_users\") or [] def render_GET(self, request: Request): user = request.args.get(b\"user\")[0].decode() request.setHeader(b\"Content-Type\", b\"application/json\") return json.dumps({\"evil\": user in self.evil_users}).encode() class ListSpamChecker: def __init__(self, config: dict, api: ModuleApi): self.api = api self.evil_users = config.get(\"evil_users\") or [] self.api.register_spam_checker_callbacks( check_event_for_spam=self.check_event_for_spam, ) self.api.register_web_resource( path=\"/_synapse/client/list_spam_checker/is_evil\", resource=IsUserEvilResource(config), ) async def check_event_for_spam(self, event: \"synapse.events.EventBase\") -> Union[Literal[\"NOT_SPAM\"], Codes]: if event.sender in self.evil_users: return Codes.FORBIDDEN else: return synapse.module_api.NOT_SPAM","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Spam checker callbacks » Example","id":"631","title":"Example"},"632":{"body":"Third party rules callbacks allow module developers to add extra checks to verify the validity of incoming events. Third party event rules callbacks can be registered using the module API's register_third_party_rules_callbacks method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » Third party rules callbacks","id":"632","title":"Third party rules callbacks"},"633":{"body":"The available third party rules callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » Callbacks","id":"633","title":"Callbacks"},"634":{"body":"First introduced in Synapse v1.39.0 async def check_event_allowed( event: \"synapse.events.EventBase\", state_events: \"synapse.types.StateMap\",\n) -> Tuple[bool, Optional[dict]] This callback is very experimental and can and will break without notice. Module developers are encouraged to implement check_event_for_spam from the spam checker category instead. Called when processing any incoming event, with the event and a StateMap representing the current state of the room the event is being sent into. A StateMap is a dictionary that maps tuples containing an event type and a state key to the corresponding state event. For example retrieving the room's m.room.create event from the state_events argument would look like this: state_events.get((\"m.room.create\", \"\")). The module must return a boolean indicating whether the event can be allowed. Note that this callback function processes incoming events coming via federation traffic (on top of client traffic). This means denying an event might cause the local copy of the room's history to diverge from that of remote servers. This may cause federation issues in the room. It is strongly recommended to only deny events using this callback function if the sender is a local user, or in a private federation in which all servers are using the same module, with the same configuration. If the boolean returned by the module is True, it may also tell Synapse to replace the event with new data by returning the new event's data as a dictionary. In order to do that, it is recommended the module calls event.get_dict() to get the current event as a dictionary, and modify the returned dictionary accordingly. If check_event_allowed raises an exception, the module is assumed to have failed. The event will not be accepted but is not treated as explicitly rejected, either. An HTTP request causing the module check will likely result in a 500 Internal Server Error. When the boolean returned by the module is False, the event is rejected. (Module developers should not use exceptions for rejection.) Note that replacing the event only works for events sent by local users, not for events received over federation. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » check_event_allowed","id":"634","title":"check_event_allowed"},"635":{"body":"First introduced in Synapse v1.39.0 async def on_create_room( requester: \"synapse.types.Requester\", request_content: dict, is_requester_admin: bool,\n) -> None Called when processing a room creation request, with the Requester object for the user performing the request, a dictionary representing the room creation request's JSON body (see the spec for a list of possible parameters), and a boolean indicating whether the user performing the request is a server admin. Modules can modify the request_content (by e.g. adding events to its initial_state), or deny the room's creation by raising a module_api.errors.SynapseError. If multiple modules implement this callback, they will be considered in order. If a callback returns without raising an exception, Synapse falls through to the next one. The room creation will be forbidden as soon as one of the callbacks raises an exception. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_create_room","id":"635","title":"on_create_room"},"636":{"body":"First introduced in Synapse v1.39.0 async def check_threepid_can_be_invited( medium: str, address: str, state_events: \"synapse.types.StateMap\",\n) -> bool: Called when processing an invite via a third-party identifier (i.e. email or phone number). The module must return a boolean indicating whether the invite can go through. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » check_threepid_can_be_invited","id":"636","title":"check_threepid_can_be_invited"},"637":{"body":"First introduced in Synapse v1.39.0 async def check_visibility_can_be_modified( room_id: str, state_events: \"synapse.types.StateMap\", new_visibility: str,\n) -> bool: Called when changing the visibility of a room in the local public room directory. The visibility is a string that's either \"public\" or \"private\". The module must return a boolean indicating whether the change can go through. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » check_visibility_can_be_modified","id":"637","title":"check_visibility_can_be_modified"},"638":{"body":"First introduced in Synapse v1.47.0 async def on_new_event( event: \"synapse.events.EventBase\", state_events: \"synapse.types.StateMap\",\n) -> None: Called after sending an event into a room. The module is passed the event, as well as the state of the room after the event. This means that if the event is a state event, it will be included in this state. The state map may not be complete if Synapse hasn't yet loaded the full state of the room. This can happen for events in rooms that were just joined from a remote server. Note that this callback is called when the event has already been processed and stored into the room, which means this callback cannot be used to deny persisting the event. To deny an incoming event, see check_event_for_spam instead. For any given event, this callback will be called on every worker process, even if that worker will not end up acting on that event. This callback will not be called for events that are marked as rejected. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_new_event","id":"638","title":"on_new_event"},"639":{"body":"First introduced in Synapse v1.55.0 async def check_can_shutdown_room( user_id: str, room_id: str,\n) -> bool: Called when an admin user requests the shutdown of a room. The module must return a boolean indicating whether the shutdown can go through. If the callback returns False, the shutdown will not proceed and the caller will see a M_FORBIDDEN error. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » check_can_shutdown_room","id":"639","title":"check_can_shutdown_room"},"64":{"body":"","breadcrumbs":"Delegation » Delegation FAQ","id":"64","title":"Delegation FAQ"},"640":{"body":"First introduced in Synapse v1.55.0 async def check_can_deactivate_user( user_id: str, by_admin: bool,\n) -> bool: Called when the deactivation of a user is requested. User deactivation can be performed by an admin or the user themselves, so developers are encouraged to check the requester when implementing this callback. The module must return a boolean indicating whether the deactivation can go through. If the callback returns False, the deactivation will not proceed and the caller will see a M_FORBIDDEN error. The module is passed two parameters, user_id which is the ID of the user being deactivated, and by_admin which is True if the request is made by a serve admin, and False otherwise. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » check_can_deactivate_user","id":"640","title":"check_can_deactivate_user"},"641":{"body":"First introduced in Synapse v1.54.0 async def on_profile_update( user_id: str, new_profile: \"synapse.module_api.ProfileInfo\", by_admin: bool, deactivation: bool,\n) -> None: Called after updating a local user's profile. The update can be triggered either by the user themselves or a server admin. The update can also be triggered by a user being deactivated (in which case their display name is set to an empty string (\"\") and the avatar URL is set to None). The module is passed the Matrix ID of the user whose profile has been updated, their new profile, as well as a by_admin boolean that is True if the update was triggered by a server admin (and False otherwise), and a deactivated boolean that is True if the update is a result of the user being deactivated. Note that the by_admin boolean is also True if the profile change happens as a result of the user logging in through Single Sign-On, or if a server admin updates their own profile. Per-room profile changes do not trigger this callback to be called. Synapse administrators wishing this callback to be called on every profile change are encouraged to disable per-room profiles globally using the allow_per_room_profiles configuration setting in Synapse's configuration file. This callback is not called when registering a user, even when setting it through the get_displayname_for_registration module callback. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_profile_update","id":"641","title":"on_profile_update"},"642":{"body":"First introduced in Synapse v1.54.0 async def on_user_deactivation_status_changed( user_id: str, deactivated: bool, by_admin: bool\n) -> None: Called after deactivating a local user, or reactivating them through the admin API. The deactivation can be triggered either by the user themselves or a server admin. The module is passed the Matrix ID of the user whose status is changed, as well as a deactivated boolean that is True if the user is being deactivated and False if they're being reactivated, and a by_admin boolean that is True if the deactivation was triggered by a server admin (and False otherwise). This latter by_admin boolean is always True if the user is being reactivated, as this operation can only be performed through the admin API. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_user_deactivation_status_changed","id":"642","title":"on_user_deactivation_status_changed"},"643":{"body":"First introduced in Synapse v1.56.0 This callback is deprecated in favour of the on_add_user_third_party_identifier callback, which features the same functionality. The only difference is in name. async def on_threepid_bind(user_id: str, medium: str, address: str) -> None: Called after creating an association between a local user and a third-party identifier (email address, phone number). The module is given the Matrix ID of the user the association is for, as well as the medium (email or msisdn) and address of the third-party identifier. Note that this callback is not called after a successful association on an identity server . If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_threepid_bind","id":"643","title":"on_threepid_bind"},"644":{"body":"First introduced in Synapse v1.79.0 async def on_add_user_third_party_identifier(user_id: str, medium: str, address: str) -> None: Called after successfully creating an association between a user and a third-party identifier (email address, phone number). The module is given the Matrix ID of the user the association is for, as well as the medium (email or msisdn) and address of the third-party identifier (i.e. an email address). Note that this callback is not called if a user attempts to bind their third-party identifier to an identity server (via a call to POST /_matrix/client/v3/account/3pid/bind ). If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_add_user_third_party_identifier","id":"644","title":"on_add_user_third_party_identifier"},"645":{"body":"First introduced in Synapse v1.79.0 async def on_remove_user_third_party_identifier(user_id: str, medium: str, address: str) -> None: Called after successfully removing an association between a user and a third-party identifier (email address, phone number). The module is given the Matrix ID of the user the association is for, as well as the medium (email or msisdn) and address of the third-party identifier (i.e. an email address). Note that this callback is not called if a user attempts to unbind their third-party identifier from an identity server (via a call to POST /_matrix/client/v3/account/3pid/unbind ). If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » on_remove_user_third_party_identifier","id":"645","title":"on_remove_user_third_party_identifier"},"646":{"body":"The example below is a module that implements the third-party rules callback check_event_allowed to censor incoming messages as dictated by a third-party service. from typing import Optional, Tuple from synapse.module_api import ModuleApi _DEFAULT_CENSOR_ENDPOINT = \"https://my-internal-service.local/censor-event\" class EventCensorer: def __init__(self, config: dict, api: ModuleApi): self.api = api self._endpoint = config.get(\"endpoint\", _DEFAULT_CENSOR_ENDPOINT) self.api.register_third_party_rules_callbacks( check_event_allowed=self.check_event_allowed, ) async def check_event_allowed( self, event: \"synapse.events.EventBase\", state_events: \"synapse.types.StateMap\", ) -> Tuple[bool, Optional[dict]]: event_dict = event.get_dict() new_event_content = await self.api.http_client.post_json_get_json( uri=self._endpoint, post_json=event_dict, ) event_dict[\"content\"] = new_event_content return event_dict","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Third-party rules callbacks » Example","id":"646","title":"Example"},"647":{"body":"Presence router callbacks allow module developers to define additional users which receive presence updates from local users. The additional users can be local or remote. For example, it could be used to direct all of @alice:example.com (a local user)'s presence updates to @bob:matrix.org (a remote user), even though they don't share a room. (Note that those presence updates might not make it to @bob:matrix.org's client unless a similar presence router is running on that homeserver.) Presence router callbacks can be registered using the module API's register_presence_router_callbacks method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Presence router callbacks » Presence router callbacks","id":"647","title":"Presence router callbacks"},"648":{"body":"The available presence router callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Presence router callbacks » Callbacks","id":"648","title":"Callbacks"},"649":{"body":"First introduced in Synapse v1.42.0 async def get_users_for_states( state_updates: Iterable[\"synapse.api.UserPresenceState\"],\n) -> Dict[str, Set[\"synapse.api.UserPresenceState\"]] Requires get_interested_users to also be registered Called when processing updates to the presence state of one or more users. This callback can be used to instruct the server to forward that presence state to specific users. The module must return a dictionary that maps from Matrix user IDs (which can be local or remote) to the UserPresenceState changes that they should be forwarded. Synapse will then attempt to send the specified presence updates to each user when possible. If multiple modules implement this callback, Synapse merges all the dictionaries returned by the callbacks. If multiple callbacks return a dictionary containing the same key, Synapse concatenates the sets associated with this key from each dictionary.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Presence router callbacks » get_users_for_states","id":"649","title":"get_users_for_states"},"65":{"body":"If your homeserver's APIs are accessible on the default federation port (8448) and the domain your server_name points to, you do not need any delegation. For instance, if you registered example.com and pointed its DNS A record at a fresh server, you could install Synapse on that host, giving it a server_name of example.com, and once a reverse proxy has been set up to proxy all requests sent to the port 8448 and serve TLS certificates for example.com, you wouldn't need any delegation set up. However , if your homeserver's APIs aren't accessible on port 8448 and on the domain server_name points to, you will need to let other servers know how to find it using delegation.","breadcrumbs":"Delegation » When do I need delegation?","id":"65","title":"When do I need delegation?"},"650":{"body":"First introduced in Synapse v1.42.0 async def get_interested_users( user_id: str\n) -> Union[Set[str], \"synapse.module_api.PRESENCE_ALL_USERS\"] Requires get_users_for_states to also be registered Called when determining which users someone should be able to see the presence state of. This callback should return complementary results to get_users_for_state or the presence information may not be properly forwarded. The callback is given the Matrix user ID for a local user that is requesting presence data and should return the Matrix user IDs of the users whose presence state they are allowed to query. The returned users can be local or remote. Alternatively the callback can return synapse.module_api.PRESENCE_ALL_USERS to indicate that the user should receive updates from all known users. If multiple modules implement this callback, they will be considered in order. Synapse calls each callback one by one, and use a concatenation of all the sets returned by the callbacks. If one callback returns synapse.module_api.PRESENCE_ALL_USERS, Synapse uses this value instead. If this happens, Synapse does not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Presence router callbacks » get_interested_users","id":"650","title":"get_interested_users"},"651":{"body":"The example below is a module that implements both presence router callbacks, and ensures that @alice:example.org receives all presence updates from @bob:example.com and @charlie:somewhere.org, regardless of whether Alice shares a room with any of them. from typing import Dict, Iterable, Set, Union from synapse.module_api import ModuleApi class CustomPresenceRouter: def __init__(self, config: dict, api: ModuleApi): self.api = api self.api.register_presence_router_callbacks( get_users_for_states=self.get_users_for_states, get_interested_users=self.get_interested_users, ) async def get_users_for_states( self, state_updates: Iterable[\"synapse.api.UserPresenceState\"], ) -> Dict[str, Set[\"synapse.api.UserPresenceState\"]]: res = {} for update in state_updates: if ( update.user_id == \"@bob:example.com\" or update.user_id == \"@charlie:somewhere.org\" ): res.setdefault(\"@alice:example.com\", set()).add(update) return res async def get_interested_users( self, user_id: str, ) -> Union[Set[str], \"synapse.module_api.PRESENCE_ALL_USERS\"]: if user_id == \"@alice:example.com\": return {\"@bob:example.com\", \"@charlie:somewhere.org\"} return set()","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Presence router callbacks » Example","id":"651","title":"Example"},"652":{"body":"Account validity callbacks allow module developers to add extra steps to verify the validity on an account, i.e. see if a user can be granted access to their account on the Synapse instance. Account validity callbacks can be registered using the module API's register_account_validity_callbacks method. The available account validity callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account validity callbacks » Account validity callbacks","id":"652","title":"Account validity callbacks"},"653":{"body":"First introduced in Synapse v1.39.0 async def is_user_expired(user: str) -> Optional[bool] Called when processing any authenticated request (except for logout requests). The module can return a bool to indicate whether the user has expired and should be locked out of their account, or None if the module wasn't able to figure it out. The user is represented by their Matrix user ID (e.g. @alice:example.com). If the module returns True, the current request will be denied with the error code ORG_MATRIX_EXPIRED_ACCOUNT and the HTTP status code 403. Note that this doesn't invalidate the user's access token. If multiple modules implement this callback, they will be considered in order. If a callback returns None, Synapse falls through to the next one. The value of the first callback that does not return None will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account validity callbacks » is_user_expired","id":"653","title":"is_user_expired"},"654":{"body":"First introduced in Synapse v1.39.0 async def on_user_registration(user: str) -> None Called after successfully registering a user, in case the module needs to perform extra operations to keep track of them. (e.g. add them to a database table). The user is represented by their Matrix user ID. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account validity callbacks » on_user_registration","id":"654","title":"on_user_registration"},"655":{"body":"First introduced in Synapse v1.98.0 async def on_user_login(user_id: str, auth_provider_type: str, auth_provider_id: str) -> None Called after successfully login or registration of a user for cases when module needs to perform extra operations after auth. represented by their Matrix user ID. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account validity callbacks » on_user_login","id":"655","title":"on_user_login"},"656":{"body":"Password auth providers offer a way for server administrators to integrate their Synapse installation with an external authentication system. The callbacks can be registered by using the Module API's register_password_auth_provider_callbacks method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » Password auth provider callbacks","id":"656","title":"Password auth provider callbacks"},"657":{"body":"","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » Callbacks","id":"657","title":"Callbacks"},"658":{"body":"First introduced in Synapse v1.46.0 auth_checkers: Dict[Tuple[str, Tuple[str, ...]], Callable] A dict mapping from tuples of a login type identifier (such as m.login.password) and a tuple of field names (such as (\"password\", \"secret_thing\")) to authentication checking callbacks, which should be of the following form: async def check_auth( user: str, login_type: str, login_dict: \"synapse.module_api.JsonDict\",\n) -> Optional[ Tuple[ str, Optional[Callable[[\"synapse.module_api.LoginResponse\"], Awaitable[None]]] ]\n] The login type and field names should be provided by the user in the request to the /login API. The Matrix specification defines some types, however user defined ones are also allowed. The callback is passed the user field provided by the client (which might not be in @username:server form), the login type, and a dictionary of login secrets passed by the client. If the authentication is successful, the module must return the user's Matrix ID (e.g. @alice:example.com) and optionally a callback to be called with the response to the /login request. If the module doesn't wish to return a callback, it must return None instead. If the authentication is unsuccessful, the module must return None. Note that the user is not automatically registered, the register_user(..) method of the module API can be used to lazily create users. If multiple modules register an auth checker for the same login type but with different fields, Synapse will refuse to start. If multiple modules register an auth checker for the same login type with the same fields, then the callbacks will be executed in order, until one returns a Matrix User ID (and optionally a callback). In that case, the return value of that callback will be accepted and subsequent callbacks will not be fired. If every callback returns None, then the authentication fails.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » auth_checkers","id":"658","title":"auth_checkers"},"659":{"body":"First introduced in Synapse v1.46.0 async def check_3pid_auth( medium: str, address: str, password: str,\n) -> Optional[ Tuple[ str, Optional[Callable[[\"synapse.module_api.LoginResponse\"], Awaitable[None]]] ]\n] Called when a user attempts to register or log in with a third party identifier, such as email. It is passed the medium (eg. email), an address (eg. jdoe@example.com) and the user's password. If the authentication is successful, the module must return the user's Matrix ID (e.g. @alice:example.com) and optionally a callback to be called with the response to the /login request. If the module doesn't wish to return a callback, it must return None instead. If the authentication is unsuccessful, the module must return None. If multiple modules implement this callback, they will be considered in order. If a callback returns None, Synapse falls through to the next one. The value of the first callback that does not return None will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback. If every callback returns None, the authentication is denied.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » check_3pid_auth","id":"659","title":"check_3pid_auth"},"66":{"body":"Generally, using a reverse proxy for both the federation and client traffic is a good idea, since it saves handling TLS traffic in Synapse. See the reverse proxy documentation for information on setting up a reverse proxy.","breadcrumbs":"Delegation » Should I use a reverse proxy for federation traffic?","id":"66","title":"Should I use a reverse proxy for federation traffic?"},"660":{"body":"First introduced in Synapse v1.46.0 async def on_logged_out( user_id: str, device_id: Optional[str], access_token: str\n) -> None Called during a logout request for a user. It is passed the qualified user ID, the ID of the deactivated device (if any: access tokens are occasionally created without an associated device ID), and the (now deactivated) access token. Deleting the related pushers is done after calling on_logged_out, so you can rely on them to still be present. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » on_logged_out","id":"660","title":"on_logged_out"},"661":{"body":"First introduced in Synapse v1.52.0 async def get_username_for_registration( uia_results: Dict[str, Any], params: Dict[str, Any],\n) -> Optional[str] Called when registering a new user. The module can return a username to set for the user being registered by returning it as a string, or None if it doesn't wish to force a username for this user. If a username is returned, it will be used as the local part of a user's full Matrix ID (e.g. it's alice in @alice:example.com). This callback is called once User-Interactive Authentication has been completed by the user. It is not called when registering a user via SSO. It is passed two dictionaries, which include the information that the user has provided during the registration process. The first dictionary contains the results of the User-Interactive Authentication flow followed by the user. Its keys are the identifiers of every step involved in the flow, associated with either a boolean value indicating whether the step was correctly completed, or additional information (e.g. email address, phone number...). A list of most existing identifiers can be found in the Matrix specification . Here's an example featuring all currently supported keys: { \"m.login.dummy\": True, # Dummy authentication \"m.login.terms\": True, # User has accepted the terms of service for the homeserver \"m.login.recaptcha\": True, # User has completed the recaptcha challenge \"m.login.email.identity\": { # User has provided and verified an email address \"medium\": \"email\", \"address\": \"alice@example.com\", \"validated_at\": 1642701357084, }, \"m.login.msisdn\": { # User has provided and verified a phone number \"medium\": \"msisdn\", \"address\": \"33123456789\", \"validated_at\": 1642701357084, }, \"m.login.registration_token\": \"sometoken\", # User has registered through a registration token\n} The second dictionary contains the parameters provided by the user's client in the request to /_matrix/client/v3/register. See the Matrix specification for a complete list of these parameters. If the module cannot, or does not wish to, generate a username for this user, it must return None. If multiple modules implement this callback, they will be considered in order. If a callback returns None, Synapse falls through to the next one. The value of the first callback that does not return None will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback. If every callback returns None, the username provided by the user is used, if any (otherwise one is automatically generated).","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » get_username_for_registration","id":"661","title":"get_username_for_registration"},"662":{"body":"First introduced in Synapse v1.54.0 async def get_displayname_for_registration( uia_results: Dict[str, Any], params: Dict[str, Any],\n) -> Optional[str] Called when registering a new user. The module can return a display name to set for the user being registered by returning it as a string, or None if it doesn't wish to force a display name for this user. This callback is called once User-Interactive Authentication has been completed by the user. It is not called when registering a user via SSO. It is passed two dictionaries, which include the information that the user has provided during the registration process. These dictionaries are identical to the ones passed to get_username_for_registration , so refer to the documentation of this callback for more information about them. If multiple modules implement this callback, they will be considered in order. If a callback returns None, Synapse falls through to the next one. The value of the first callback that does not return None will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback. If every callback returns None, the username will be used (e.g. alice if the user being registered is @alice:example.com).","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » get_displayname_for_registration","id":"662","title":"get_displayname_for_registration"},"663":{"body":"First introduced in Synapse v1.53.0 async def is_3pid_allowed(self, medium: str, address: str, registration: bool) -> bool Called when attempting to bind a third-party identifier (i.e. an email address or a phone number). The module is given the medium of the third-party identifier (which is email if the identifier is an email address, or msisdn if the identifier is a phone number) and its address, as well as a boolean indicating whether the attempt to bind is happening as part of registering a new user. The module must return a boolean indicating whether the identifier can be allowed to be bound to an account on the local homeserver. If multiple modules implement this callback, they will be considered in order. If a callback returns True, Synapse falls through to the next one. The value of the first callback that does not return True will be used. If this happens, Synapse will not call any of the subsequent implementations of this callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » is_3pid_allowed","id":"663","title":"is_3pid_allowed"},"664":{"body":"The example module below implements authentication checkers for two different login types: my.login.type Expects a my_field field to be sent to /login Is checked by the method: self.check_my_login m.login.password (defined in the spec ) Expects a password field to be sent to /login Is checked by the method: self.check_pass from typing import Awaitable, Callable, Optional, Tuple import synapse\nfrom synapse import module_api class MyAuthProvider: def __init__(self, config: dict, api: module_api): self.api = api self.credentials = { \"bob\": \"building\", \"@scoop:matrix.org\": \"digging\", } api.register_password_auth_provider_callbacks( auth_checkers={ (\"my.login_type\", (\"my_field\",)): self.check_my_login, (\"m.login.password\", (\"password\",)): self.check_pass, }, ) async def check_my_login( self, username: str, login_type: str, login_dict: \"synapse.module_api.JsonDict\", ) -> Optional[ Tuple[ str, Optional[Callable[[\"synapse.module_api.LoginResponse\"], Awaitable[None]]], ] ]: if login_type != \"my.login_type\": return None if self.credentials.get(username) == login_dict.get(\"my_field\"): return (self.api.get_qualified_user_id(username), None) async def check_pass( self, username: str, login_type: str, login_dict: \"synapse.module_api.JsonDict\", ) -> Optional[ Tuple[ str, Optional[Callable[[\"synapse.module_api.LoginResponse\"], Awaitable[None]]], ] ]: if login_type != \"m.login.password\": return None if self.credentials.get(username) == login_dict.get(\"password\"): return (self.api.get_qualified_user_id(username), None)","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Password auth provider callbacks » Example","id":"664","title":"Example"},"665":{"body":"Background update controller callbacks allow module developers to control (e.g. rate-limit) how database background updates are run. A database background update is an operation Synapse runs on its database in the background after it starts. It's usually used to run database operations that would take too long if they were run at the same time as schema updates (which are run on startup) and delay Synapse's startup too much: populating a table with a big amount of data, adding an index on a big table, deleting superfluous data, etc. Background update controller callbacks can be registered using the module API's register_background_update_controller_callbacks method. Only the first module (in order of appearance in Synapse's configuration file) calling this method can register background update controller callbacks, subsequent calls are ignored. The available background update controller callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Background update controller callbacks » Background update controller callbacks","id":"665","title":"Background update controller callbacks"},"666":{"body":"First introduced in Synapse v1.49.0 def on_update(update_name: str, database_name: str, one_shot: bool) -> AsyncContextManager[int] Called when about to do an iteration of a background update. The module is given the name of the update, the name of the database, and a flag to indicate whether the background update will happen in one go and may take a long time (e.g. creating indices). If this last argument is set to False, the update will be run in batches. The module must return an async context manager. It will be entered before Synapse runs a background update; this should return the desired duration of the iteration, in milliseconds. The context manager will be exited when the iteration completes. Note that the duration returned by the context manager is a target, and an iteration may take substantially longer or shorter. If the one_shot flag is set to True, the duration returned is ignored. Note : Unlike most module callbacks in Synapse, this one is synchronous . This is because asynchronous operations are expected to be run by the async context manager. This callback is required when registering any other background update controller callback.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Background update controller callbacks » on_update","id":"666","title":"on_update"},"667":{"body":"First introduced in Synapse v1.49.0 async def default_batch_size(update_name: str, database_name: str) -> int Called before the first iteration of a background update, with the name of the update and of the database. The module must return the number of elements to process in this first iteration. If this callback is not defined, Synapse will use a default value of 100.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Background update controller callbacks » default_batch_size","id":"667","title":"default_batch_size"},"668":{"body":"First introduced in Synapse v1.49.0 async def min_batch_size(update_name: str, database_name: str) -> int Called before running a new batch for a background update, with the name of the update and of the database. The module must return an integer representing the minimum number of elements to process in this iteration. This number must be at least 1, and is used to ensure that progress is always made. If this callback is not defined, Synapse will use a default value of 100.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Background update controller callbacks » min_batch_size","id":"668","title":"min_batch_size"},"669":{"body":"Account data callbacks allow module developers to react to changes of the account data of local users. Account data callbacks can be registered using the module API's register_account_data_callbacks method.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account data callbacks » Account data callbacks","id":"669","title":"Account data callbacks"},"67":{"body":"Before upgrading check if any special steps are required to upgrade from the version you currently have installed to the current version of Synapse. The extra instructions that may be required are listed later in this document. Check that your versions of Python and PostgreSQL are still supported. Synapse follows upstream lifecycles for Python and PostgreSQL , and removes support for versions which are no longer maintained. The website https://endoflife.date also offers convenient summaries. If Synapse was installed using prebuilt packages , you will need to follow the normal process for upgrading those packages. If Synapse was installed using pip then upgrade to the latest version by running: pip install --upgrade matrix-synapse If Synapse was installed from source, then: Obtain the latest version of the source code. Git users can run git pull to do this. If you're running Synapse in a virtualenv, make sure to activate it before upgrading. For example, if Synapse is installed in a virtualenv in ~/synapse/env then run: source ~/synapse/env/bin/activate\npip install --upgrade . Include any relevant extras between square brackets, e.g. pip install --upgrade \".[postgres,oidc]\". If you're using poetry to manage a Synapse installation, run: poetry install Include any relevant extras with --extras, e.g. poetry install --extras postgres --extras oidc. It's probably easiest to run poetry install --extras all. Restart Synapse: synctl restart To check whether your update was successful, you can check the running server version with: # you may need to replace 'localhost:8008' if synapse is not configured\n# to listen on port 8008. curl http://localhost:8008/_synapse/admin/v1/server_version","breadcrumbs":"Upgrading between Synapse Versions » Upgrading Synapse","id":"67","title":"Upgrading Synapse"},"670":{"body":"The available account data callbacks are:","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account data callbacks » Callbacks","id":"670","title":"Callbacks"},"671":{"body":"First introduced in Synapse v1.57.0 async def on_account_data_updated( user_id: str, room_id: Optional[str], account_data_type: str, content: \"synapse.module_api.JsonDict\",\n) -> None: Called after user's account data has been updated. The module is given the Matrix ID of the user whose account data is changing, the room ID the data is associated with, the type associated with the change, as well as the new content. If the account data is not associated with a specific room, then the room ID is None. This callback is triggered when new account data is added or when the data associated with a given type (and optionally room) changes. This includes deletion, since in Matrix, deleting account data consists of replacing the data associated with a given type (and optionally room) with an empty dictionary ({}). Note that this doesn't trigger when changing the tags associated with a room, as these are processed separately by Synapse. If multiple modules implement this callback, Synapse runs them all in order.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account data callbacks » on_account_data_updated","id":"671","title":"on_account_data_updated"},"672":{"body":"The example below is a module that implements the on_account_data_updated callback, and sends an event to an audit room when a user changes their account data. import json\nimport attr\nfrom typing import Any, Dict, Optional from synapse.module_api import JsonDict, ModuleApi\nfrom synapse.module_api.errors import ConfigError @attr.s(auto_attribs=True)\nclass CustomAccountDataConfig: audit_room: str sender: str class CustomAccountDataModule: def __init__(self, config: CustomAccountDataConfig, api: ModuleApi): self.api = api self.config = config self.api.register_account_data_callbacks( on_account_data_updated=self.log_new_account_data, ) @staticmethod def parse_config(config: Dict[str, Any]) -> CustomAccountDataConfig: def check_in_config(param: str): if param not in config: raise ConfigError(f\"'{param}' is required\") check_in_config(\"audit_room\") check_in_config(\"sender\") return CustomAccountDataConfig( audit_room=config[\"audit_room\"], sender=config[\"sender\"], ) async def log_new_account_data( self, user_id: str, room_id: Optional[str], account_data_type: str, content: JsonDict, ) -> None: content_raw = json.dumps(content) msg_content = f\"{user_id} has changed their account data for type {account_data_type} to: {content_raw}\" if room_id is not None: msg_content += f\" (in room {room_id})\" await self.api.create_and_send_event_into_room( { \"room_id\": self.config.audit_room, \"sender\": self.config.sender, \"type\": \"m.room.message\", \"content\": { \"msgtype\": \"m.text\", \"body\": msg_content } } )","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Account data callbacks » Example","id":"672","title":"Example"},"673":{"body":"First introduced in Synapse v1.96.0 This callback allows modules to add extra fields to the unsigned section of events when they get sent down to clients. These get called every time an event is to be sent to clients, so care should be taken to ensure with respect to performance.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Add extra fields to client events unsigned section callbacks » Add extra fields to client events unsigned section callbacks","id":"673","title":"Add extra fields to client events unsigned section callbacks"},"674":{"body":"To register the callback, use register_add_extra_fields_to_unsigned_client_event_callbacks on the ModuleApi. The callback should be of the form async def add_field_to_unsigned( event: EventBase,\n) -> JsonDict: where the extra fields to add to the event's unsigned section is returned. (Modules must not attempt to modify the event directly). This cannot be used to alter the \"core\" fields in the unsigned section emitted by Synapse itself. If multiple such callbacks try to add the same field to an event's unsigned section, the last-registered callback wins.","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Add extra fields to client events unsigned section callbacks » API","id":"674","title":"API"},"675":{"body":"In order to port a module that uses Synapse's old module interface, its author needs to: ensure the module's callbacks are all asynchronous. register their callbacks using one or more of the register_[...]_callbacks methods from the ModuleApi class in the module's __init__ method (see this section for more info). Additionally, if the module is packaged with an additional web resource, the module should register this resource in its __init__ method using the register_web_resource method from the ModuleApi class (see this section for more info). There is no longer a get_db_schema_files callback provided for password auth provider modules. Any changes to the database should now be made by the module using the module API class. The module's author should also update any example in the module's configuration to only use the new modules section in Synapse's configuration file (see this section for more info).","breadcrumbs":"Configuration » Pluggable Modules » Writing a module » Porting a legacy module to the new interface » Porting an existing module that uses the old interface","id":"675","title":"Porting an existing module that uses the old interface"},"676":{"body":"For small instances it is recommended to run Synapse in the default monolith mode. For larger instances where performance is a concern it can be helpful to split out functionality into multiple separate python processes. These processes are called 'workers', and are (eventually) intended to scale horizontally independently. Synapse's worker support is under active development and subject to change as we attempt to rapidly scale ever larger Synapse instances. However we are documenting it here to help admins needing a highly scalable Synapse instance similar to the one running matrix.org. All processes continue to share the same database instance, and as such, workers only work with PostgreSQL-based Synapse deployments. SQLite should only be used for demo purposes and any admin considering workers should already be running PostgreSQL. See also Matrix.org blog post for a higher level overview.","breadcrumbs":"Configuration » Workers » Scaling synapse via workers","id":"676","title":"Scaling synapse via workers"},"677":{"body":"The processes communicate with each other via a Synapse-specific protocol called 'replication' (analogous to MySQL- or Postgres-style database replication) which feeds streams of newly written data between processes so they can be kept in sync with the database state. When configured to do so, Synapse uses a Redis pub/sub channel to send the replication stream between all configured Synapse processes. Additionally, processes may make HTTP requests to each other, primarily for operations which need to wait for a reply ─ such as sending an event. All the workers and the main process connect to Redis, which relays replication commands between processes. If Redis support is enabled Synapse will use it as a shared cache, as well as a pub/sub mechanism. See the Architectural diagram section at the end for a visualisation of what this looks like.","breadcrumbs":"Configuration » Workers » Main process/worker communication","id":"677","title":"Main process/worker communication"},"678":{"body":"A Redis server is required to manage the communication between the processes. The Redis server should be installed following the normal procedure for your distribution (e.g. apt install redis-server on Debian). It is safe to use an existing Redis deployment if you have one. Once installed, check that Redis is running and accessible from the host running Synapse, for example by executing echo PING | nc -q1 localhost 6379 and seeing a response of +PONG. The appropriate dependencies must also be installed for Synapse. If using a virtualenv, these can be installed with: pip install \"matrix-synapse[redis]\" Note that these dependencies are included when synapse is installed with pip install matrix-synapse[all]. They are also included in the debian packages from packages.matrix.org and in the docker images at https://hub.docker.com/r/ectorim/synapse/. To make effective use of the workers, you will need to configure an HTTP reverse-proxy such as nginx or haproxy, which will direct incoming requests to the correct worker, or to the main synapse instance. See the reverse proxy documentation for information on setting up a reverse proxy. When using workers, each worker process has its own configuration file which contains settings specific to that worker, such as the HTTP listener that it provides (if any), logging configuration, etc. Normally, the worker processes are configured to read from a shared configuration file as well as the worker-specific configuration files. This makes it easier to keep common configuration settings synchronised across all the processes. The main process is somewhat special in this respect: it does not normally need its own configuration file and can take all of its configuration from the shared configuration file.","breadcrumbs":"Configuration » Workers » Setting up workers","id":"678","title":"Setting up workers"},"679":{"body":"Normally, only a few changes are needed to make an existing configuration file suitable for use with workers: First, you need to enable an \"HTTP replication listener\" for the main process Secondly, you need to enable redis-based replication You will need to add an instance_map with the main process defined, as well as the relevant connection information from it's HTTP replication listener (defined in step 1 above). Note that the host defined is the address the worker needs to look for the main process at, not necessarily the same address that is bound to. If you are using Unix sockets for the replication resource, make sure to use a path to the socket file instead of a port. Optionally, a shared secret can be used to authenticate HTTP traffic between workers. For example: # extend the existing `listeners` section. This defines the ports that the\n# main process will listen on.\nlisteners: # The HTTP replication port - port: 9093 bind_address: '127.0.0.1' type: http resources: - names: [replication] # Add a random shared secret to authenticate traffic.\nworker_replication_secret: \"\" redis: enabled: true instance_map: main: host: 'localhost' port: 9093 See the configuration manual for the full documentation of each option. Under no circumstances should the replication listener be exposed to the public internet; replication traffic is: always unencrypted unauthenticated, unless worker_replication_secret is configured","breadcrumbs":"Configuration » Workers » Shared configuration","id":"679","title":"Shared configuration"},"68":{"body":"Rolling back to previous releases can be difficult, due to database schema changes between releases. Where we have been able to test the rollback process, this will be noted below. In general, you will need to undo any changes made during the upgrade process, for example: pip: source env/bin/activate\n# replace `1.3.0` accordingly:\npip install matrix-synapse==1.3.0 Debian: # replace `1.3.0` and `stretch` accordingly:\nwget https://packages.matrix.org/debian/pool/main/m/matrix-synapse-py3/matrix-synapse-py3_1.3.0+stretch1_amd64.deb\ndpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb Generally Synapse database schemas are compatible across multiple versions, but once a version of Synapse is deployed you may not be able to roll back automatically. The following table gives the version ranges and the earliest version they can be rolled back to. E.g. Synapse versions v1.58.0 through v1.61.1 can be rolled back safely to v1.57.0, but starting with v1.62.0 it is only safe to roll back to v1.61.0. Versions Compatible version v1.0.0 – v1.2.1 v1.0.0 v1.3.0 – v1.8.0 v1.3.0 v1.9.0 – v1.12.4 v1.9.0 v1.13.0 – v1.25.0 v1.13.0 v1.26.0 – v1.44.0 v1.26.0 v1.45.0 – v1.47.1 v1.38.0 v1.48.0 – v1.51.0 v1.39.0 v1.52.0 – v1.57.1 v1.49.0 v1.58.0 – v1.61.1 v1.57.0 v1.62.0 – v1.63.1 v1.61.0 v1.64.0 – v1.69.0 v1.62.0 v1.70.0 – v1.82.0 v1.68.0 v1.83.0 – v1.84.1 v1.77.0 v1.85.0 – v1.91.2 v1.83.0 v1.92.0 – v1.97.0 v1.90.0 v1.98.0 – v1.105.0 v1.96.0 v1.105.1 – v1.131.0 v1.100.0","breadcrumbs":"Upgrading between Synapse Versions » Rolling back to older versions","id":"68","title":"Rolling back to older versions"},"680":{"body":"In the config file for each worker, you must specify: The type of worker ( worker_app ). The currently available worker applications are listed below . A unique name for the worker ( worker_name ). If handling HTTP requests, a worker_listeners option with an http listener. Synapse 1.72 and older: if handling the ^/_matrix/client/v3/keys/upload endpoint, the HTTP URI for the main process (worker_main_http_uri). This config option is no longer required and is ignored when running Synapse 1.73 and newer. For example: worker_app: synapse.app.generic_worker\nworker_name: generic_worker1 worker_listeners: - type: http port: 8083 x_forwarded: true resources: - names: [client, federation] worker_log_config: /etc/matrix-synapse/generic-worker-log.yaml ...is a full configuration for a generic worker instance, which will expose a plain HTTP endpoint on port 8083 separately serving various endpoints, e.g. /sync, which are listed below. Obviously you should configure your reverse-proxy to route the relevant endpoints to the worker (localhost:8083 in the above example).","breadcrumbs":"Configuration » Workers » Worker configuration","id":"680","title":"Worker configuration"},"681":{"body":"Finally, you need to start your worker processes. This can be done with either synctl or your distribution's preferred service manager such as systemd. We recommend the use of systemd where available: for information on setting up systemd to start synapse workers, see Systemd with Workers . To use synctl, see Using synctl with Workers .","breadcrumbs":"Configuration » Workers » Running Synapse with workers","id":"681","title":"Running Synapse with workers"},"682":{"body":"The following applies to Synapse installations that have been installed from source using poetry. You can start the main Synapse process with Poetry by running the following command: poetry run synapse_homeserver --config-path [your homeserver.yaml] For worker setups, you can run the following command poetry run synapse_worker --config-path [your homeserver.yaml] --config-path [your worker.yaml]","breadcrumbs":"Configuration » Workers » Start Synapse with Poetry","id":"682","title":"Start Synapse with Poetry"},"683":{"body":"","breadcrumbs":"Configuration » Workers » Available worker applications","id":"683","title":"Available worker applications"},"684":{"body":"This worker can handle API requests matching the following regular expressions. These endpoints can be routed to any worker. If a worker is set up to handle a stream then, for maximum efficiency, additional endpoints should be routed to that worker: refer to the stream writers section below for further information. # Sync requests\n^/_matrix/client/(r0|v3)/sync$\n^/_matrix/client/(api/v1|r0|v3)/events$\n^/_matrix/client/(api/v1|r0|v3)/initialSync$\n^/_matrix/client/(api/v1|r0|v3)/rooms/[^/]+/initialSync$ # Federation requests\n^/_matrix/federation/v1/version$\n^/_matrix/federation/v1/event/\n^/_matrix/federation/v1/state/\n^/_matrix/federation/v1/state_ids/\n^/_matrix/federation/v1/backfill/\n^/_matrix/federation/v1/get_missing_events/\n^/_matrix/federation/v1/publicRooms\n^/_matrix/federation/v1/query/\n^/_matrix/federation/v1/make_join/\n^/_matrix/federation/v1/make_leave/\n^/_matrix/federation/(v1|v2)/send_join/\n^/_matrix/federation/(v1|v2)/send_leave/\n^/_matrix/federation/v1/make_knock/\n^/_matrix/federation/v1/send_knock/\n^/_matrix/federation/(v1|v2)/invite/\n^/_matrix/federation/v1/event_auth/\n^/_matrix/federation/v1/timestamp_to_event/\n^/_matrix/federation/v1/exchange_third_party_invite/\n^/_matrix/federation/v1/user/devices/\n^/_matrix/key/v2/query\n^/_matrix/federation/v1/hierarchy/ # Inbound federation transaction request\n^/_matrix/federation/v1/send/ # Client API requests\n^/_matrix/client/(api/v1|r0|v3|unstable)/createRoom$\n^/_matrix/client/(api/v1|r0|v3|unstable)/publicRooms$\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/joined_members$\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/context/.*$\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/members$\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state$\n^/_matrix/client/v1/rooms/.*/hierarchy$\n^/_matrix/client/(v1|unstable)/rooms/.*/relations/\n^/_matrix/client/v1/rooms/.*/threads$\n^/_matrix/client/unstable/im.nheko.summary/summary/.*$\n^/_matrix/client/(r0|v3|unstable)/account/3pid$\n^/_matrix/client/(r0|v3|unstable)/account/whoami$\n^/_matrix/client/(r0|v3|unstable)/devices$\n^/_matrix/client/versions$\n^/_matrix/client/(api/v1|r0|v3|unstable)/voip/turnServer$\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/event/\n^/_matrix/client/(api/v1|r0|v3|unstable)/joined_rooms$\n^/_matrix/client/v1/rooms/.*/timestamp_to_event$\n^/_matrix/client/(api/v1|r0|v3|unstable/.*)/rooms/.*/aliases\n^/_matrix/client/(api/v1|r0|v3|unstable)/search$\n^/_matrix/client/(r0|v3|unstable)/user/.*/filter(/|$)\n^/_matrix/client/(api/v1|r0|v3|unstable)/directory/room/.*$\n^/_matrix/client/(r0|v3|unstable)/capabilities$\n^/_matrix/client/(r0|v3|unstable)/notifications$\n^/_synapse/admin/v1/rooms/ # Encryption requests\n^/_matrix/client/(r0|v3|unstable)/keys/query$\n^/_matrix/client/(r0|v3|unstable)/keys/changes$\n^/_matrix/client/(r0|v3|unstable)/keys/claim$\n^/_matrix/client/(r0|v3|unstable)/room_keys/\n^/_matrix/client/(r0|v3|unstable)/keys/upload$ # Registration/login requests\n^/_matrix/client/(api/v1|r0|v3|unstable)/login$\n^/_matrix/client/(r0|v3|unstable)/register$\n^/_matrix/client/(r0|v3|unstable)/register/available$\n^/_matrix/client/v1/register/m.login.registration_token/validity$\n^/_matrix/client/(r0|v3|unstable)/password_policy$ # Event sending requests\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/redact\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/send\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/state/\n^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/(join|invite|leave|ban|unban|kick)$\n^/_matrix/client/(api/v1|r0|v3|unstable)/join/\n^/_matrix/client/(api/v1|r0|v3|unstable)/knock/\n^/_matrix/client/(api/v1|r0|v3|unstable)/profile/ # User directory search requests\n^/_matrix/client/(r0|v3|unstable)/user_directory/search$ Additionally, the following REST endpoints can be handled for GET requests: ^/_matrix/client/(api/v1|r0|v3|unstable)/pushrules/\n^/_matrix/client/unstable/org.matrix.msc4140/delayed_events\n^/_matrix/client/(api/v1|r0|v3|unstable)/devices/ # Account data requests\n^/_matrix/client/(r0|v3|unstable)/.*/tags\n^/_matrix/client/(r0|v3|unstable)/.*/account_data # Presence requests\n^/_matrix/client/(api/v1|r0|v3|unstable)/presence/ Pagination requests can also be handled, but all requests for a given room must be routed to the same instance. Additionally, care must be taken to ensure that the purge history admin API is not used while pagination requests for the room are in flight: ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/messages$ Additionally, the following endpoints should be included if Synapse is configured to use SSO (you only need to include the ones for whichever SSO provider you're using): # for all SSO providers\n^/_matrix/client/(api/v1|r0|v3|unstable)/login/sso/redirect\n^/_synapse/client/pick_idp$\n^/_synapse/client/pick_username\n^/_synapse/client/new_user_consent$\n^/_synapse/client/sso_register$ # OpenID Connect requests.\n^/_synapse/client/oidc/callback$ # SAML requests.\n^/_synapse/client/saml2/authn_response$ # CAS requests.\n^/_matrix/client/(api/v1|r0|v3|unstable)/login/cas/ticket$ Ensure that all SSO logins go to a single process. For multiple workers not handling the SSO endpoints properly, see #7530 and #9427 . Additionally, when MSC3861 is enabled (experimental_features.msc3861.enabled set to true), the following endpoints can be handled by the worker: ^/_synapse/admin/v2/users/[^/]+$\n^/_synapse/admin/v1/username_available$\n^/_synapse/admin/v1/users/[^/]+/_allow_cross_signing_replacement_without_uia$\n# Only the GET method:\n^/_synapse/admin/v1/users/[^/]+/devices$ Note that a HTTP listener with client and federation resources must be configured in the worker_listeners option in the worker config. Load balancing It is possible to run multiple instances of this worker app, with incoming requests being load-balanced between them by the reverse-proxy. However, different endpoints have different characteristics and so admins may wish to run multiple groups of workers handling different endpoints so that load balancing can be done in different ways. For /sync and /initialSync requests it will be more efficient if all requests from a particular user are routed to a single instance. This can be done in reverse proxy by extracting username part from the users access token. Admins may additionally wish to separate out /sync requests that have a since query parameter from those that don't (and /initialSync), as requests that don't are known as \"initial sync\" that happens when a user logs in on a new device and can be very resource intensive, so isolating these requests will stop them from interfering with other users ongoing syncs. Example nginx configuration snippet that handles the cases above. This is just an example and probably requires some changes according to your particular setup: # Choose sync worker based on the existence of \"since\" query parameter\nmap $arg_since $sync { default synapse_sync; '' synapse_initial_sync;\n} # Extract username from access token passed as URL parameter\nmap $arg_access_token $accesstoken_from_urlparam { # Defaults to just passing back the whole accesstoken default $arg_access_token; # Try to extract username part from accesstoken URL parameter \"~syt_(?.*?)_.*\" $username;\n} # Extract username from access token passed as authorization header\nmap $http_authorization $mxid_localpart { # Defaults to just passing back the whole accesstoken default $http_authorization; # Try to extract username part from accesstoken header \"~Bearer syt_(?.*?)_.*\" $username; # if no authorization-header exist, try mapper for URL parameter \"access_token\" \"\" $accesstoken_from_urlparam;\n} upstream synapse_initial_sync { # Use the username mapper result for hash key hash $mxid_localpart consistent; server 127.0.0.1:8016; server 127.0.0.1:8036;\n} upstream synapse_sync { # Use the username mapper result for hash key hash $mxid_localpart consistent; server 127.0.0.1:8013; server 127.0.0.1:8037; server 127.0.0.1:8038; server 127.0.0.1:8039;\n} # Sync initial/normal\nlocation ~ ^/_matrix/client/(r0|v3)/sync$ { proxy_pass http://$sync;\n} # Normal sync\nlocation ~ ^/_matrix/client/(api/v1|r0|v3)/events$ { proxy_pass http://synapse_sync;\n} # Initial_sync\nlocation ~ ^/_matrix/client/(api/v1|r0|v3)/initialSync$ { proxy_pass http://synapse_initial_sync;\n}\nlocation ~ ^/_matrix/client/(api/v1|r0|v3)/rooms/[^/]+/initialSync$ { proxy_pass http://synapse_initial_sync;\n} Federation and client requests can be balanced via simple round robin. The inbound federation transaction request ^/_matrix/federation/v1/send/ should be balanced by source IP so that transactions from the same remote server go to the same process. Registration/login requests can be handled separately purely to help ensure that unexpected load doesn't affect new logins and sign ups. Finally, event sending requests can be balanced by the room ID in the URI (or the full URI, or even just round robin), the room ID is the path component after /rooms/. If there is a large bridge connected that is sending or may send lots of events, then a dedicated set of workers can be provisioned to limit the effects of bursts of events from that bridge on events sent by normal users. Stream writers Additionally, the writing of specific streams (such as events) can be moved off of the main process to a particular worker. To enable this, the worker must have: An HTTP replication listener configured, Have a worker_name and be listed in the instance_map config. Have the main process declared on the instance_map as well. Note: The same worker can handle multiple streams, but unless otherwise documented, each stream can only have a single writer. For example, to move event persistence off to a dedicated worker, the shared configuration would include: instance_map: main: host: localhost port: 8030 event_persister1: host: localhost port: 8034 stream_writers: events: event_persister1 An example for a stream writer instance: worker_app: synapse.app.generic_worker\nworker_name: event_persister1 worker_listeners: - type: http port: 8034 resources: - names: [replication] # Enable listener if this stream writer handles endpoints for the `typing` or # `to_device` streams. Uses a different port to the `replication` listener to # avoid exposing the `replication` listener publicly. # #- type: http # port: 8035 # x_forwarded: true # resources: # - names: [client] worker_log_config: /etc/matrix-synapse/event-persister-log.yaml Some of the streams have associated endpoints which, for maximum efficiency, should be routed to the workers handling that stream. See below for the currently supported streams and the endpoints associated with them: The events stream The events stream experimentally supports having multiple writer workers, where load is sharded between them by room ID. Each writer is called an event persister . They are responsible for receiving new events, linking them to those already in the room DAG , persisting them to the DB, and finally updating the events stream. Because load is sharded in this way, you must restart all worker instances when adding or removing event persisters. An event_persister should not be mistaken for an event_creator. An event_creator listens for requests from clients to create new events and does so. It will then pass those events over HTTP replication to any configured event persisters (or the main process if none are configured). Note that event_creators and event_persisters are implemented using the same synapse.app.generic_worker . An example stream_writers configuration with multiple writers: stream_writers: events: - event_persister1 - event_persister2 The typing stream The following endpoints should be routed directly to the worker configured as the stream writer for the typing stream: ^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/typing The to_device stream The following endpoints should be routed directly to the worker configured as the stream writer for the to_device stream: ^/_matrix/client/(r0|v3|unstable)/sendToDevice/ The account_data stream The following endpoints should be routed directly to the worker configured as the stream writer for the account_data stream: ^/_matrix/client/(r0|v3|unstable)/.*/tags\n^/_matrix/client/(r0|v3|unstable)/.*/account_data The receipts stream The following endpoints should be routed directly to the worker configured as the stream writer for the receipts stream: ^/_matrix/client/(r0|v3|unstable)/rooms/.*/receipt\n^/_matrix/client/(r0|v3|unstable)/rooms/.*/read_markers The presence stream The following endpoints should be routed directly to the worker configured as the stream writer for the presence stream: ^/_matrix/client/(api/v1|r0|v3|unstable)/presence/ The push_rules stream The following endpoints should be routed directly to the worker configured as the stream writer for the push_rules stream: ^/_matrix/client/(api/v1|r0|v3|unstable)/pushrules/ Restrict outbound federation traffic to a specific set of workers The outbound_federation_restricted_to configuration is useful to make sure outbound federation traffic only goes through a specified subset of workers. This allows you to set more strict access controls (like a firewall) for all workers and only allow the federation_sender's to contact the outside world. instance_map: main: host: localhost port: 8030 federation_sender1: host: localhost port: 8034 outbound_federation_restricted_to: - federation_sender1 worker_replication_secret: \"secret_secret\" Background tasks There is also support for moving background tasks to a separate worker. Background tasks are run periodically or started via replication. Exactly which tasks are configured to run depends on your Synapse configuration (e.g. if stats is enabled). This worker doesn't handle any REST endpoints itself. To enable this, the worker must have a unique worker_name and can be configured to run background tasks. For example, to move background tasks to a dedicated worker, the shared configuration would include: run_background_tasks_on: background_worker You might also wish to investigate the update_user_directory_from_worker and media_instance_running_background_jobs settings. An example for a dedicated background worker instance: worker_app: synapse.app.generic_worker\nworker_name: background_worker worker_log_config: /etc/matrix-synapse/background-worker-log.yaml Updating the User Directory You can designate one generic worker to update the user directory. Specify its name in the shared configuration as follows: update_user_directory_from_worker: worker_name This work cannot be load-balanced; please ensure the main process is restarted after setting this option in the shared configuration! User directory updates allow REST endpoints matching the following regular expressions to work: ^/_matrix/client/(r0|v3|unstable)/user_directory/search$ The above endpoints can be routed to any worker, though you may choose to route it to the chosen user directory worker. This style of configuration supersedes the legacy synapse.app.user_dir worker application type. Notifying Application Services You can designate one generic worker to send output traffic to Application Services. Doesn't handle any REST endpoints itself, but you should specify its name in the shared configuration as follows: notify_appservices_from_worker: worker_name This work cannot be load-balanced; please ensure the main process is restarted after setting this option in the shared configuration! This style of configuration supersedes the legacy synapse.app.appservice worker application type. Push Notifications You can designate generic workers to send push notifications to a push gateway such as sygnal and email. This will stop the main process sending push notifications. The workers responsible for sending push notifications can be defined using the pusher_instances option. For example: pusher_instances: - pusher_worker1 - pusher_worker2 Multiple workers can be added to this map, in which case the work is balanced across them. Ensure the main process and all pusher workers are restarted after changing this option. These workers don't need to accept incoming HTTP requests to send push notifications, so no additional reverse proxy configuration is required for pusher workers. This style of configuration supersedes the legacy synapse.app.pusher worker application type.","breadcrumbs":"Configuration » Workers » synapse.app.generic_worker","id":"684","title":"synapse.app.generic_worker"},"685":{"body":"It is likely this option will be deprecated in the future and is not recommended for new installations. Instead, use synapse.app.generic_worker with the pusher_instances . Handles sending push notifications to sygnal and email. Doesn't handle any REST endpoints itself, but you should set start_pushers: false in the shared configuration file to stop the main synapse sending push notifications. To run multiple instances at once the pusher_instances option should list all pusher instances by their worker_name , e.g.: start_pushers: false\npusher_instances: - pusher_worker1 - pusher_worker2 An example for a pusher instance: worker_app: synapse.app.pusher\nworker_name: pusher_worker1 worker_log_config: /etc/matrix-synapse/pusher-worker-log.yaml","breadcrumbs":"Configuration » Workers » synapse.app.pusher","id":"685","title":"synapse.app.pusher"},"686":{"body":"Deprecated as of Synapse v1.59. Use synapse.app.generic_worker with the notify_appservices_from_worker option instead. Handles sending output traffic to Application Services. Doesn't handle any REST endpoints itself, but you should set notify_appservices: False in the shared configuration file to stop the main synapse sending appservice notifications. Note this worker cannot be load-balanced: only one instance should be active.","breadcrumbs":"Configuration » Workers » synapse.app.appservice","id":"686","title":"synapse.app.appservice"},"687":{"body":"It is likely this option will be deprecated in the future and not recommended for new installations. Instead, use synapse.app.generic_worker with the federation_sender_instances . Handles sending federation traffic to other servers. Doesn't handle any REST endpoints itself, but you should set send_federation: false in the shared configuration file to stop the main synapse sending this traffic. If running multiple federation senders then you must list each instance in the federation_sender_instances option by their worker_name . All instances must be stopped and started when adding or removing instances. For example: send_federation: false\nfederation_sender_instances: - federation_sender1 - federation_sender2 An example for a federation sender instance: worker_app: synapse.app.federation_sender\nworker_name: federation_sender1 worker_log_config: /etc/matrix-synapse/federation-sender-log.yaml","breadcrumbs":"Configuration » Workers » synapse.app.federation_sender","id":"687","title":"synapse.app.federation_sender"},"688":{"body":"Handles the media repository. It can handle all endpoints starting with: /_matrix/media/\n/_matrix/client/v1/media/\n/_matrix/federation/v1/media/ ... and the following regular expressions matching media-specific administration APIs: ^/_synapse/admin/v1/purge_media_cache$\n^/_synapse/admin/v1/room/.*/media.*$\n^/_synapse/admin/v1/user/.*/media.*$\n^/_synapse/admin/v1/media/.*$\n^/_synapse/admin/v1/quarantine_media/.*$\n^/_synapse/admin/v1/users/.*/media$ You should also set enable_media_repo: False in the shared configuration file to stop the main synapse running background jobs related to managing the media repository. Note that doing so will prevent the main process from being able to handle the above endpoints. In the media_repository worker configuration file, configure the HTTP listener to expose the media resource. For example: worker_app: synapse.app.media_repository\nworker_name: media_worker worker_listeners: - type: http port: 8085 x_forwarded: true resources: - names: [media] worker_log_config: /etc/matrix-synapse/media-worker-log.yaml Note that if running multiple media repositories they must be on the same server and you must specify a single instance to run the background tasks in the shared configuration , e.g.: media_instance_running_background_jobs: \"media-repository-1\" Note that if a reverse proxy is used , then /_matrix/media/ must be routed for both inbound client and federation requests (if they are handled separately).","breadcrumbs":"Configuration » Workers » synapse.app.media_repository","id":"688","title":"synapse.app.media_repository"},"689":{"body":"Deprecated as of Synapse v1.59. Use synapse.app.generic_worker with the update_user_directory_from_worker option instead. Handles searches in the user directory. It can handle REST endpoints matching the following regular expressions: ^/_matrix/client/(r0|v3|unstable)/user_directory/search$ When using this worker you must also set update_user_directory: false in the shared configuration file to stop the main synapse running background jobs related to updating the user directory. Above endpoint is not required to be routed to this worker. By default, update_user_directory is set to true, which means the main process will handle updates. All workers configured with client can handle the above endpoint as long as either this worker or the main process are configured to handle it, and are online. If update_user_directory is set to false, and this worker is not running, the above endpoint may give outdated results.","breadcrumbs":"Configuration » Workers » synapse.app.user_dir","id":"689","title":"synapse.app.user_dir"},"69":{"body":"You need to read all of the upgrade notes for each version between your current version and the latest so that you can update your dependencies, environment, config files, etc. if necessary. But you do not need to perform an upgrade to each individual version that was missed. We do not have a list of which versions must be installed. Instead, we recommend that you upgrade through each incompatible database schema version, which would give you the ability to roll back the maximum number of versions should anything go wrong. See Rolling back to older versions above. Additionally, new versions of Synapse will occasionally run database migrations and background updates to update the database. Synapse will not start until database migrations are complete. You should wait until background updates from each upgrade are complete before moving on to the next upgrade, to avoid stacking them up. You can monitor the currently running background updates with the Admin API .","breadcrumbs":"Upgrading between Synapse Versions » Upgrading from a very old version","id":"69","title":"Upgrading from a very old version"},"690":{"body":"The following used to be separate worker application types, but are now equivalent to synapse.app.generic_worker: synapse.app.client_reader synapse.app.event_creator synapse.app.federation_reader synapse.app.federation_sender synapse.app.frontend_proxy synapse.app.pusher synapse.app.synchrotron","breadcrumbs":"Configuration » Workers » Historical apps","id":"690","title":"Historical apps"},"691":{"body":"A main change that has occurred is the merging of worker apps into synapse.app.generic_worker. This change is backwards compatible and so no changes to the config are required. To migrate apps to use synapse.app.generic_worker simply update the worker_app option in the worker configs, and where worker are started (e.g. in systemd service files, but not required for synctl).","breadcrumbs":"Configuration » Workers » Migration from old config","id":"691","title":"Migration from old config"},"692":{"body":"The following shows an example setup using Redis and a reverse proxy: Clients & Federation | v +-----------+ | | | Reverse | | Proxy | | | +-----------+ | | | | | | HTTP requests +-------------------+ | +-----------+ | +---+ | | | | v v v\n+--------------+ +--------------+ +--------------+ +--------------+\n| Main | | Generic | | Generic | | Event |\n| Process | | Worker 1 | | Worker 2 | | Persister |\n+--------------+ +--------------+ +--------------+ +--------------+ ^ ^ | ^ | | ^ | | ^ ^ | | | | | | | | | | | | | | | | HTTP | | | | | | | +----------+<--|---|---------+<--|---|---------+ | | | | +-------------|-->+-------------+ | | | | | | | | | v v v v\n====================================================================== Redis pub/sub channel","breadcrumbs":"Configuration » Workers » Architectural diagram","id":"692","title":"Architectural diagram"},"693":{"body":"If you want to use synctl to manage your synapse processes, you will need to create an an additional configuration file for the main synapse process. That configuration should look like this: worker_app: synapse.app.homeserver Additionally, each worker app must be configured with the name of a \"pid file\", to which it will write its process ID when it starts. For example, for a synchrotron, you might write: worker_pid_file: /home/matrix/synapse/worker1.pid Finally, to actually run your worker-based synapse, you must pass synctl the -a commandline option to tell it to operate on all the worker configurations found in the given directory, e.g.: synctl -a $CONFIG/workers start Currently one should always restart all workers when restarting or upgrading synapse, unless you explicitly know it's safe not to. For instance, restarting synapse without restarting all the synchrotrons may result in broken typing notifications. To manipulate a specific worker, you pass the -w option to synctl: synctl -w $CONFIG/workers/worker1.yaml restart","breadcrumbs":"Configuration » Workers » Using synctl with Workers » Using synctl with workers","id":"693","title":"Using synctl with workers"},"694":{"body":"This is a setup for managing synapse with systemd, including support for managing workers. It provides a matrix-synapse service for the master, as well as a matrix-synapse-worker@ service template for any workers you require. Additionally, to group the required services, it sets up a matrix-synapse.target. See the folder system for the systemd unit files. The folder workers contains an example configuration for the generic_worker worker.","breadcrumbs":"Configuration » Workers » Systemd » Setting up Synapse with Workers and Systemd","id":"694","title":"Setting up Synapse with Workers and Systemd"},"695":{"body":"See the worker documentation for information on how to set up the configuration files and reverse-proxy correctly. Below is a sample generic_worker worker configuration file. worker_app: synapse.app.generic_worker\nworker_name: generic_worker1 worker_listeners: - type: http port: 8083 x_forwarded: true resources: - names: [client, federation] worker_log_config: /etc/matrix-synapse/generic-worker-log.yaml Systemd manages daemonization itself, so ensure that none of the configuration files set either daemonize or worker_daemonize. The config files of all workers are expected to be located in /etc/matrix-synapse/workers. If you want to use a different location, edit the provided *.service files accordingly. There is no need for a separate configuration file for the master process.","breadcrumbs":"Configuration » Workers » Systemd » Synapse configuration files","id":"695","title":"Synapse configuration files"},"696":{"body":"Adjust synapse configuration files as above. Copy the *.service and *.target files in system to /etc/systemd/system. Run systemctl daemon-reload to tell systemd to load the new unit files. Run systemctl enable matrix-synapse.service. This will configure the synapse master process to be started as part of the matrix-synapse.target target. For each worker process to be enabled, run systemctl enable matrix-synapse-worker@.service. For each , there should be a corresponding configuration file. /etc/matrix-synapse/workers/.yaml. Start all the synapse processes with systemctl start matrix-synapse.target. Tell systemd to start synapse on boot with systemctl enable matrix-synapse.target.","breadcrumbs":"Configuration » Workers » Systemd » Set up","id":"696","title":"Set up"},"697":{"body":"Once the services are correctly set up, you can use the following commands to manage your synapse installation: # Restart Synapse master and all workers\nsystemctl restart matrix-synapse.target # Stop Synapse and all workers\nsystemctl stop matrix-synapse.target # Restart the master alone\nsystemctl start matrix-synapse.service # Restart a specific worker (eg. generic_worker); the master is\n# unaffected by this.\nsystemctl restart matrix-synapse-worker@generic_worker.service # Add a new worker (assuming all configs are set up already)\nsystemctl enable matrix-synapse-worker@federation_writer.service\nsystemctl restart matrix-synapse.target","breadcrumbs":"Configuration » Workers » Systemd » Usage","id":"697","title":"Usage"},"698":{"body":"Optional: If further hardening is desired, the file override-hardened.conf may be copied from contrib/systemd/override-hardened.conf in this repository to the location /etc/systemd/system/matrix-synapse.service.d/override-hardened.conf (the directory may have to be created). It enables certain sandboxing features in systemd to further secure the synapse service. You may read the comments to understand what the override file is doing. The same file will need to be copied to /etc/systemd/system/matrix-synapse-worker@.service.d/override-hardened-worker.conf (this directory may also have to be created) in order to apply the same hardening options to any worker processes. Once these files have been copied to their appropriate locations, simply reload systemd's manager config files and restart all Synapse services to apply the hardening options. They will automatically be applied at every restart as long as the override files are present at the specified locations. systemctl daemon-reload # Restart services\nsystemctl restart matrix-synapse.target In order to see their effect, you may run systemd-analyze security matrix-synapse.service before and after applying the hardening options to see the changes being applied at a glance.","breadcrumbs":"Configuration » Workers » Systemd » Hardening","id":"698","title":"Hardening"},"699":{"body":"This section contains information on managing your Synapse homeserver. This includes: Managing users, rooms and media via the Admin API. Setting up metrics and monitoring to give you insight into your homeserver's health. Configuring structured logging.","breadcrumbs":"Administration » Administration","id":"699","title":"Administration"},"7":{"body":"Prebuilt packages are available for a number of platforms. These are recommended for most users. Docker images and Ansible playbooks There is an official synapse image available at https://hub.docker.com/r/matrixdotorg/synapse or at ghcr.io/element-hq/synapse which can be used with the docker-compose file available at contrib/docker . Further information on this including configuration options is available in the README on hub.docker.com. Alternatively, Andreas Peters (previously Silvio Fricke) has contributed a Dockerfile to automate a synapse server in a single Docker image, at https://hub.docker.com/r/avhost/docker-matrix/tags/ Slavi Pantaleev has created an Ansible playbook, which installs the official Docker image of Matrix Synapse along with many other Matrix-related services (Postgres database, Element, coturn, ma1sd, SSL support, etc.). For more details, see https://github.com/spantaleev/matrix-docker-ansible-deploy Debian/Ubuntu Matrix.org packages Matrix.org provides Debian/Ubuntu packages of Synapse, for the amd64 architecture via https://packages.matrix.org/debian/ . To install the latest release: sudo apt install -y lsb-release wget apt-transport-https\nsudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg\necho \"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\nsudo apt update\nsudo apt install matrix-synapse-py3 Packages are also published for release candidates. To enable the prerelease channel, add prerelease to the sources.list line. For example: sudo wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg\necho \"deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main prerelease\" | sudo tee /etc/apt/sources.list.d/matrix-org.list\nsudo apt update\nsudo apt install matrix-synapse-py3 The fingerprint of the repository signing key (as shown by gpg /usr/share/keyrings/matrix-org-archive-keyring.gpg) is AAF9AE843A7584B5A3E4CD2BCF45A512DE2DA058. When installing with Debian packages, you might prefer to place files in /etc/matrix-synapse/conf.d/ to override your configuration without editing the main configuration file at /etc/matrix-synapse/homeserver.yaml. By doing that, you won't be asked if you want to replace your configuration file when you upgrade the Debian package to a later version. Downstream Debian packages Andrej Shadura maintains a matrix-synapse package in the Debian repositories. For bookworm and sid, it can be installed simply with: sudo apt install matrix-synapse Synapse is also available in bullseye-backports. Please see the Debian documentation for information on how to use backports. matrix-synapse is no longer maintained for buster and older. Downstream Ubuntu packages We do not recommend using the packages in the default Ubuntu repository at this time, as they are old and suffer from known security vulnerabilities . The latest version of Synapse can be installed from our repository . Fedora Synapse is in the Fedora repositories as matrix-synapse : sudo dnf install matrix-synapse Additionally, Oleg Girko provides Fedora RPMs at https://obs.infoserver.lv/project/monitor/matrix-synapse OpenSUSE Synapse is in the OpenSUSE repositories as matrix-synapse : sudo zypper install matrix-synapse SUSE Linux Enterprise Server Unofficial package are built for SLES 15 in the openSUSE:Backports:SLE-15 repository at https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15/standard/ ArchLinux The quickest way to get up and running with ArchLinux is probably with the package provided by ArchLinux https://archlinux.org/packages/extra/x86_64/matrix-synapse/ , which should pull in most of the necessary dependencies. pip may be outdated (6.0.7-1 and needs to be upgraded to 6.0.8-1 ): sudo pip install --upgrade pip If you encounter an error with lib bcrypt causing an Wrong ELF Class: ELFCLASS32 (x64 Systems), you may need to reinstall py-bcrypt to correctly compile it under the right architecture. (This should not be needed if installing under virtualenv): sudo pip uninstall py-bcrypt\nsudo pip install py-bcrypt Alpine Linux Jahway603 maintains Synapse packages for Alpine Linux in the community repository. Install with: sudo apk add synapse Void Linux Synapse can be found in the void repositories as 'synapse' : xbps-install -Su\nxbps-install -S synapse FreeBSD Synapse can be installed via FreeBSD Ports or Packages contributed by Brendan Molloy from: Ports: cd /usr/ports/net-im/py-matrix-synapse && make install clean Packages: pkg install py38-matrix-synapse OpenBSD As of OpenBSD 6.7 Synapse is available as a pre-compiled binary. The filesystem underlying the homeserver directory (defaults to /var/synapse) has to be mounted with wxallowed (cf. mount(8)), so creating a separate filesystem and mounting it to /var/synapse should be taken into consideration. Installing Synapse: doas pkg_add synapse NixOS Robin Lambertz has packaged Synapse for NixOS at: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/matrix/synapse.nix","breadcrumbs":"Installation » Prebuilt packages","id":"7","title":"Prebuilt packages"},"70":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.130.0","id":"70","title":"Upgrading to v1.130.0"},"700":{"body":"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.","breadcrumbs":"Administration » Backups » How to back up a Synapse homeserver","id":"700","title":"How to back up a Synapse homeserver"},"701":{"body":"Keep a copy of your configuration file (homeserver.yaml), as well as any auxiliary config files it refers to such as the log_config file, 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.","breadcrumbs":"Administration » Backups » Configuration files","id":"701","title":"Configuration files"},"702":{"body":"Your server has a signing key 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 .","breadcrumbs":"Administration » Backups » Server signing key","id":"702","title":"Server signing key"},"703":{"body":"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 . A full discussion of backup strategies for PostgreSQL is out of scope for this document; see the PostgreSQL documentation for detailed information.","breadcrumbs":"Administration » Backups » Database","id":"703","title":"Database"},"704":{"body":"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 TRUNCATEd 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 . 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.]","breadcrumbs":"Administration » Backups » Synapse-specfic details","id":"704","title":"Synapse-specfic details"},"705":{"body":"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. 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 , then load the dump into it with pg_restore: sudo -u postgres createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse_user synapse\nsudo -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.","breadcrumbs":"Administration » Backups » Quick and easy database backup and restore","id":"705","title":"Quick and easy database backup and restore"},"706":{"body":"Synapse keeps a copy of media uploaded by users, including avatars and message attachments, in its 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 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 feature. These do not need to be backed up.","breadcrumbs":"Administration » Backups » Media store","id":"706","title":"Media store"},"707":{"body":"","breadcrumbs":"Administration » Admin API » The Admin API","id":"707","title":"The Admin API"},"708":{"body":"Many of the API calls in the admin api will require an access_token for a server admin. (Note that a server admin is distinct from a room admin.) An existing user can be marked as a server admin by updating the database directly. Check your database settings in the configuration file, connect to the correct database using either psql [database name] (if using PostgreSQL) or sqlite3 path/to/your/database.db (if using SQLite) and elevate the user @foo:bar.com to administrator. UPDATE users SET admin = 1 WHERE name = '@foo:bar.com'; A new server admin user can also be created using the register_new_matrix_user command. This is a script that is distributed as part of synapse. It is possibly already on your $PATH depending on how Synapse was installed. Finding your user's access_token is client-dependent, but will usually be shown in the client's settings.","breadcrumbs":"Administration » Admin API » Authenticate as a server admin","id":"708","title":"Authenticate as a server admin"},"709":{"body":"For security reasons, we recommend that the Admin API (/_synapse/admin/...) should be hidden from public view using a reverse proxy. This means you should typically query the Admin API from a terminal on the machine which runs Synapse. Once you have your access_token, you will need to authenticate each request to an Admin API endpoint by providing the token as either a query parameter or a request header. To add it as a request header in cURL: curl --header \"Authorization: Bearer \" For example, suppose we want to query the account of the user @foo:bar.com. We need an admin access token (e.g. syt_AjfVef2_L33JNpafeif_0feKJfeaf0CQpoZk), and we need to know which port Synapse's client listener is listening on (e.g. 8008). Then we can use the following command to request the account information from the Admin API. curl --header \"Authorization: Bearer syt_AjfVef2_L33JNpafeif_0feKJfeaf0CQpoZk\" -X GET http://127.0.0.1:8008/_synapse/admin/v2/users/@foo:bar.com For more details on access tokens in Matrix, please refer to the complete matrix spec documentation .","breadcrumbs":"Administration » Admin API » Making an Admin API request","id":"709","title":"Making an Admin API request"},"71":{"body":"The endpoint ^/_matrix/federation/v1/version$ can be delegated to a federation worker. This is not new behaviour, but had not been documented yet. The list of delegatable endpoints has been updated to include it. Make sure to check your reverse proxy rules if you are using workers.","breadcrumbs":"Upgrading between Synapse Versions » Documented endpoint which can be delegated to a federation worker","id":"71","title":"Documented endpoint which can be delegated to a federation worker"},"710":{"body":"Note: This API is disabled when MSC3861 is enabled. See #15582 This API allows a server administrator to manage the validity of an account. To use it, you must enable the account validity feature (under account_validity) in Synapse's configuration. To use it, you will need to authenticate by providing an access_token for a server admin: see Admin API .","breadcrumbs":"Administration » Admin API » Account Validity » Account validity API","id":"710","title":"Account validity API"},"711":{"body":"This API extends the validity of an account by as much time as configured in the period parameter from the account_validity configuration. The API is: POST /_synapse/admin/v1/account_validity/validity with the following body: { \"user_id\": \"\", \"expiration_ts\": 0, \"enable_renewal_emails\": true\n} expiration_ts is an optional parameter and overrides the expiration date, which otherwise defaults to now + validity period. enable_renewal_emails is also an optional parameter and enables/disables sending renewal emails to the user. Defaults to true. The API returns with the new expiration date for this account, as a timestamp in milliseconds since epoch: { \"expiration_ts\": 0\n}","breadcrumbs":"Administration » Admin API » Account Validity » Renew account","id":"711","title":"Renew account"},"712":{"body":"This API allows a server administrator to manage the background updates being run against the database.","breadcrumbs":"Administration » Admin API » Background Updates » Background Updates API","id":"712","title":"Background Updates API"},"713":{"body":"This API gets the current status of the background updates. The API is: GET /_synapse/admin/v1/background_updates/status Returning: { \"enabled\": true, \"current_updates\": { \"\": { \"name\": \"\", \"total_item_count\": 50, \"total_duration_ms\": 10000.0, \"average_items_per_ms\": 2.2, }, }\n} enabled whether the background updates are enabled or disabled. db_name the database name (usually Synapse is configured with a single database named 'master'). For each update: name the name of the update. total_item_count total number of \"items\" processed (the meaning of 'items' depends on the update in question). total_duration_ms how long the background process has been running, not including time spent sleeping. average_items_per_ms how many items are processed per millisecond based on an exponential average.","breadcrumbs":"Administration » Admin API » Background Updates » Status","id":"713","title":"Status"},"714":{"body":"This API allows pausing background updates. Background updates should not be paused for significant periods of time, as this can affect the performance of Synapse. Note : This won't persist over restarts. Note : This won't cancel any update query that is currently running. This is usually fine since most queries are short lived, except for CREATE INDEX background updates which won't be cancelled once started. The API is: POST /_synapse/admin/v1/background_updates/enabled with the following body: { \"enabled\": false\n} enabled sets whether the background updates are enabled or disabled. The API returns the enabled param. { \"enabled\": false\n} There is also a GET version which returns the enabled state.","breadcrumbs":"Administration » Admin API » Background Updates » Enabled","id":"714","title":"Enabled"},"715":{"body":"This API schedules a specific background update to run. The job starts immediately after calling the API. The API is: POST /_synapse/admin/v1/background_updates/start_job with the following body: { \"job_name\": \"populate_stats_process_rooms\"\n} The following JSON body parameters are available: job_name - A string which job to run. Valid values are: populate_stats_process_rooms - Recalculate the stats for all rooms. regenerate_directory - Recalculate the user directory if it is stale or out of sync.","breadcrumbs":"Administration » Admin API » Background Updates » Run","id":"715","title":"Run"},"716":{"body":"This API returns information about reported events. To use it, you will need to authenticate by providing an access_token for a server admin: see Admin API . The api is: GET /_synapse/admin/v1/event_reports?from=0&limit=10 It returns a JSON body like the following: { \"event_reports\": [ { \"event_id\": \"$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY\", \"id\": 2, \"reason\": \"foo\", \"score\": -100, \"received_ts\": 1570897107409, \"canonical_alias\": \"#alias1:matrix.org\", \"room_id\": \"!ERAgBpSOcCCuTJqQPk:matrix.org\", \"name\": \"Matrix HQ\", \"sender\": \"@foobar:matrix.org\", \"user_id\": \"@foo:matrix.org\" }, { \"event_id\": \"$3IcdZsDaN_En-S1DF4EMCy3v4gNRKeOJs8W5qTOKj4I\", \"id\": 3, \"reason\": \"bar\", \"score\": -100, \"received_ts\": 1598889612059, \"canonical_alias\": \"#alias2:matrix.org\", \"room_id\": \"!eGvUQuTCkHGVwNMOjv:matrix.org\", \"name\": \"Your room name here\", \"sender\": \"@foobar:matrix.org\", \"user_id\": \"@bar:matrix.org\" } ], \"next_token\": 2, \"total\": 4\n} To paginate, check for next_token and if present, call the endpoint again with from set to the value of next_token. This will return a new page. If the endpoint does not return a next_token then there are no more reports to paginate through. URL parameters: limit: integer - Is optional but is used for pagination, denoting the maximum number of items to return in this call. Defaults to 100. from: integer - Is optional but used for pagination, denoting the offset in the returned results. This should be treated as an opaque value and not explicitly set to anything other than the return value of next_token from a previous call. Defaults to 0. dir: string - Direction of event report order. Whether to fetch the most recent first (b) or the oldest first (f). Defaults to b. user_id: optional string - Filter by the user ID of the reporter. This is the user who reported the event and wrote the reason. room_id: optional string - Filter by room id. event_sender_user_id: optional string - Filter by the sender of the reported event. This is the user who the report was made against. Response The following fields are returned in the JSON response body: id: integer - ID of event report. received_ts: integer - The timestamp (in milliseconds since the unix epoch) when this report was sent. room_id: string - The ID of the room in which the event being reported is located. name: string - The name of the room. event_id: string - The ID of the reported event. user_id: string - This is the user who reported the event and wrote the reason. reason: string - Comment made by the user_id in this report. May be blank or null. score: integer - Content is reported based upon a negative score, where -100 is \"most offensive\" and 0 is \"inoffensive\". May be null. sender: string - This is the ID of the user who sent the original message/event that was reported. canonical_alias: string - The canonical alias of the room. null if the room does not have a canonical alias set. next_token: integer - Indication for pagination. See above. total: integer - Total number of event reports related to the query (user_id and room_id).","breadcrumbs":"Administration » Admin API » Event Reports » Show reported events","id":"716","title":"Show reported events"},"717":{"body":"This API returns information about a specific event report. The api is: GET /_synapse/admin/v1/event_reports/ It returns a JSON body like the following: { \"event_id\": \"$bNUFCwGzWca1meCGkjp-zwslF-GfVcXukvRLI1_FaVY\", \"event_json\": { \"auth_events\": [ \"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M\", \"$oggsNXxzPFRE3y53SUNd7nsj69-QzKv03a1RucHu-ws\" ], \"content\": { \"body\": \"matrix.org: This Week in Matrix\", \"format\": \"org.matrix.custom.html\", \"formatted_body\": \"matrix.org:
This Week in Matrix\", \"msgtype\": \"m.notice\" }, \"depth\": 546, \"hashes\": { \"sha256\": \"xK1//xnmvHJIOvbgXlkI8eEqdvoMmihVDJ9J4SNlsAw\" }, \"origin\": \"matrix.org\", \"origin_server_ts\": 1592291711430, \"prev_events\": [ \"$YK4arsKKcc0LRoe700pS8DSjOvUT4NDv0HfInlMFw2M\" ], \"prev_state\": [], \"room_id\": \"!ERAgBpSOcCCuTJqQPk:matrix.org\", \"sender\": \"@foobar:matrix.org\", \"signatures\": { \"matrix.org\": { \"ed25519:a_JaEG\": \"cs+OUKW/iHx5pEidbWxh0UiNNHwe46Ai9LwNz+Ah16aWDNszVIe2gaAcVZfvNsBhakQTew51tlKmL2kspXk/Dg\" } }, \"type\": \"m.room.message\", \"unsigned\": { \"age_ts\": 1592291711430 } }, \"id\": , \"reason\": \"foo\", \"score\": -100, \"received_ts\": 1570897107409, \"canonical_alias\": \"#alias1:matrix.org\", \"room_id\": \"!ERAgBpSOcCCuTJqQPk:matrix.org\", \"name\": \"Matrix HQ\", \"sender\": \"@foobar:matrix.org\", \"user_id\": \"@foo:matrix.org\"\n} URL parameters: report_id: string - The ID of the event report. Response The following fields are returned in the JSON response body: id: integer - ID of event report. received_ts: integer - The timestamp (in milliseconds since the unix epoch) when this report was sent. room_id: string - The ID of the room in which the event being reported is located. name: string - The name of the room. event_id: string - The ID of the reported event. user_id: string - This is the user who reported the event and wrote the reason. reason: string - Comment made by the user_id in this report. May be blank. score: integer - Content is reported based upon a negative score, where -100 is \"most offensive\" and 0 is \"inoffensive\". sender: string - This is the ID of the user who sent the original message/event that was reported. canonical_alias: string - The canonical alias of the room. null if the room does not have a canonical alias set. event_json: object - Details of the original event that was reported.","breadcrumbs":"Administration » Admin API » Event Reports » Show details of a specific event report","id":"717","title":"Show details of a specific event report"},"718":{"body":"This API deletes a specific event report. If the request is successful, the response body will be an empty JSON object. The api is: DELETE /_synapse/admin/v1/event_reports/ URL parameters: report_id: string - The ID of the event report.","breadcrumbs":"Administration » Admin API » Event Reports » Delete a specific event report","id":"718","title":"Delete a specific event report"},"719":{"body":"This API allows a server administrator to enable or disable some experimental features on a per-user basis. The currently supported features are: MSC3881 : enable remotely toggling push notifications for another client MSC3575 : enable experimental sliding sync support MSC4222 : adding state_after to sync v2 To use it, you will need to authenticate by providing an access_token for a server admin: see Admin API .","breadcrumbs":"Administration » Admin API » Experimental Features » Experimental Features API","id":"719","title":"Experimental Features API"},"72":{"body":"","breadcrumbs":"Upgrading between Synapse Versions » Upgrading to v1.126.0","id":"72","title":"Upgrading to v1.126.0"},"720":{"body":"This API allows a server administrator to enable experimental features for a given user. The request must provide a body containing the user id and listing the features to enable/disable in the following format: { \"features\": { \"msc3026\":true, \"msc3881\":true }\n} where true is used to enable the feature, and false is used to disable the feature. The API is: PUT /_synapse/admin/v1/experimental_features/