1
0

Compare commits

...

22 Commits

Author SHA1 Message Date
Olivier 'reivilibre b21487300c Add application_names to the postgres connections based on the worker names 2024-09-09 16:15:52 +01:00
Andrew Morgan 1e73e7dde2 Merge branch 'develop' of github.com:element-hq/synapse into anoa/configure_workers_updates 2024-09-09 12:12:04 +01:00
Andrew Morgan b2141a3640 Merge branch 'develop' of github.com:element-hq/synapse into anoa/configure_workers_updates 2024-09-04 12:34:18 +01:00
Olivier 'reivilibre 5d2241e372 Configure sliding-sync workers with sticky load balancing 2024-09-02 16:27:02 +01:00
Olivier 'reivilibre bd46391d31 Merge branch 'develop' into anoa/configure_workers_updates 2024-08-30 14:51:48 +01:00
Till Faelligen e64a35cb00 Route key queries to the client_reader 2024-08-30 12:01:31 +02:00
Till Faelligen 58c8a2c6fd Merge branch 'develop' of github.com:element-hq/synapse into anoa/configure_workers_updates 2024-08-29 15:40:21 +02:00
Olivier 'reivilibre 56bcba2b16 Add metrics listener config for main process 2024-08-29 11:48:22 +01:00
Olivier 'reivilibre 40a684e169 Gen metrics scraping configurations, for use with file_sd_configs 2024-08-28 18:58:02 +01:00
Till Faelligen 84880cbe94 Route createRoom to event creators, add sliding_sync worker type 2024-08-21 11:56:08 +02:00
Till Faelligen 50bb114032 Add metrics 2024-08-19 14:53:24 +02:00
Till Faelligen e466404b4f Fix paths, remove logging (for now), disable passwords 2024-08-15 14:22:50 +02:00
Till Faelligen 4dd02db657 Fix parameter ordering 2024-08-15 11:33:10 +02:00
Andrew Morgan 333f806d06 fixup: Add SYNAPSE_CONFIG_TEMPLATE_DIR env var 2024-08-14 19:00:57 +01:00
Andrew Morgan 550d2a1e77 start.py: Support SYNAPSE_CONFIG_TEMPLATE_DIR 2024-08-14 18:57:23 +01:00
Andrew Morgan 61349bd860 create data directory if it doesn't exist
ideally this would be done in `main`
2024-08-14 18:52:47 +01:00
Andrew Morgan 20bd26ecad Allow configuring data dir in start.py 2024-08-14 18:47:47 +01:00
Andrew Morgan e91cd9c722 Allow running python from a venv 2024-08-14 17:27:36 +01:00
Andrew Morgan 18a331a18c Document additional environment variables 2024-08-14 17:27:34 +01:00
Andrew Morgan d7e3925a14 Allow specifying where generated config files are stored
* Store generated worker config files in SYNAPSE_CONFIG_DIR, rather than hardcoding
  `/conf`.
