//  [python]
def __init__(self, cfg, reactor=twisted.internet.reactor):
    self.reactor = reactor
    self.config_file = get_config_file_path()

    self.cfg = cfg

    logger.info("Starting Sydent server")

    self.pidfile = self.cfg.get('general', "pidfile.path");

    self.db = SqliteDatabase(self).db

    self.server_name = self.cfg.get('general', 'server.name')
    if self.server_name == '':
        self.server_name = os.uname()[1]
        logger.warn(("You had not specified a server name. I have guessed that this server is called '%s' "
                    + "and saved this in the config file. If this is incorrect, you should edit server.name in "
                    + "the config file.") % (self.server_name,))
        self.cfg.set('general', 'server.name', self.server_name)
        self.save_config()

    if self.cfg.has_option("general", "sentry_dsn"):
        # Only import and start sentry SDK if configured.
        import sentry_sdk
        sentry_sdk.init(
            dsn=self.cfg.get("general", "sentry_dsn"),
        )
        with sentry_sdk.configure_scope() as scope:
            scope.set_tag("sydent_server_name", self.server_name)

    if self.cfg.has_option("general", "prometheus_port"):
        import prometheus_client
        prometheus_client.start_http_server(
            port=self.cfg.getint("general", "prometheus_port"),
            addr=self.cfg.get("general", "prometheus_addr"),
        )

    if self.cfg.has_option("general", "templates.path"):
        # Get the possible brands by looking at directories under the
        # templates.path directory.
        root_template_path = self.cfg.get("general", "templates.path")
        if os.path.exists(root_template_path):
            self.valid_brands = {
                p for p in os.listdir(root_template_path) if os.path.isdir(os.path.join(root_template_path, p))
            }
        else:
            # This is a legacy code-path and assumes that verify_response_template,
            # email.template, and email.invite_template are defined.
            self.valid_brands = set()

    self.enable_v1_associations = parse_cfg_bool(
        self.cfg.get("general", "enable_v1_associations")
    )

    self.delete_tokens_on_bind = parse_cfg_bool(
        self.cfg.get("general", "delete_tokens_on_bind")
    )

    self.default_web_client_location = self.cfg.get(
        "email", "email.default_web_client_location"
    )
    self.username_obfuscate_characters = int(self.cfg.get(
        "email", "email.third_party_invite_username_obfuscate_characters"
    ))
    self.domain_obfuscate_characters = int(self.cfg.get(
        "email", "email.third_party_invite_domain_obfuscate_characters"
    ))

    # See if a pepper already exists in the database
    # Note: This MUST be run before we start serving requests, otherwise lookups for
    # 3PID hashes may come in before we've completed generating them
    hashing_metadata_store = HashingMetadataStore(self)
    lookup_pepper = hashing_metadata_store.get_lookup_pepper()
    if not lookup_pepper:
        # No pepper defined in the database, generate one
        lookup_pepper = generateAlphanumericTokenOfLength(5)

        # Store it in the database and rehash 3PIDs
        hashing_metadata_store.store_lookup_pepper(sha256_and_url_safe_base64,
                                                   lookup_pepper)

    self.validators = Validators()
    self.validators.email = EmailValidator(self)
    self.validators.msisdn = MsisdnValidator(self)

    self.keyring = Keyring()
    self.keyring.ed25519 = SydentEd25519(self).signing_key
    self.keyring.ed25519.alg = 'ed25519'

    self.sig_verifier = Verifier(self)

    self.servlets = Servlets()
    self.servlets.v1 = V1Servlet(self)
    self.servlets.v2 = V2Servlet(self)
    self.servlets.emailRequestCode = EmailRequestCodeServlet(self)
    self.servlets.emailRequestCodeV2 = EmailRequestCodeServlet(self, require_auth=True)
    self.servlets.emailValidate = EmailValidateCodeServlet(self)
    self.servlets.emailValidateV2 = EmailValidateCodeServlet(self, require_auth=True)
    self.servlets.msisdnRequestCode = MsisdnRequestCodeServlet(self)
    self.servlets.msisdnRequestCodeV2 = MsisdnRequestCodeServlet(self, require_auth=True)
    self.servlets.msisdnValidate = MsisdnValidateCodeServlet(self)
    self.servlets.msisdnValidateV2 = MsisdnValidateCodeServlet(self, require_auth=True)
    self.servlets.lookup = LookupServlet(self)
    self.servlets.bulk_lookup = BulkLookupServlet(self)
    self.servlets.hash_details = HashDetailsServlet(self, lookup_pepper)
    self.servlets.lookup_v2 = LookupV2Servlet(self, lookup_pepper)
    self.servlets.pubkey_ed25519 = Ed25519Servlet(self)
    self.servlets.pubkeyIsValid = PubkeyIsValidServlet(self)
    self.servlets.ephemeralPubkeyIsValid = EphemeralPubkeyIsValidServlet(self)
    self.servlets.threepidBind = ThreePidBindServlet(self)
    self.servlets.threepidBindV2 = ThreePidBindServlet(self, require_auth=True)
    self.servlets.threepidUnbind = ThreePidUnbindServlet(self)
    self.servlets.replicationPush = ReplicationPushServlet(self)
    self.servlets.getValidated3pid = GetValidated3pidServlet(self)
    self.servlets.getValidated3pidV2 = GetValidated3pidServlet(self, require_auth=True)
    self.servlets.storeInviteServlet = StoreInviteServlet(self)
    self.servlets.storeInviteServletV2 = StoreInviteServlet(self, require_auth=True)
    self.servlets.blindlySignStuffServlet = BlindlySignStuffServlet(self)
    self.servlets.blindlySignStuffServletV2 = BlindlySignStuffServlet(self, require_auth=True)
    self.servlets.termsServlet = TermsServlet(self)
    self.servlets.accountServlet = AccountServlet(self)
    self.servlets.registerServlet = RegisterServlet(self)
    self.servlets.logoutServlet = LogoutServlet(self)

    self.threepidBinder = ThreepidBinder(self)

    self.sslComponents = SslComponents(self)

    self.clientApiHttpServer = ClientApiHttpServer(self)
    self.replicationHttpsServer = ReplicationHttpsServer(self)
    self.replicationHttpsClient = ReplicationHttpsClient(self)

    self.pusher = Pusher(self)

    # A dedicated validation session store just to clean up old sessions every N minutes
    self.cleanupValSession = ThreePidValSessionStore(self)
    cb = task.LoopingCall(self.cleanupValSession.deleteOldSessions)
    cb.clock = self.reactor
    cb.start(10 * 60.0)

    # workaround for https://github.com/getsentry/sentry-python/issues/803: we
    # disable automatic GC and run it periodically instead.
    gc.disable()
    cb = task.LoopingCall(run_gc)
    cb.clock = self.reactor
    cb.start(1.0)