def run(**kwargs):
    """
    This function was necessary to separate from main() to accommodate for
    server startup path on system 3.0, which is server.main. In the case where
    the api is on system 3.0, server.main will redirect to this function with
    an additional argument of 'patch_old_init'. kwargs are hence used to allow
    the use of different length args
    """
    log_init()
    loop = asyncio.get_event_loop()
    log.info("API server version:  {}".format(__version__))
    if not os.environ.get("ENABLE_VIRTUAL_SMOOTHIE"):
        initialize_robot(loop)
        if ff.use_protocol_api_v2():
            loop.run_until_complete(hardware.cache_instruments())
        if not ff.disable_home_on_boot():
            log.info("Homing Z axes")
            if ff.use_protocol_api_v2():
                loop.run_until_complete(hardware.home_z())
            else:
                hardware.home_z()
        try:
            udev.setup_rules_file()
        except Exception:
            log.exception(
                "Could not setup udev rules, modules may not be detected")
    # Explicitly unlock resin updates in case a prior server left them locked
    resin.unlock_updates()

    server.run(kwargs.get('hostname'), kwargs.get('port'), kwargs.get('path'),
               loop)