def test_generate_config_generates_files(self): HomeServerConfig.load_or_generate_config( "", [ "--generate-config", "-c", self.file, "--report-stats=yes", "-H", "lemurs.win", ], ) self.assertSetEqual( set( [ "homeserver.yaml", "lemurs.win.log.config", "lemurs.win.signing.key", "lemurs.win.tls.crt", "lemurs.win.tls.dh", "lemurs.win.tls.key", ] ), set(os.listdir(self.dir)), ) self.assert_log_filename_is( os.path.join(self.dir, "lemurs.win.log.config"), os.path.join(os.getcwd(), "homeserver.log"), )
def _run_first_time_setup(self): self.create_config_dir() if 'riot_web' in self.plugins: riot = self.plugins['riot_web'].Controller() web_client_location = os.path.join(riot.config_dir, 'webapp') else: web_client_location = None configs = { 'domain': os.environ['NOTEWORTHY_DOMAIN'], 'registration_shared_secret': self._get_new_secret(), 'macaroon_secret_key': self._get_new_secret(), 'form_secret': self._get_new_secret(), 'web_client_location': web_client_location, 'config_dir': self.config_dir, 'homeserver_log_config': self.log_config_file, 'homeserver_log_target': self.log_file } homeserver_tmpl = os.path.join(self.deploy_dir, 'homeserver.tmpl.yaml') homeserver_target = os.path.join(self.config_dir, 'homeserver.yaml') self._generate_file_from_template(homeserver_tmpl, homeserver_target, configs) logconfig_tmpl = os.path.join(self.deploy_dir, 'log.config.tmpl.yaml') self._generate_file_from_template(logconfig_tmpl, self.log_config_file, configs) from synapse.config.homeserver import HomeServerConfig HomeServerConfig.load_or_generate_config( 'Noteworthy Messenger', ['-c', homeserver_target, '--generate-missing-configs'])
def test_generate_config_generates_files(self): with redirect_stdout(StringIO()): HomeServerConfig.load_or_generate_config( "", [ "--generate-config", "-c", self.file, "--report-stats=yes", "-H", "lemurs.win", ], ) self.assertSetEqual( { "homeserver.yaml", "lemurs.win.log.config", "lemurs.win.signing.key" }, set(os.listdir(self.dir)), ) self.assert_log_filename_is( os.path.join(self.dir, "lemurs.win.log.config"), os.path.join(os.getcwd(), "homeserver.log"), )
def generate_config(self): HomeServerConfig.load_or_generate_config("", [ "--generate-config", "-c", self.file, "--report-stats=yes", "-H", "lemurs.win" ])
def generate_config(self): with redirect_stdout(StringIO()): HomeServerConfig.load_or_generate_config( "", [ "--generate-config", "-c", self.config_file, "--report-stats=yes", "-H", "lemurs.win", ], )
def test_disable_registration(self): self.generate_config() self.add_lines_to_config( ["enable_registration: true", "disable_registration: true"]) # Check that disable_registration clobbers enable_registration. config = HomeServerConfig.load_config("", ["-c", self.file]) self.assertFalse(config.registration.enable_registration) config = HomeServerConfig.load_or_generate_config( "", ["-c", self.file]) self.assertFalse(config.registration.enable_registration) # Check that either config value is clobbered by the command line. config = HomeServerConfig.load_or_generate_config( "", ["-c", self.file, "--enable-registration"]) self.assertTrue(config.registration.enable_registration)
def test_load_succeeds_if_macaroon_secret_key_missing(self): self.generate_config_and_remove_lines_containing("macaroon") config1 = HomeServerConfig.load_config("", ["-c", self.file]) config2 = HomeServerConfig.load_config("", ["-c", self.file]) config3 = HomeServerConfig.load_or_generate_config("", ["-c", self.file]) self.assertEqual(config1.macaroon_secret_key, config2.macaroon_secret_key) self.assertEqual(config1.macaroon_secret_key, config3.macaroon_secret_key)
def test_generates_and_loads_macaroon_secret_key(self): self.generate_config() with open(self.config_file) as f: raw = yaml.safe_load(f) self.assertIn("macaroon_secret_key", raw) config = HomeServerConfig.load_config("", ["-c", self.config_file]) self.assertTrue( hasattr(config.key, "macaroon_secret_key"), "Want config to have attr macaroon_secret_key", ) if len(config.key.macaroon_secret_key) < 5: self.fail( "Want macaroon secret key to be string of at least length 5," "was: %r" % (config.key.macaroon_secret_key, )) config2 = HomeServerConfig.load_or_generate_config( "", ["-c", self.config_file]) assert config2 is not None self.assertTrue( hasattr(config2.key, "macaroon_secret_key"), "Want config to have attr macaroon_secret_key", ) if len(config2.key.macaroon_secret_key) < 5: self.fail( "Want macaroon secret key to be string of at least length 5," "was: %r" % (config2.key.macaroon_secret_key, ))
def test_generates_and_loads_macaroon_secret_key(self): self.generate_config() with open(self.file, "r") as f: raw = yaml.load(f) self.assertIn("macaroon_secret_key", raw) config = HomeServerConfig.load_config("", ["-c", self.file]) self.assertTrue( hasattr(config, "macaroon_secret_key"), "Want config to have attr macaroon_secret_key", ) if len(config.macaroon_secret_key) < 5: self.fail( "Want macaroon secret key to be string of at least length 5," "was: %r" % (config.macaroon_secret_key,) ) config = HomeServerConfig.load_or_generate_config("", ["-c", self.file]) self.assertTrue( hasattr(config, "macaroon_secret_key"), "Want config to have attr macaroon_secret_key", ) if len(config.macaroon_secret_key) < 5: self.fail( "Want macaroon secret key to be string of at least length 5," "was: %r" % (config.macaroon_secret_key,) )
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options) except ConfigError as e: sys.stderr.write("\n") for f in format_config_error(e): sys.stderr.write(f) sys.stderr.write("\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) events.USE_FROZEN_DICTS = config.use_frozen_dicts synapse.util.caches.TRACK_MEMORY_USAGE = config.caches.track_memory_usage if config.server.gc_seconds: synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds hs = SynapseHomeServer( config.server_name, config=config, version_string="Synapse/" + get_version_string(synapse), ) synapse.config.logger.setup_logging(hs, config, use_worker_options=False) logger.info("Setting up server") try: hs.setup() except Exception as e: handle_startup_exception(e) async def start(): # Load the OIDC provider metadatas, if OIDC is enabled. if hs.config.oidc_enabled: oidc = hs.get_oidc_handler() # Loading the provider metadata also ensures the provider config is valid. await oidc.load_metadata() await _base.start(hs) hs.get_datastore().db_pool.updates.start_doing_background_updates() register_start(start) return hs
def test_disable_registration(self): self.generate_config() self.add_lines_to_config( ["enable_registration: true", "disable_registration: true"] ) # Check that disable_registration clobbers enable_registration. config = HomeServerConfig.load_config("", ["-c", self.file]) self.assertFalse(config.enable_registration) config = HomeServerConfig.load_or_generate_config("", ["-c", self.file]) self.assertFalse(config.enable_registration) # Check that either config value is clobbered by the command line. config = HomeServerConfig.load_or_generate_config( "", ["-c", self.file, "--enable-registration"] ) self.assertTrue(config.enable_registration)
def test_generate_config_generates_files(self): HomeServerConfig.load_or_generate_config("", [ "--generate-config", "-c", self.file, "--report-stats=yes", "-H", "lemurs.win" ]) self.assertSetEqual( set([ "homeserver.yaml", "lemurs.win.log.config", "lemurs.win.signing.key", "lemurs.win.tls.crt", "lemurs.win.tls.dh", "lemurs.win.tls.key", ]), set(os.listdir(self.dir)) )
def test_generate_config_generates_files(self): HomeServerConfig.load_or_generate_config("", [ "--generate-config", "-c", self.file, "--report-stats=yes", "-H", "lemurs.win" ]) self.assertSetEqual( set([ "homeserver.yaml", "lemurs.win.log.config", "lemurs.win.signing.key", "lemurs.win.tls.crt", "lemurs.win.tls.dh", "lemurs.win.tls.key", ]), set(os.listdir(self.dir))) self.assert_log_filename_is( os.path.join(self.dir, "lemurs.win.log.config"), os.path.join(os.getcwd(), "homeserver.log"), )
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) sighup_callbacks = [] synapse.config.logger.setup_logging( config, use_worker_options=False, register_sighup=sighup_callbacks.append ) def handle_sighup(*args, **kwargs): for i in sighup_callbacks: i(*args, **kwargs) if hasattr(signal, "SIGHUP"): signal.signal(signal.SIGHUP, handle_sighup) events.USE_FROZEN_DICTS = config.use_frozen_dicts database_engine = create_engine(config.database_config) config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, config=config, version_string="Synapse/" + get_version_string(synapse), database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: with hs.get_db_conn(run_new_connection=False) as db_conn: prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n" ) sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() def refresh_certificate(*args): """ Refresh the TLS certificates that Synapse is using by re-reading them from disk and updating the TLS context factories to use them. """ logging.info("Reloading certificate from disk...") hs.config.read_certificate_from_disk() hs.tls_server_context_factory = context_factory.ServerContextFactory(config) hs.tls_client_options_factory = context_factory.ClientTLSOptionsFactory( config ) logging.info("Certificate reloaded.") logging.info("Updating context factories...") for i in hs._listening_services: if isinstance(i.factory, TLSMemoryBIOFactory): i.factory = TLSMemoryBIOFactory( hs.tls_server_context_factory, False, i.factory.wrappedFactory ) logging.info("Context factories updated.") sighup_callbacks.append(refresh_certificate) @defer.inlineCallbacks def start(): try: # Check if the certificate is still valid. cert_days_remaining = hs.config.is_disk_cert_valid() if hs.config.acme_enabled: # If ACME is enabled, we might need to provision a certificate # before starting. acme = hs.get_acme_handler() # Start up the webservices which we will respond to ACME # challenges with. yield acme.start_listening() # We want to reprovision if cert_days_remaining is None (meaning no # certificate exists), or the days remaining number it returns # is less than our re-registration threshold. if (cert_days_remaining is None) or ( not cert_days_remaining > hs.config.acme_reprovision_threshold ): yield acme.provision_certificate() # Read the certificate from disk and build the context factories for # TLS. hs.config.read_certificate_from_disk() hs.tls_server_context_factory = context_factory.ServerContextFactory(config) hs.tls_client_options_factory = context_factory.ClientTLSOptionsFactory( config ) # It is now safe to start your Synapse. hs.start_listening() hs.get_pusherpool().start() hs.get_datastore().start_profiling() hs.get_datastore().start_doing_background_updates() except Exception as e: # If a DeferredList failed (like in listening on the ACME listener), # we need to print the subfailure explicitly. if isinstance(e, defer.FirstError): e.subFailure.printTraceback(sys.stderr) sys.exit(1) # Something else went wrong when starting. Print it and bail out. traceback.print_exc(file=sys.stderr) sys.exit(1) reactor.callWhenRunning(start) return hs
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) synapse.config.logger.setup_logging(config, use_worker_options=False) events.USE_FROZEN_DICTS = config.use_frozen_dicts tls_server_context_factory = context_factory.ServerContextFactory(config) tls_client_options_factory = context_factory.ClientTLSOptionsFactory(config) database_engine = create_engine(config.database_config) config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, tls_server_context_factory=tls_server_context_factory, tls_client_options_factory=tls_client_options_factory, config=config, version_string="Synapse/" + get_version_string(synapse), database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: with hs.get_db_conn(run_new_connection=False) as db_conn: prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n" ) sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() hs.start_listening() def start(): hs.get_pusherpool().start() hs.get_datastore().start_profiling() hs.get_datastore().start_doing_background_updates() reactor.callWhenRunning(start) return hs
def test_load_fails_if_server_name_missing(self): self.generate_config_and_remove_lines_containing("server_name") with self.assertRaises(Exception): HomeServerConfig.load_config("", ["-c", self.file]) with self.assertRaises(Exception): HomeServerConfig.load_or_generate_config("", ["-c", self.file])
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + e.message + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) config.setup_logging() # check any extra requirements we have now we have a config check_requirements(config) version_string = get_version_string("Synapse", synapse) logger.info("Server hostname: %s", config.server_name) logger.info("Server version: %s", version_string) events.USE_FROZEN_DICTS = config.use_frozen_dicts tls_server_context_factory = context_factory.ServerContextFactory(config) database_engine = create_engine(config.database_config) config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, tls_server_context_factory=tls_server_context_factory, config=config, content_addr=config.content_addr, version_string=version_string, database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: db_conn = hs.get_db_conn(run_new_connection=False) prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n" ) sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() hs.start_listening() def start(): hs.get_pusherpool().start() hs.get_state_handler().start_caching() hs.get_datastore().start_profiling() hs.get_datastore().start_doing_background_updates() hs.get_replication_layer().start_get_pdu_cache() reactor.callWhenRunning(start) return hs
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options) except ConfigError as e: sys.stderr.write("\n") for f in format_config_error(e): sys.stderr.write(f) sys.stderr.write("\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) events.USE_FROZEN_DICTS = config.use_frozen_dicts hs = SynapseHomeServer( config.server_name, config=config, version_string="Synapse/" + get_version_string(synapse), ) synapse.config.logger.setup_logging(hs, config, use_worker_options=False) logger.info("Setting up server") try: hs.setup() except IncorrectDatabaseSetup as e: quit_with_error(str(e)) except UpgradeDatabaseException as e: quit_with_error("Failed to upgrade database: %s" % (e, )) async def do_acme() -> bool: """ Reprovision an ACME certificate, if it's required. Returns: Whether the cert has been updated. """ acme = hs.get_acme_handler() # Check how long the certificate is active for. cert_days_remaining = hs.config.is_disk_cert_valid( allow_self_signed=False) # We want to reprovision if cert_days_remaining is None (meaning no # certificate exists), or the days remaining number it returns # is less than our re-registration threshold. provision = False if (cert_days_remaining is None or cert_days_remaining < hs.config.acme_reprovision_threshold): provision = True if provision: await acme.provision_certificate() return provision async def reprovision_acme(): """ Provision a certificate from ACME, if required, and reload the TLS certificate if it's renewed. """ reprovisioned = await do_acme() if reprovisioned: _base.refresh_certificate(hs) async def start(): # Run the ACME provisioning code, if it's enabled. if hs.config.acme_enabled: acme = hs.get_acme_handler() # Start up the webservices which we will respond to ACME # challenges with, and then provision. await acme.start_listening() await do_acme() # Check if it needs to be reprovisioned every day. hs.get_clock().looping_call(reprovision_acme, 24 * 60 * 60 * 1000) # Load the OIDC provider metadatas, if OIDC is enabled. if hs.config.oidc_enabled: oidc = hs.get_oidc_handler() # Loading the provider metadata also ensures the provider config is valid. await oidc.load_metadata() await _base.start(hs, config.listeners) hs.get_datastore().db_pool.updates.start_doing_background_updates() register_start(start) return hs
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) synapse.config.logger.setup_logging( config, use_worker_options=False ) events.USE_FROZEN_DICTS = config.use_frozen_dicts database_engine = create_engine(config.database_config) config.database_config["args"]["cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, config=config, version_string="Synapse/" + get_version_string(synapse), database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: with hs.get_db_conn(run_new_connection=False) as db_conn: prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n" ) sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() hs.setup_master() @defer.inlineCallbacks def do_acme(): """ Reprovision an ACME certificate, if it's required. Returns: Deferred[bool]: Whether the cert has been updated. """ acme = hs.get_acme_handler() # Check how long the certificate is active for. cert_days_remaining = hs.config.is_disk_cert_valid( allow_self_signed=False ) # We want to reprovision if cert_days_remaining is None (meaning no # certificate exists), or the days remaining number it returns # is less than our re-registration threshold. provision = False if ( cert_days_remaining is None or cert_days_remaining < hs.config.acme_reprovision_threshold ): provision = True if provision: yield acme.provision_certificate() defer.returnValue(provision) @defer.inlineCallbacks def reprovision_acme(): """ Provision a certificate from ACME, if required, and reload the TLS certificate if it's renewed. """ reprovisioned = yield do_acme() if reprovisioned: _base.refresh_certificate(hs) @defer.inlineCallbacks def start(): try: # Run the ACME provisioning code, if it's enabled. if hs.config.acme_enabled: acme = hs.get_acme_handler() # Start up the webservices which we will respond to ACME # challenges with, and then provision. yield acme.start_listening() yield do_acme() # Check if it needs to be reprovisioned every day. hs.get_clock().looping_call( reprovision_acme, 24 * 60 * 60 * 1000 ) _base.start(hs, config.listeners) hs.get_pusherpool().start() hs.get_datastore().start_doing_background_updates() except Exception: # Print the exception and bail out. print("Error during startup:", file=sys.stderr) # this gives better tracebacks than traceback.print_exc() Failure().printTraceback(file=sys.stderr) if reactor.running: reactor.stop() sys.exit(1) reactor.callWhenRunning(start) return hs
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + str(e) + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) synapse.config.logger.setup_logging(config, use_worker_options=False) events.USE_FROZEN_DICTS = config.use_frozen_dicts database_engine = create_engine(config.database_config) config.database_config["args"][ "cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, config=config, version_string="Synapse/" + get_version_string(synapse), database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: with hs.get_db_conn(run_new_connection=False) as db_conn: prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n") sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() @defer.inlineCallbacks def do_acme(): """ Reprovision an ACME certificate, if it's required. Returns: Deferred[bool]: Whether the cert has been updated. """ acme = hs.get_acme_handler() # Check how long the certificate is active for. cert_days_remaining = hs.config.is_disk_cert_valid( allow_self_signed=False) # We want to reprovision if cert_days_remaining is None (meaning no # certificate exists), or the days remaining number it returns # is less than our re-registration threshold. provision = False if (cert_days_remaining is None or cert_days_remaining < hs.config.acme_reprovision_threshold): provision = True if provision: yield acme.provision_certificate() defer.returnValue(provision) @defer.inlineCallbacks def reprovision_acme(): """ Provision a certificate from ACME, if required, and reload the TLS certificate if it's renewed. """ reprovisioned = yield do_acme() if reprovisioned: _base.refresh_certificate(hs) @defer.inlineCallbacks def start(): try: # Run the ACME provisioning code, if it's enabled. if hs.config.acme_enabled: acme = hs.get_acme_handler() # Start up the webservices which we will respond to ACME # challenges with, and then provision. yield acme.start_listening() yield do_acme() # Check if it needs to be reprovisioned every day. hs.get_clock().looping_call(reprovision_acme, 24 * 60 * 60 * 1000) _base.start(hs, config.listeners) hs.get_pusherpool().start() hs.get_datastore().start_doing_background_updates() except Exception: # Print the exception and bail out. print("Error during startup:", file=sys.stderr) # this gives better tracebacks than traceback.print_exc() Failure().printTraceback(file=sys.stderr) if reactor.running: reactor.stop() sys.exit(1) reactor.callWhenRunning(start) return hs
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options, ) except ConfigError as e: sys.stderr.write("\n" + e.message + "\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) synapse.config.logger.setup_logging(config, use_worker_options=False) # check any extra requirements we have now we have a config check_requirements(config) version_string = "Synapse/" + get_version_string(synapse) logger.info("Server hostname: %s", config.server_name) logger.info("Server version: %s", version_string) events.USE_FROZEN_DICTS = config.use_frozen_dicts tls_server_context_factory = context_factory.ServerContextFactory(config) database_engine = create_engine(config.database_config) config.database_config["args"][ "cp_openfun"] = database_engine.on_new_connection hs = SynapseHomeServer( config.server_name, db_config=config.database_config, tls_server_context_factory=tls_server_context_factory, config=config, version_string=version_string, database_engine=database_engine, ) logger.info("Preparing database: %s...", config.database_config['name']) try: db_conn = hs.get_db_conn(run_new_connection=False) prepare_database(db_conn, database_engine, config=config) database_engine.on_new_connection(db_conn) hs.run_startup_checks(db_conn, database_engine) db_conn.commit() except UpgradeDatabaseException: sys.stderr.write( "\nFailed to upgrade database.\n" "Have you checked for version specific instructions in" " UPGRADES.rst?\n") sys.exit(1) logger.info("Database prepared in %s.", config.database_config['name']) hs.setup() hs.start_listening() def start(): hs.get_pusherpool().start() hs.get_state_handler().start_caching() hs.get_datastore().start_profiling() hs.get_datastore().start_doing_background_updates() hs.get_replication_layer().start_get_pdu_cache() register_memory_metrics(hs) reactor.callWhenRunning(start) return hs
def setup(config_options: List[str]) -> SynapseHomeServer: """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: A homeserver instance. """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options) except ConfigError as e: sys.stderr.write("\n") for f in format_config_error(e): sys.stderr.write(f) sys.stderr.write("\n") sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) if config.worker.worker_app: raise ConfigError( "You have specified `worker_app` in the config but are attempting to start a non-worker " "instance. Please use `python -m synapse.app.generic_worker` instead (or remove the option if this is the main process)." ) sys.exit(1) events.USE_FROZEN_DICTS = config.server.use_frozen_dicts synapse.util.caches.TRACK_MEMORY_USAGE = config.caches.track_memory_usage if config.server.gc_seconds: synapse.metrics.MIN_TIME_BETWEEN_GCS = config.server.gc_seconds if (config.registration.enable_registration and not config.registration.enable_registration_without_verification): if (not config.captcha.enable_registration_captcha and not config.registration.registrations_require_3pid and not config.registration.registration_requires_token): raise ConfigError( "You have enabled open registration without any verification. This is a known vector for " "spam and abuse. If you would like to allow public registration, please consider adding email, " "captcha, or token-based verification. Otherwise this check can be removed by setting the " "`enable_registration_without_verification` config option to `true`." ) hs = SynapseHomeServer( config.server.server_name, config=config, version_string="Synapse/" + get_distribution_version_string("matrix-synapse"), ) synapse.config.logger.setup_logging(hs, config, use_worker_options=False) logger.info("Setting up server") try: hs.setup() except Exception as e: handle_startup_exception(e) async def start() -> None: # Load the OIDC provider metadatas, if OIDC is enabled. if hs.config.oidc.oidc_enabled: oidc = hs.get_oidc_handler() # Loading the provider metadata also ensures the provider config is valid. await oidc.load_metadata() await _base.start(hs) hs.get_datastores( ).main.db_pool.updates.start_doing_background_updates() register_start(start) return hs
def test_load_fails_if_server_name_missing(self): self.generate_config_and_remove_lines_containing("server_name") with self.assertRaises(ConfigError): HomeServerConfig.load_config("", ["-c", self.file]) with self.assertRaises(ConfigError): HomeServerConfig.load_or_generate_config("", ["-c", self.file])
def setup(config_options): """ Args: config_options_options: The options passed to Synapse. Usually `sys.argv[1:]`. Returns: HomeServer """ try: config = HomeServerConfig.load_or_generate_config( "Synapse Homeserver", config_options) except ConfigError as e: sys.stderr.write("\nERROR: %s\n" % (e, )) sys.exit(1) if not config: # If a config isn't returned, and an exception isn't raised, we're just # generating config files and shouldn't try to continue. sys.exit(0) events.USE_FROZEN_DICTS = config.use_frozen_dicts hs = SynapseHomeServer( config.server_name, config=config, version_string="Synapse/" + get_version_string(synapse), ) synapse.config.logger.setup_logging(hs, config, use_worker_options=False) logger.info("Setting up server") try: hs.setup() except IncorrectDatabaseSetup as e: quit_with_error(str(e)) except UpgradeDatabaseException as e: quit_with_error("Failed to upgrade database: %s" % (e, )) hs.setup_master() @defer.inlineCallbacks def do_acme(): """ Reprovision an ACME certificate, if it's required. Returns: Deferred[bool]: Whether the cert has been updated. """ acme = hs.get_acme_handler() # Check how long the certificate is active for. cert_days_remaining = hs.config.is_disk_cert_valid( allow_self_signed=False) # We want to reprovision if cert_days_remaining is None (meaning no # certificate exists), or the days remaining number it returns # is less than our re-registration threshold. provision = False if (cert_days_remaining is None or cert_days_remaining < hs.config.acme_reprovision_threshold): provision = True if provision: yield acme.provision_certificate() return provision @defer.inlineCallbacks def reprovision_acme(): """ Provision a certificate from ACME, if required, and reload the TLS certificate if it's renewed. """ reprovisioned = yield do_acme() if reprovisioned: _base.refresh_certificate(hs) @defer.inlineCallbacks def start(): try: # Run the ACME provisioning code, if it's enabled. if hs.config.acme_enabled: acme = hs.get_acme_handler() # Start up the webservices which we will respond to ACME # challenges with, and then provision. yield acme.start_listening() yield do_acme() # Check if it needs to be reprovisioned every day. hs.get_clock().looping_call(reprovision_acme, 24 * 60 * 60 * 1000) _base.start(hs, config.listeners) hs.get_pusherpool().start() hs.get_datastore().db.updates.start_doing_background_updates() except Exception: # Print the exception and bail out. print("Error during startup:", file=sys.stderr) # this gives better tracebacks than traceback.print_exc() Failure().printTraceback(file=sys.stderr) if reactor.running: reactor.stop() sys.exit(1) reactor.callWhenRunning(start) return hs