* Move the `workers_have_been_configured` filepath to the config dir.
2024-08-14 17:27:30 +01:00
Andrew Morgan 9df46343b9 Remove unused config_path dict entry 2024-08-14 17:27:27 +01:00
Andrew Morgan a035d84ce0 Add SYNAPSE_CONFIG_TEMPLATE_DIR env var to worker config script
This allows specifying a directory other than `/conf` where config templates should live. This allows this
script to be used outside of the context of a docker container where /conf is bound to a dir on the host.
2024-08-14 17:27:24 +01:00
6 changed files with 196 additions and 68 deletions
+2 -10
View File
@@ -11,24 +11,16 @@ files = /etc/supervisor/conf.d/*.conf
[program:nginx]
command=/usr/local/bin/prefix-log /usr/sbin/nginx -g "daemon off;"
priority=500
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
username=www-data
autorestart=true
[program:redis]
{% if using_unix_sockets %}
command=/usr/local/bin/prefix-log /usr/local/bin/redis-server --unixsocket /tmp/redis.sock
command=/usr/local/bin/prefix-log /usr/bin/redis-server --unixsocket /tmp/redis.sock
{% else %}
command=/usr/local/bin/prefix-log /usr/local/bin/redis-server
command=/usr/local/bin/prefix-log /usr/bin/redis-server
{% endif %}
priority=1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
username=redis
autorestart=true
@@ -1,52 +1,38 @@
{% if use_forking_launcher %}
[program:synapse_fork]
command=/usr/local/bin/python -m synapse.app.complement_fork_starter
command=/usr/local/bin/prefix-log /root/synapse/env/bin/python -m synapse.app.complement_fork_starter
{{ main_config_path }}
synapse.app.homeserver
--config-path="{{ main_config_path }}"
--config-path=/conf/workers/shared.yaml
--config-path=/root/synapse/config/workers/shared.yaml
{%- for worker in workers %}
-- {{ worker.app }}
--config-path="{{ main_config_path }}"
--config-path=/conf/workers/shared.yaml
--config-path=/conf/workers/{{ worker.name }}.yaml
--config-path=/root/synapse/config/workers/shared.yaml
--config-path=/root/synapse/config/workers/{{ worker.name }}.yaml
{%- endfor %}
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=unexpected
exitcodes=0
{% else %}
[program:synapse_main]
command=/usr/local/bin/prefix-log /usr/local/bin/python -m synapse.app.homeserver
command=/usr/local/bin/prefix-log /root/synapse/env/bin/python -m synapse.app.homeserver
--config-path="{{ main_config_path }}"
--config-path=/conf/workers/shared.yaml
--config-path=/root/synapse/config/workers/shared.yaml
priority=10
# Log startup failures to supervisord's stdout/err
# Regular synapse logs will still go in the configured data directory
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autorestart=unexpected
exitcodes=0
{% for worker in workers %}
[program:synapse_{{ worker.name }}]
command=/usr/local/bin/prefix-log /usr/local/bin/python -m {{ worker.app }}
command=/usr/local/bin/prefix-log /root/synapse/env/bin/python -m {{ worker.app }}
--config-path="{{ main_config_path }}"
--config-path=/conf/workers/shared.yaml
--config-path=/conf/workers/{{ worker.name }}.yaml
--config-path=/root/synapse/config/workers/shared.yaml
--config-path=/root/synapse/config/workers/{{ worker.name }}.yaml
autorestart=unexpected
priority=500
exitcodes=0
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
{% endfor %}
{% endif %}
+19
View File
@@ -20,7 +20,26 @@ worker_listeners:
- {{ resource }}
{%- endfor %}
{% endif %}
- type: metrics
port: {{ port + 1 }}
resources:
- metrics
worker_log_config: {{ worker_log_config_filepath }}
database:
name: "psycopg2"
args:
user: "{{ POSTGRES_USER or "synapse" }}"
password: "{{ POSTGRES_PASSWORD }}"
database: "{{ POSTGRES_DB or "synapse" }}"
{% if not SYNAPSE_USE_UNIX_SOCKET %}
{# Synapse will use a default unix socket for Postgres when host/port is not specified (behavior from `psycopg2`). #}
host: "{{ POSTGRES_HOST or "db" }}"
port: "{{ POSTGRES_PORT or "5432" }}"
{% endif %}
cp_min: {{ POSTGRES_CP_MIN or 5 }}
cp_max: {{ POSTGRES_CP_MAX or 10 }}
application_name: "{{ name }}"
{{ worker_extra_conf }}
+4 -3
View File
@@ -69,6 +69,7 @@ database:
{% endif %}
cp_min: {{ POSTGRES_CP_MIN or 5 }}
cp_max: {{ POSTGRES_CP_MAX or 10 }}
application_name: synapse
{% else %}
database:
name: "sqlite3"
@@ -92,7 +93,7 @@ federation_rc_concurrent: 3
## Files ##
media_store_path: "/data/media"
media_store_path: "/root/synapse/data/media"
max_upload_size: "{{ SYNAPSE_MAX_UPLOAD_SIZE or "50M" }}"
max_image_pixels: "32M"
dynamic_thumbnails: false
@@ -179,7 +180,7 @@ macaroon_secret_key: "{{ SYNAPSE_MACAROON_SECRET_KEY }}"
## Signing Keys ##
signing_key_path: "/data/{{ SYNAPSE_SERVER_NAME }}.signing.key"
signing_key_path: "/root/synapse/data/{{ SYNAPSE_SERVER_NAME }}.signing.key"
old_signing_keys: {}
key_refresh_interval: "1d" # 1 Day.
@@ -190,4 +191,4 @@ trusted_key_servers:
"ed25519:auto": "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"
password_config:
enabled: true
enabled: false
+141 -23
View File
@@ -24,6 +24,15 @@
# nginx and supervisord configs depending on the workers requested.
#
# The environment variables it reads are:
# * SYNAPSE_CONFIG_PATH: The path where the generated `homeserver.yaml` will
# be stored.
# * SYNAPSE_CONFIG_DIR: The directory where generated config will be stored.
# If `SYNAPSE_CONFIG_PATH` is not set, it will default to
# SYNAPSE_CONFIG_DIR/homeserver.yaml.
# * SYNAPSE_DATA_DIR: Where the generated config will put persistent data
# such as the database and media store.
# * SYNAPSE_CONFIG_TEMPLATE_DIR: The directory containing jinja2 templates for
# configuration that this script will generate config from.
# * 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 WORKERS_CONFIG
@@ -35,6 +44,8 @@
# SYNAPSE_WORKER_TYPES='event_persister, federation_sender, client_reader'
# SYNAPSE_WORKER_TYPES='event_persister:2, federation_sender:2, client_reader'
# SYNAPSE_WORKER_TYPES='stream_writers=account_data+presence+typing'
# * SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK: Whether worker logs should be written to disk,
# in addition to stdout.
# * SYNAPSE_AS_REGISTRATION_DIR: If specified, a directory in which .yaml and .yml files
# will be treated as Application Service registration files.
# * SYNAPSE_TLS_CERT: Path to a TLS certificate in PEM format.
@@ -48,12 +59,15 @@
# * SYNAPSE_LOG_SENSITIVE: If unset, SQL and SQL values won't be logged,
# regardless of the SYNAPSE_LOG_LEVEL setting.
# * SYNAPSE_LOG_TESTING: if set, Synapse will log additional information useful
# for testing.
# for testing.
# * SYNAPSE_USE_UNIX_SOCKET: if set, workers will communicate via unix socket
# rather than TCP.
#
# 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 json
import os
import platform
import re
@@ -82,6 +96,7 @@ MAIN_PROCESS_HTTP_LISTENER_PORT = 8080
MAIN_PROCESS_INSTANCE_NAME = "main"
MAIN_PROCESS_LOCALHOST_ADDRESS = "127.0.0.1"
MAIN_PROCESS_REPLICATION_PORT = 9093
MAIN_PROCESS_METRICS_PORT = 9094
# Obviously, these would only be used with the UNIX socket option
MAIN_PROCESS_UNIX_SOCKET_PUBLIC_PATH = "/run/main_public.sock"
MAIN_PROCESS_UNIX_SOCKET_PRIVATE_PATH = "/run/main_private.sock"
@@ -163,6 +178,16 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
"shared_extra_conf": {},
"worker_extra_conf": "",
},
"sliding_sync": {
"app": "synapse.app.generic_worker",
"listener_resources": ["client"],
"endpoint_patterns": [
"^/_matrix/client/unstable/org.matrix.simplified_msc3575/sync$",
],
"shared_extra_conf": {},
"worker_extra_conf": "",
"nginx_upstream_extra_conf": "hash $http_authorization consistent;",
},
"client_reader": {
"app": "synapse.app.generic_worker",
"listener_resources": ["client"],
@@ -194,6 +219,8 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
"^/_matrix/client/(api/v1|r0|v3|unstable)/directory/room/.*$",
"^/_matrix/client/(r0|v3|unstable)/capabilities$",
"^/_matrix/client/(r0|v3|unstable)/notifications$",
"^/_matrix/client/(r0|v3|unstable)/keys/query$"
"^/_matrix/client/(r0|v3|unstable)/keys/changes$"
],
"shared_extra_conf": {},
"worker_extra_conf": "",
@@ -260,6 +287,7 @@ WORKERS_CONFIG: Dict[str, Dict[str, Any]] = {
"^/_matrix/client/(api/v1|r0|v3|unstable)/join/",
"^/_matrix/client/(api/v1|r0|v3|unstable)/knock/",
"^/_matrix/client/(api/v1|r0|v3|unstable)/profile/",
"^/_matrix/client/(api/v1|r0|v3|unstable)/createRoom$",
],
"shared_extra_conf": {},
"worker_extra_conf": "",
@@ -604,7 +632,13 @@ def generate_base_homeserver_config() -> None:
# 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.run(["/usr/local/bin/python", "/start.py", "migrate_config"], check=True)
# This script makes use of the `SYNAPSE_CONFIG_DIR` environment variable to
# determine where to place the generated homeserver config.
# We use "python" instead of supplying an absolute path here to allow those
# running the script to use python from a virtual env.
subprocess.run(["python", "/start.py", "migrate_config"], check=True)
def parse_worker_types(
@@ -730,11 +764,39 @@ def parse_worker_types(
return dict_to_return
def generate_metrics_scrape_config(
metrics_ports: Dict[str, int]
) -> None:
out_scrape_configs = []
for worker_name, worker_metrics_port in metrics_ports.items():
job = worker_name.rstrip("0123456789")
if len(job) < len(worker_name):
index = int(worker_name[len(job):])
else:
# worker name without a number: assume index=1
index = 1
out_scrape_configs.append({
"targets": [f"127.0.0.1:{worker_metrics_port}"],
"labels": {
"job": f"synapse-{job}",
"index": f"{index}",
# we want all instance names to be the same, even on different scrape addresses
"instance": "synapse",
}
})
with open("/out_scrape.json", "w") as fout:
json.dump(out_scrape_configs, fout)
def generate_worker_files(
environ: Mapping[str, str],
config_dir: str,
config_path: str,
data_dir: str,
template_dir: str,
requested_worker_types: Dict[str, Set[str]],
) -> None:
"""Read the desired workers(if any) that is passed in and generate shared
@@ -742,9 +804,13 @@ def generate_worker_files(
Args:
environ: os.environ instance.
config_path: The location of the generated Synapse main worker config file.
data_dir: The location of the synapse data directory. Where log and
user-facing config files live.
config_dir: The location of the configuration directory, where generated
worker config files are written to.
config_path: The location of the base Synapse homeserver config file.
data_dir: The location of the synapse data directory. Where logs will be
stored (if `SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK` is set).
template_dir: The location of the template directory. Where jinja2
templates for config files live.
requested_worker_types: A Dict containing requested workers in the format of
{'worker_name1': {'worker_type', ...}}
"""
@@ -774,6 +840,13 @@ def generate_worker_files(
"resources": [{"names": ["replication"]}],
}
]
listeners.append({
"port": MAIN_PROCESS_METRICS_PORT,
"type": "metrics",
"bind_address": "::",
})
with open(config_path) as file_stream:
original_config = yaml.safe_load(file_stream)
original_listeners = original_config.get("listeners")
@@ -806,8 +879,14 @@ def generate_worker_files(
# with nginx_upstreams and placed in /etc/nginx/conf.d.
nginx_locations: Dict[str, str] = {}
# A map from worker name to which HTTP port is in use for its metrics.
metrics_ports: Dict[str, int] = {
MAIN_PROCESS_INSTANCE_NAME: MAIN_PROCESS_METRICS_PORT,
}
# Create the worker configuration directory if it doesn't already exist
os.makedirs("/conf/workers", exist_ok=True)
workers_config_dir = os.path.join(config_dir, "workers")
os.makedirs(workers_config_dir, exist_ok=True)
# Start worker ports from this arbitrary port
worker_port = 18009
@@ -854,9 +933,11 @@ def generate_worker_files(
worker_config = insert_worker_name_for_worker_config(worker_config, worker_name)
worker_config.update(
{"name": worker_name, "port": str(worker_port), "config_path": config_path}
{"name": worker_name, "port": worker_port}
)
metrics_ports[worker_name] = worker_port + 1
# Update the shared config with any worker_type specific options. The first of a
# given worker_type needs to stay assigned and not be replaced.
worker_config["shared_extra_conf"].update(shared_config)
@@ -877,13 +958,21 @@ def generate_worker_files(
worker_descriptors.append(worker_config)
# Write out the worker's logging config file
log_config_filepath = generate_worker_log_config(environ, worker_name, data_dir)
log_config_filepath = generate_worker_log_config(
environ, worker_name, workers_config_dir, template_dir, data_dir
)
extra_env: Dict[str, str] = {}
for extra_env_var in ("POSTGRES_HOST", "POSTGRES_PORT", "POSTGRES_USER", "POSTGRES_PASSWORD", "POSTGRES_SOCKET", "POSTGRES_DB", "SYNAPSE_USE_UNIX_SOCKET", "POSTGRES_CP_MIN", "POSTGRES_CP_MAX"):
if extra_env_var in os.environ:
extra_env[extra_env_var] = os.environ[extra_env_var]
# Then a worker config file
convert(
"/conf/worker.yaml.j2",
f"/conf/workers/{worker_name}.yaml",
os.path.join(template_dir, "worker.yaml.j2"),
os.path.join(workers_config_dir, f"{worker_name}.yaml"),
**worker_config,
**extra_env,
worker_log_config_filepath=log_config_filepath,
using_unix_sockets=using_unix_sockets,
)
@@ -892,7 +981,7 @@ def generate_worker_files(
for worker_type in worker_types_set:
nginx_upstreams.setdefault(worker_type, set()).add(worker_port)
worker_port += 1
worker_port += 2
# Build the nginx location config blocks
nginx_location_config = ""
@@ -914,6 +1003,11 @@ def generate_worker_files(
for port in upstream_worker_ports:
body += f" server localhost:{port};\n"
# Append extra lines required for the specialised type of worker
extra_upstream_conf: Optional[str] = WORKERS_CONFIG[upstream_worker_base_name].get("nginx_upstream_extra_conf")
if extra_upstream_conf:
body += "".join(f"\n {line}" for line in extra_upstream_conf.split("\n"))
# Add to the list of configured upstreams
nginx_upstream_config += NGINX_UPSTREAM_CONFIG_BLOCK.format(
upstream_worker_base_name=upstream_worker_base_name,
@@ -923,7 +1017,9 @@ def generate_worker_files(
# Finally, we'll write out the config files.
# log config for the master process
master_log_config = generate_worker_log_config(environ, "master", data_dir)
master_log_config = generate_worker_log_config(
environ, "master", workers_config_dir, template_dir, data_dir
)
shared_config["log_config"] = master_log_config
# Find application service registrations
@@ -954,8 +1050,8 @@ def generate_worker_files(
# Shared homeserver config
convert(
"/conf/shared.yaml.j2",
"/conf/workers/shared.yaml",
os.path.join(template_dir, "shared.yaml.j2"),
os.path.join(workers_config_dir, "shared.yaml"),
shared_worker_config=yaml.dump(shared_config),
appservice_registrations=appservice_registrations,
enable_redis=workers_in_use,
@@ -965,7 +1061,7 @@ def generate_worker_files(
# Nginx config
convert(
"/conf/nginx.conf.j2",
os.path.join(template_dir, "nginx.conf.j2"),
"/etc/nginx/conf.d/matrix-synapse.conf",
worker_locations=nginx_location_config,
upstream_directives=nginx_upstream_config,
@@ -977,7 +1073,7 @@ def generate_worker_files(
# Supervisord config
os.makedirs("/etc/supervisor", exist_ok=True)
convert(
"/conf/supervisord.conf.j2",
os.path.join(template_dir, "supervisord.conf.j2"),
"/etc/supervisor/supervisord.conf",
main_config_path=config_path,
enable_redis=workers_in_use,
@@ -985,7 +1081,7 @@ def generate_worker_files(
)
convert(
"/conf/synapse.supervisord.conf.j2",
os.path.join(template_dir, "synapse.supervisord.conf.j2"),
"/etc/supervisor/conf.d/synapse.conf",
workers=worker_descriptors,
main_config_path=config_path,
@@ -994,7 +1090,7 @@ def generate_worker_files(
# healthcheck config
convert(
"/conf/healthcheck.sh.j2",
os.path.join(template_dir, "healthcheck.sh.j2"),
"/healthcheck.sh",
healthcheck_urls=healthcheck_urls,
)
@@ -1004,12 +1100,29 @@ def generate_worker_files(
if not os.path.exists(log_dir):
os.mkdir(log_dir)
# Add metrics scraping configurations
generate_metrics_scrape_config(metrics_ports)
def generate_worker_log_config(
environ: Mapping[str, str], worker_name: str, data_dir: str
environ: Mapping[str, str],
worker_name: str,
workers_config_dir: str,
template_dir: str,
data_dir: str,
) -> str:
"""Generate a log.config file for the given worker.
Args:
environ: A mapping representing the environment variables that this script
is running with.
worker_name: The name of the worker. Used in generated file paths.
workers_config_dir: The location of the worker configuration directory,
where the generated worker log config will be saved.
template_dir: The directory containing jinja2 template files.
data_dir: The directory where log files will be written (if
`SYNAPSE_WORKERS_WRITE_LOGS_TO_DISK` is set).
Returns: the path to the generated file
"""
# Check whether we should write worker logs to disk, in addition to the console
@@ -1024,9 +1137,9 @@ def generate_worker_log_config(
extra_log_template_args["SYNAPSE_LOG_TESTING"] = environ.get("SYNAPSE_LOG_TESTING")
# Render and write the file
log_config_filepath = f"/conf/workers/{worker_name}.log.config"
log_config_filepath = os.path.join(workers_config_dir, f"{worker_name}.log.config")
convert(
"/conf/log.config",
os.path.join(template_dir, "log.config"),
log_config_filepath,
worker_name=worker_name,
**extra_log_template_args,
@@ -1049,6 +1162,7 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
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")
template_dir = environ.get("SYNAPSE_CONFIG_TEMPLATE_DIR", "/conf")
# override SYNAPSE_NO_TLS, we don't support TLS in worker mode,
# this needs to be handled by a frontend proxy
@@ -1060,9 +1174,10 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
generate_base_homeserver_config()
else:
log("Base homeserver config exists—not regenerating")
# 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"
mark_filepath = os.path.join(config_dir, "workers_have_been_configured")
if not os.path.exists(mark_filepath):
# Collect and validate worker_type requests
# Read the desired worker configuration from the environment
@@ -1079,7 +1194,9 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
# Always regenerate all other config files
log("Generating worker config files")
generate_worker_files(environ, config_path, data_dir, requested_worker_types)
generate_worker_files(
environ, config_dir, config_path, data_dir, template_dir, requested_worker_types
)
# Mark workers as being configured
with open(mark_filepath, "w") as f:
@@ -1114,3 +1231,4 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
if __name__ == "__main__":
main(sys.argv[1:], os.environ)
+21 -9
View File
@@ -42,6 +42,8 @@ def convert(src: str, dst: str, environ: Mapping[str, object]) -> None:
def generate_config_from_template(
data_dir: str,
template_dir: str,
config_dir: str,
config_path: str,
os_environ: Mapping[str, str],
@@ -50,6 +52,9 @@ def generate_config_from_template(
"""Generate a homeserver.yaml from environment variables
Args:
data_dir: where persistent data is stored
template_dir: The location of the template directory. Where jinja2
templates for config files live.
config_dir: where to put generated config files
config_path: where to put the main config file
os_environ: environment mapping
@@ -70,9 +75,13 @@ def generate_config_from_template(
"macaroon": "SYNAPSE_MACAROON_SECRET_KEY",
}
if not os.path.exists(data_dir):
os.mkdir(data_dir)
synapse_server_name = environ["SYNAPSE_SERVER_NAME"]
for name, secret in secrets.items():
if secret not in environ:
filename = "/data/%s.%s.key" % (environ["SYNAPSE_SERVER_NAME"], name)
filename = os.path.join(data_dir, f"{synapse_server_name}.{name}.key")
# if the file already exists, load in the existing value; otherwise,
# generate a new secret and write it to a file
@@ -88,7 +97,7 @@ def generate_config_from_template(
handle.write(value)
environ[secret] = value
environ["SYNAPSE_APPSERVICES"] = glob.glob("/data/appservices/*.yaml")
environ["SYNAPSE_APPSERVICES"] = glob.glob(os.path.join(data_dir, "appservices", "*.yaml"))
if not os.path.exists(config_dir):
os.mkdir(config_dir)
@@ -111,12 +120,12 @@ def generate_config_from_template(
environ["SYNAPSE_LOG_CONFIG"] = config_dir + "/log.config"
log("Generating synapse config file " + config_path)
convert("/conf/homeserver.yaml", config_path, environ)
convert(os.path.join(template_dir, "homeserver.yaml"), config_path, environ)
log_config_file = environ["SYNAPSE_LOG_CONFIG"]
log("Generating log config file " + log_config_file)
convert(
"/conf/log.config",
os.path.join(template_dir, "log.config"),
log_config_file,
{**environ, "include_worker_name_in_log_line": False},
)
@@ -128,15 +137,15 @@ def generate_config_from_template(
"synapse.app.homeserver",
"--config-path",
config_path,
# tell synapse to put generated keys in /data rather than /compiled
# tell synapse to put generated keys in the data directory rather than /compiled
"--keys-directory",
config_dir,
"--generate-keys",
]
if ownership is not None:
log(f"Setting ownership on /data to {ownership}")
subprocess.run(["chown", "-R", ownership, "/data"], check=True)
log(f"Setting ownership on the data dir to {ownership}")
subprocess.run(["chown", "-R", ownership, data_dir], check=True)
args = ["gosu", ownership] + args
subprocess.run(args, check=True)
@@ -159,12 +168,13 @@ def run_generate_config(environ: Mapping[str, str], ownership: Optional[str]) ->
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")
template_dir = environ.get("SYNAPSE_CONFIG_TEMPLATE_DIR", "/conf")
# create a suitable log config from our template
log_config_file = "%s/%s.log.config" % (config_dir, server_name)
if not os.path.exists(log_config_file):
log("Creating log config %s" % (log_config_file,))
convert("/conf/log.config", log_config_file, environ)
convert(os.path.join(template_dir, "log.config"), log_config_file, environ)
# generate the main config file, and a signing key.
args = [
@@ -216,12 +226,14 @@ def main(args: List[str], environ: MutableMapping[str, str]) -> None:
if mode == "migrate_config":
# generate a config based on environment vars.
data_dir = environ.get("SYNAPSE_DATA_DIR", "/data")
config_dir = environ.get("SYNAPSE_CONFIG_DIR", "/data")
config_path = environ.get(
"SYNAPSE_CONFIG_PATH", config_dir + "/homeserver.yaml"
)
template_dir = environ.get("SYNAPSE_CONFIG_TEMPLATE_DIR", "/conf")
return generate_config_from_template(
config_dir, config_path, environ, ownership
data_dir, template_dir, config_dir, config_path, environ, ownership
)
if mode != "run":