mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2024-10-01 11:49:51 -04:00
158d73ebdd
Revert "Sort internal changes in changelog" Revert "Update CHANGES.md" Revert "1.49.0rc1" Revert "Revert "Move `glob_to_regex` and `re_word_boundary` to `matrix-python-common` (#11505) (#11527)" Revert "Refactors in `_generate_sync_entry_for_rooms` (#11515)" Revert "Correctly register shutdown handler for presence workers (#11518)" Revert "Fix `ModuleApi.looping_background_call` for non-async functions (#11524)" Revert "Fix 'delete room' admin api to work on incomplete rooms (#11523)" Revert "Correctly ignore invites from ignored users (#11511)" Revert "Fix the test breakage introduced by #11435 as a result of concurrent PRs (#11522)" Revert "Stabilise support for MSC2918 refresh tokens as they have now been merged into the Matrix specification. (#11435)" Revert "Save the OIDC session ID (sid) with the device on login (#11482)" Revert "Add admin API to get some information about federation status (#11407)" Revert "Include bundled aggregations in /sync and related fixes (#11478)" Revert "Move `glob_to_regex` and `re_word_boundary` to `matrix-python-common` (#11505)" Revert "Update backward extremity docs to make it clear that it does not indicate whether we have fetched an events' `prev_events` (#11469)" Revert "Support configuring the lifetime of non-refreshable access tokens separately to refreshable access tokens. (#11445)" Revert "Add type hints to `synapse/tests/rest/admin` (#11501)" Revert "Revert accidental commits to develop." Revert "Newsfile" Revert "Give `tests.server.setup_test_homeserver` (nominally!) the same behaviour" Revert "Move `tests.utils.setup_test_homeserver` to `tests.server`" Revert "Convert one of the `setup_test_homeserver`s to `make_test_homeserver_synchronous`" Revert "Disambiguate queries on `state_key` (#11497)" Revert "Comments on the /sync tentacles (#11494)" Revert "Clean up tests.storage.test_appservice (#11492)" Revert "Clean up `tests.storage.test_main` to remove use of legacy code. (#11493)" Revert "Clean up `tests.test_visibility` to remove legacy code. (#11495)" Revert "Minor cleanup on recently ported doc pages (#11466)" Revert "Add most of the missing type hints to `synapse.federation`. (#11483)" Revert "Avoid waiting for zombie processes in `synctl stop` (#11490)" Revert "Fix media repository failing when media store path contains symlinks (#11446)" Revert "Add type annotations to `tests.storage.test_appservice`. (#11488)" Revert "`scripts-dev/sign_json`: support for signing events (#11486)" Revert "Add MSC3030 experimental client and federation API endpoints to get the closest event to a given timestamp (#9445)" Revert "Port wiki pages to documentation website (#11402)" Revert "Add a license header and comment. (#11479)" Revert "Clean-up get_version_string (#11468)" Revert "Link background update controller docs to summary (#11475)" Revert "Additional type hints for config module. (#11465)" Revert "Register the login redirect endpoint for v3. (#11451)" Revert "Update openid.md" Revert "Remove mention of OIDC certification from Dex (#11470)" Revert "Add a note about huge pages to our Postgres doc (#11467)" Revert "Don't start Synapse master process if `worker_app` is set (#11416)" Revert "Expose worker & homeserver as entrypoints in `setup.py` (#11449)" Revert "Bundle relations of relations into the `/relations` result. (#11284)" Revert "Fix `LruCache` corruption bug with a `size_callback` that can return 0 (#11454)" Revert "Eliminate a few `Any`s in `LruCache` type hints (#11453)" Revert "Remove unnecessary `json.dumps` from `tests.rest.admin` (#11461)" Revert "Merge branch 'master' into develop" This reverts commit26b5d2320f
. This reverts commitbce4220f38
. This reverts commit966b5d0fa0
. This reverts commit088d748f2c
. This reverts commit14d593f72d
. This reverts commit2a3ec6facf
. This reverts commiteccc49d755
. This reverts commitb1ecd19c5d
. This reverts commit9c55dedc8c
. This reverts commit2d42e586a8
. This reverts commit2f053f3f82
. This reverts commita15a893df8
. This reverts commit8b4b153c9e
. This reverts commit494ebd7347
. This reverts commita77c369897
. This reverts commit4eb77965cd
. This reverts commit637df95de6
. This reverts commite5f426cd54
. This reverts commit8cd68b8102
. This reverts commit6cae125e20
. This reverts commit7be88fbf48
. This reverts commitb3fd99b74a
. This reverts commitf7ec6e7d9e
. This reverts commit5640992d17
. This reverts commitd26808dd85
. This reverts commitf91624a595
. This reverts commit16d39a5490
. This reverts commit8a4c296987
. This reverts commit49e1356ee3
. This reverts commitd2279f471b
. This reverts commitb50e39df57
. This reverts commit858d80bf0f
. This reverts commit435f044807
. This reverts commitf61462e1be
. This reverts commita6f1a3abec
. This reverts commit84dc50e160
. This reverts commited635d3285
. This reverts commit7b62791e00
. This reverts commit153194c771
. This reverts commitf44d729d4c
. This reverts commita265fbd397
. This reverts commitb9fef1a7cd
. This reverts commitb0eb64ff7b
. This reverts commitf1795463bf
. This reverts commit70cbb1a5e3
. This reverts commit42bf020463
. This reverts commit379f2650cf
. This reverts commit7ff22d6da4
. This reverts commit5a0b652d36
. This reverts commit432a174bc1
. This reverts commitb14f8a1baf
, reversing changes made toe713855dca
.
559 lines
20 KiB
Python
Executable File
559 lines
20 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# This script reads environment variables and generates a shared Synapse worker,
|
|
# nginx and supervisord configs depending on the workers requested.
|
|
#
|
|
# The environment variables it reads are:
|
|
# * SYNAPSE_SERVER_NAME: The desired server_name of the homeserver.
|
|
# * SYNAPSE_REPORT_STATS: Whether to report stats.
|
|
# * SYNAPSE_WORKER_TYPES: A comma separated list of worker names as specified in WORKER_CONFIG
|
|
# below. Leave empty for no workers, or set to '*' for all possible workers.
|
|
#
|
|
# NOTE: According to Complement's ENTRYPOINT expectations for a homeserver image (as defined
|
|
# in the project's README), this script may be run multiple times, and functionality should
|
|
# continue to work if so.
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
import jinja2
|
|
import yaml
|
|
|
|
MAIN_PROCESS_HTTP_LISTENER_PORT = 8080
|
|
|
|
|
|
WORKERS_CONFIG = {
|
|
"pusher": {
|
|
"app": "synapse.app.pusher",
|
|
"listener_resources": [],
|
|
"endpoint_patterns": [],
|
|
"shared_extra_conf": {"start_pushers": False},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"user_dir": {
|
|
"app": "synapse.app.user_dir",
|
|
"listener_resources": ["client"],
|
|
"endpoint_patterns": [
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/user_directory/search$"
|
|
],
|
|
"shared_extra_conf": {"update_user_directory": False},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"media_repository": {
|
|
"app": "synapse.app.media_repository",
|
|
"listener_resources": ["media"],
|
|
"endpoint_patterns": [
|
|
"^/_matrix/media/",
|
|
"^/_synapse/admin/v1/purge_media_cache$",
|
|
"^/_synapse/admin/v1/room/.*/media.*$",
|
|
"^/_synapse/admin/v1/user/.*/media.*$",
|
|
"^/_synapse/admin/v1/media/.*$",
|
|
"^/_synapse/admin/v1/quarantine_media/.*$",
|
|
],
|
|
"shared_extra_conf": {"enable_media_repo": False},
|
|
"worker_extra_conf": "enable_media_repo: true",
|
|
},
|
|
"appservice": {
|
|
"app": "synapse.app.appservice",
|
|
"listener_resources": [],
|
|
"endpoint_patterns": [],
|
|
"shared_extra_conf": {"notify_appservices": False},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"federation_sender": {
|
|
"app": "synapse.app.federation_sender",
|
|
"listener_resources": [],
|
|
"endpoint_patterns": [],
|
|
"shared_extra_conf": {"send_federation": False},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"synchrotron": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": ["client"],
|
|
"endpoint_patterns": [
|
|
"^/_matrix/client/(v2_alpha|r0|v3)/sync$",
|
|
"^/_matrix/client/(api/v1|v2_alpha|r0|v3)/events$",
|
|
"^/_matrix/client/(api/v1|r0|v3)/initialSync$",
|
|
"^/_matrix/client/(api/v1|r0|v3)/rooms/[^/]+/initialSync$",
|
|
],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"federation_reader": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": ["federation"],
|
|
"endpoint_patterns": [
|
|
"^/_matrix/federation/(v1|v2)/event/",
|
|
"^/_matrix/federation/(v1|v2)/state/",
|
|
"^/_matrix/federation/(v1|v2)/state_ids/",
|
|
"^/_matrix/federation/(v1|v2)/backfill/",
|
|
"^/_matrix/federation/(v1|v2)/get_missing_events/",
|
|
"^/_matrix/federation/(v1|v2)/publicRooms",
|
|
"^/_matrix/federation/(v1|v2)/query/",
|
|
"^/_matrix/federation/(v1|v2)/make_join/",
|
|
"^/_matrix/federation/(v1|v2)/make_leave/",
|
|
"^/_matrix/federation/(v1|v2)/send_join/",
|
|
"^/_matrix/federation/(v1|v2)/send_leave/",
|
|
"^/_matrix/federation/(v1|v2)/invite/",
|
|
"^/_matrix/federation/(v1|v2)/query_auth/",
|
|
"^/_matrix/federation/(v1|v2)/event_auth/",
|
|
"^/_matrix/federation/(v1|v2)/exchange_third_party_invite/",
|
|
"^/_matrix/federation/(v1|v2)/user/devices/",
|
|
"^/_matrix/federation/(v1|v2)/get_groups_publicised$",
|
|
"^/_matrix/key/v2/query",
|
|
],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"federation_inbound": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": ["federation"],
|
|
"endpoint_patterns": ["/_matrix/federation/(v1|v2)/send/"],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"event_persister": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": ["replication"],
|
|
"endpoint_patterns": [],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"background_worker": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": [],
|
|
"endpoint_patterns": [],
|
|
# This worker cannot be sharded. Therefore there should only ever be one background
|
|
# worker, and it should be named background_worker1
|
|
"shared_extra_conf": {"run_background_tasks_on": "background_worker1"},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"event_creator": {
|
|
"app": "synapse.app.generic_worker",
|
|
"listener_resources": ["client"],
|
|
"endpoint_patterns": [
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/redact",
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/send",
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/rooms/.*/(join|invite|leave|ban|unban|kick)$",
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/join/",
|
|
"^/_matrix/client/(api/v1|r0|v3|unstable)/profile/",
|
|
],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": "",
|
|
},
|
|
"frontend_proxy": {
|
|
"app": "synapse.app.frontend_proxy",
|
|
"listener_resources": ["client", "replication"],
|
|
"endpoint_patterns": ["^/_matrix/client/(api/v1|r0|v3|unstable)/keys/upload"],
|
|
"shared_extra_conf": {},
|
|
"worker_extra_conf": (
|
|
"worker_main_http_uri: http://127.0.0.1:%d"
|
|
% (MAIN_PROCESS_HTTP_LISTENER_PORT,)
|
|
),
|
|
},
|
|
}
|
|
|
|
# Templates for sections that may be inserted multiple times in config files
|
|
SUPERVISORD_PROCESS_CONFIG_BLOCK = """
|
|
[program:synapse_{name}]
|
|
command=/usr/local/bin/python -m {app} \
|
|
--config-path="{config_path}" \
|
|
--config-path=/conf/workers/shared.yaml \
|
|
--config-path=/conf/workers/{name}.yaml
|
|
autorestart=unexpected
|
|
priority=500
|
|
exitcodes=0
|
|
stdout_logfile=/dev/stdout
|
|
stdout_logfile_maxbytes=0
|
|
stderr_logfile=/dev/stderr
|
|
stderr_logfile_maxbytes=0
|
|
"""
|
|
|
|
NGINX_LOCATION_CONFIG_BLOCK = """
|
|
location ~* {endpoint} {{
|
|
proxy_pass {upstream};
|
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header Host $host;
|
|
}}
|
|
"""
|
|
|
|
NGINX_UPSTREAM_CONFIG_BLOCK = """
|
|
upstream {upstream_worker_type} {{
|
|
{body}
|
|
}}
|
|
"""
|
|
|
|
|
|
# Utility functions
|
|
def log(txt: str):
|
|
"""Log something to the stdout.
|
|
|
|
Args:
|
|
txt: The text to log.
|
|
"""
|
|
print(txt)
|
|
|
|
|
|
def error(txt: str):
|
|
"""Log something and exit with an error code.
|
|
|
|
Args:
|
|
txt: The text to log in error.
|
|
"""
|
|
log(txt)
|
|
sys.exit(2)
|
|
|
|
|
|
def convert(src: str, dst: str, **template_vars):
|
|
"""Generate a file from a template
|
|
|
|
Args:
|
|
src: Path to the input file.
|
|
dst: Path to write to.
|
|
template_vars: The arguments to replace placeholder variables in the template with.
|
|
"""
|
|
# Read the template file
|
|
with open(src) as infile:
|
|
template = infile.read()
|
|
|
|
# Generate a string from the template. We disable autoescape to prevent template
|
|
# variables from being escaped.
|
|
rendered = jinja2.Template(template, autoescape=False).render(**template_vars)
|
|
|
|
# Write the generated contents to a file
|
|
#
|
|
# We use append mode in case the files have already been written to by something else
|
|
# (for instance, as part of the instructions in a dockerfile).
|
|
with open(dst, "a") as outfile:
|
|
# In case the existing file doesn't end with a newline
|
|
outfile.write("\n")
|
|
|
|
outfile.write(rendered)
|
|
|
|
|
|
def add_sharding_to_shared_config(
|
|
shared_config: dict,
|
|
worker_type: str,
|
|
worker_name: str,
|
|
worker_port: int,
|
|
) -> None:
|
|
"""Given a dictionary representing a config file shared across all workers,
|
|
append sharded worker information to it for the current worker_type instance.
|
|
|
|
Args:
|
|
shared_config: The config dict that all worker instances share (after being converted to YAML)
|
|
worker_type: The type of worker (one of those defined in WORKERS_CONFIG).
|
|
worker_name: The name of the worker instance.
|
|
worker_port: The HTTP replication port that the worker instance is listening on.
|
|
"""
|
|
# The instance_map config field marks the workers that write to various replication streams
|
|
instance_map = shared_config.setdefault("instance_map", {})
|
|
|
|
# Worker-type specific sharding config
|
|
if worker_type == "pusher":
|
|
shared_config.setdefault("pusher_instances", []).append(worker_name)
|
|
|
|
elif worker_type == "federation_sender":
|
|
shared_config.setdefault("federation_sender_instances", []).append(worker_name)
|
|
|
|
elif worker_type == "event_persister":
|
|
# Event persisters write to the events stream, so we need to update
|
|
# the list of event stream writers
|
|
shared_config.setdefault("stream_writers", {}).setdefault("events", []).append(
|
|
worker_name
|
|
)
|
|
|
|
# Map of stream writer instance names to host/ports combos
|
|
instance_map[worker_name] = {
|
|
"host": "localhost",
|
|
"port": worker_port,
|
|
}
|
|
|
|
elif worker_type == "media_repository":
|
|
# The first configured media worker will run the media background jobs
|
|
shared_config.setdefault("media_instance_running_background_jobs", worker_name)
|
|
|
|
|
|
def generate_base_homeserver_config():
|
|
"""Starts Synapse and generates a basic homeserver config, which will later be
|
|
modified for worker support.
|
|
|
|
Raises: CalledProcessError if calling start.py returned a non-zero exit code.
|
|
"""
|
|
# start.py already does this for us, so just call that.
|
|
# note that this script is copied in in the official, monolith dockerfile
|
|
os.environ["SYNAPSE_HTTP_PORT"] = str(MAIN_PROCESS_HTTP_LISTENER_PORT)
|
|
subprocess.check_output(["/usr/local/bin/python", "/start.py", "migrate_config"])
|
|
|
|
|
|
def generate_worker_files(environ, config_path: str, data_dir: str):
|
|
"""Read the desired list of workers from environment variables and generate
|
|
shared homeserver, nginx and supervisord configs.
|
|
|
|
Args:
|
|
environ: _Environ[str]
|
|
config_path: Where to output the generated Synapse main worker config file.
|
|
data_dir: The location of the synapse data directory. Where log and
|
|
user-facing config files live.
|
|
"""
|
|
# Note that yaml cares about indentation, so care should be taken to insert lines
|
|
# into files at the correct indentation below.
|
|
|
|
# shared_config is the contents of a Synapse config file that will be shared amongst
|
|
# the main Synapse process as well as all workers.
|
|
# It is intended mainly for disabling functionality when certain workers are spun up,
|
|
# and adding a replication listener.
|
|
|
|
# First read the original config file and extract the listeners block. Then we'll add
|
|
# another listener for replication. Later we'll write out the result.
|
|
listeners = [
|
|
{
|
|
"port": 9093,
|
|
"bind_address": "127.0.0.1",
|
|
"type": "http",
|
|
"resources": [{"names": ["replication"]}],
|
|
}
|
|
]
|
|
with open(config_path) as file_stream:
|
|
original_config = yaml.safe_load(file_stream)
|
|
original_listeners = original_config.get("listeners")
|
|
if original_listeners:
|
|
listeners += original_listeners
|
|
|
|
# The shared homeserver config. The contents of which will be inserted into the
|
|
# base shared worker jinja2 template.
|
|
#
|
|
# This config file will be passed to all workers, included Synapse's main process.
|
|
shared_config = {"listeners": listeners}
|
|
|
|
# The supervisord config. The contents of which will be inserted into the
|
|
# base supervisord jinja2 template.
|
|
#
|
|
# Supervisord will be in charge of running everything, from redis to nginx to Synapse
|
|
# and all of its worker processes. Load the config template, which defines a few
|
|
# services that are necessary to run.
|
|
supervisord_config = ""
|
|
|
|
# Upstreams for load-balancing purposes. This dict takes the form of a worker type to the
|
|
# ports of each worker. For example:
|
|
# {
|
|
# worker_type: {1234, 1235, ...}}
|
|
# }
|
|
# and will be used to construct 'upstream' nginx directives.
|
|
nginx_upstreams = {}
|
|
|
|
# A map of: {"endpoint": "upstream"}, where "upstream" is a str representing what will be
|
|
# placed after the proxy_pass directive. The main benefit to representing this data as a
|
|
# dict over a str is that we can easily deduplicate endpoints across multiple instances
|
|
# of the same worker.
|
|
#
|
|
# An nginx site config that will be amended to depending on the workers that are
|
|
# spun up. To be placed in /etc/nginx/conf.d.
|
|
nginx_locations = {}
|
|
|
|
# Read the desired worker configuration from the environment
|
|
worker_types = environ.get("SYNAPSE_WORKER_TYPES")
|
|
if worker_types is None:
|
|
# No workers, just the main process
|
|
worker_types = []
|
|
else:
|
|
# Split type names by comma
|
|
worker_types = worker_types.split(",")
|
|
|
|
# Create the worker configuration directory if it doesn't already exist
|
|
os.makedirs("/conf/workers", exist_ok=True)
|
|
|
|
# Start worker ports from this arbitrary port
|
|
worker_port = 18009
|
|
|
|
# A counter of worker_type -> int. Used for determining the name for a given
|
|
# worker type when generating its config file, as each worker's name is just
|
|
# worker_type + instance #
|
|
worker_type_counter = {}
|
|
|
|
# For each worker type specified by the user, create config values
|
|
for worker_type in worker_types:
|
|
worker_type = worker_type.strip()
|
|
|
|
worker_config = WORKERS_CONFIG.get(worker_type)
|
|
if worker_config:
|
|
worker_config = worker_config.copy()
|
|
else:
|
|
log(worker_type + " is an unknown worker type! It will be ignored")
|
|
continue
|
|
|
|
new_worker_count = worker_type_counter.setdefault(worker_type, 0) + 1
|
|
worker_type_counter[worker_type] = new_worker_count
|
|
|
|
# Name workers by their type concatenated with an incrementing number
|
|
# e.g. federation_reader1
|
|
worker_name = worker_type + str(new_worker_count)
|
|
worker_config.update(
|
|
{"name": worker_name, "port": worker_port, "config_path": config_path}
|
|
)
|
|
|
|
# Update the shared config with any worker-type specific options
|
|
shared_config.update(worker_config["shared_extra_conf"])
|
|
|
|
# Check if more than one instance of this worker type has been specified
|
|
worker_type_total_count = worker_types.count(worker_type)
|
|
if worker_type_total_count > 1:
|
|
# Update the shared config with sharding-related options if necessary
|
|
add_sharding_to_shared_config(
|
|
shared_config, worker_type, worker_name, worker_port
|
|
)
|
|
|
|
# Enable the worker in supervisord
|
|
supervisord_config += SUPERVISORD_PROCESS_CONFIG_BLOCK.format_map(worker_config)
|
|
|
|
# Add nginx location blocks for this worker's endpoints (if any are defined)
|
|
for pattern in worker_config["endpoint_patterns"]:
|
|
# Determine whether we need to load-balance this worker
|
|
if worker_type_total_count > 1:
|
|
# Create or add to a load-balanced upstream for this worker
|
|
nginx_upstreams.setdefault(worker_type, set()).add(worker_port)
|
|
|
|
# Upstreams are named after the worker_type
|
|
upstream = "http://" + worker_type
|
|
else:
|
|
upstream = "http://localhost:%d" % (worker_port,)
|
|
|
|
# Note that this endpoint should proxy to this upstream
|
|
nginx_locations[pattern] = upstream
|
|
|
|
# Write out the worker's logging config file
|
|
|
|
# Check whether we should write worker logs to disk, in addition to the console
|
|
extra_log_template_args = {}
|
|
if environ.get("SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK"):
|
|
extra_log_template_args["LOG_FILE_PATH"] = "{dir}/logs/{name}.log".format(
|
|
dir=data_dir, name=worker_name
|
|
)
|
|
|
|
# Render and write the file
|
|
log_config_filepath = "/conf/workers/{name}.log.config".format(name=worker_name)
|
|
convert(
|
|
"/conf/log.config",
|
|
log_config_filepath,
|
|
worker_name=worker_name,
|
|
**extra_log_template_args,
|
|
)
|
|
|
|
# Then a worker config file
|
|
convert(
|
|
"/conf/worker.yaml.j2",
|
|
"/conf/workers/{name}.yaml".format(name=worker_name),
|
|
**worker_config,
|
|
worker_log_config_filepath=log_config_filepath,
|
|
)
|
|
|
|
worker_port += 1
|
|
|
|
# Build the nginx location config blocks
|
|
nginx_location_config = ""
|
|
for endpoint, upstream in nginx_locations.items():
|
|
nginx_location_config += NGINX_LOCATION_CONFIG_BLOCK.format(
|
|
endpoint=endpoint,
|
|
upstream=upstream,
|
|
)
|
|
|
|
# Determine the load-balancing upstreams to configure
|
|
nginx_upstream_config = ""
|
|
for upstream_worker_type, upstream_worker_ports in nginx_upstreams.items():
|
|
body = ""
|
|
for port in upstream_worker_ports:
|
|
body += " server localhost:%d;\n" % (port,)
|
|
|
|
# Add to the list of configured upstreams
|
|
nginx_upstream_config += NGINX_UPSTREAM_CONFIG_BLOCK.format(
|
|
upstream_worker_type=upstream_worker_type,
|
|
body=body,
|
|
)
|
|
|
|
# Finally, we'll write out the config files.
|
|
|
|
# Shared homeserver config
|
|
convert(
|
|
"/conf/shared.yaml.j2",
|
|
"/conf/workers/shared.yaml",
|
|
shared_worker_config=yaml.dump(shared_config),
|
|
)
|
|
|
|
# Nginx config
|
|
convert(
|
|
"/conf/nginx.conf.j2",
|
|
"/etc/nginx/conf.d/matrix-synapse.conf",
|
|
worker_locations=nginx_location_config,
|
|
upstream_directives=nginx_upstream_config,
|
|
)
|
|
|
|
# Supervisord config
|
|
convert(
|
|
"/conf/supervisord.conf.j2",
|
|
"/etc/supervisor/conf.d/supervisord.conf",
|
|
main_config_path=config_path,
|
|
worker_config=supervisord_config,
|
|
)
|
|
|
|
# Ensure the logging directory exists
|
|
log_dir = data_dir + "/logs"
|
|
if not os.path.exists(log_dir):
|
|
os.mkdir(log_dir)
|
|
|
|
|
|
def start_supervisord():
|
|
"""Starts up supervisord which then starts and monitors all other necessary processes
|
|
|
|
Raises: CalledProcessError if calling start.py return a non-zero exit code.
|
|
"""
|
|
subprocess.run(["/usr/bin/supervisord"], stdin=subprocess.PIPE)
|
|
|
|
|
|
def main(args, environ):
|
|
config_dir = environ.get("SYNAPSE_CONFIG_DIR", "/data")
|
|
config_path = environ.get("SYNAPSE_CONFIG_PATH", config_dir + "/homeserver.yaml")
|
|
data_dir = environ.get("SYNAPSE_DATA_DIR", "/data")
|
|
|
|
# override SYNAPSE_NO_TLS, we don't support TLS in worker mode,
|
|
# this needs to be handled by a frontend proxy
|
|
environ["SYNAPSE_NO_TLS"] = "yes"
|
|
|
|
# Generate the base homeserver config if one does not yet exist
|
|
if not os.path.exists(config_path):
|
|
log("Generating base homeserver config")
|
|
generate_base_homeserver_config()
|
|
|
|
# This script may be run multiple times (mostly by Complement, see note at top of file).
|
|
# Don't re-configure workers in this instance.
|
|
mark_filepath = "/conf/workers_have_been_configured"
|
|
if not os.path.exists(mark_filepath):
|
|
# Always regenerate all other config files
|
|
generate_worker_files(environ, config_path, data_dir)
|
|
|
|
# Mark workers as being configured
|
|
with open(mark_filepath, "w") as f:
|
|
f.write("")
|
|
|
|
# Start supervisord, which will start Synapse, all of the configured worker
|
|
# processes, redis, nginx etc. according to the config we created above.
|
|
start_supervisord()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv, os.environ)
|