Set up the server.
    Start all subsystems, write pid file, set up signal handlers, set up DB.
    Returns a server instance.

def server_setup(working_dir, port=None, api_port=None, indexer_enabled=None, indexer_url=None, api_enabled=None, recover=False):
    """
    Set up the server.
    Start all subsystems, write pid file, set up signal handlers, set up DB.
    Returns a server instance.
    """
    if not is_genesis_block_instantiated():
        # default genesis block
        genesis_block_load()

    blockstack_opts = get_blockstack_opts()
    blockstack_api_opts = get_blockstack_api_opts()
    pid_file = get_pidfile_path(working_dir)

    indexer_enabled = indexer_enabled if indexer_enabled is not None else blockstack_opts['enabled']
    api_enabled = api_enabled if api_enabled is not None else blockstack_api_opts['enabled']
    indexer_url = indexer_url if indexer_url is not None else blockstack_api_opts.get('indexer_url', None)

    # sanity check 
    if api_enabled and not indexer_url:
        print("FATAL: no 'indexer_url' in the config file, and no --indexer_url given in the arguments")
        sys.exit(1)

    if port is None:
        port = blockstack_opts['rpc_port']

    if api_port is None:
        api_port = blockstack_api_opts['api_port']

    # set up signals
    signal.signal( signal.SIGINT, blockstack_signal_handler )
    signal.signal( signal.SIGQUIT, blockstack_signal_handler )
    signal.signal( signal.SIGTERM, blockstack_signal_handler )

    # put pid file
    put_pidfile(pid_file, os.getpid())

    # clear indexing state
    set_indexing(working_dir, False)

    # process overrides
    if blockstack_opts['enabled'] != indexer_enabled:
        log.debug("Override blockstack.enabled to {}".format(indexer_enabled))
        blockstack_opts['enabled'] = indexer_enabled
        set_blockstack_opts(blockstack_opts)

    if blockstack_api_opts['enabled'] != api_enabled:
        log.debug("Override blockstack-api.enabled to {}".format(indexer_enabled))
        blockstack_api_opts['enabled'] = api_enabled
        set_blockstack_api_opts(blockstack_api_opts)

    if blockstack_api_opts['indexer_url'] != indexer_url:
        log.debug("Override blockstack-api.indexer_url to {}".format(indexer_url))
        blockstack_api_opts['indexer_url'] = indexer_url
        set_blockstack_api_opts(blockstack_api_opts)

    # start API servers
    rpc_srv = None
    api_srv = None
    atlas_state = None
    subdomain_state = None

    if blockstack_opts['enabled']:
        # get db state
        db = get_or_instantiate_db_state(working_dir)
    
        # set up atlas state, if we're an indexer
        atlas_state = atlas_init(blockstack_opts, db, port=port, recover=recover)
        db.close()

        # set up subdomains state
        subdomain_state = subdomains_init(blockstack_opts, working_dir, atlas_state)
    
        # start atlas node
        if atlas_state:
            atlas_node_start(atlas_state)
        
        # start back-plane API server
        rpc_srv = rpc_start(working_dir, port, subdomain_index=subdomain_state, thread=False)

    if blockstack_api_opts['enabled']:
        # start public RESTful API server
        api_srv = api_start(working_dir, blockstack_api_opts['api_host'], api_port, thread=False)

    if rpc_srv:
        rpc_srv.start()

    if api_srv:
        api_srv.start()

    # start GC
    gc_start()

    set_running(True)

    # clear any stale indexing state
    set_indexing(working_dir, False)

    log.debug("Server setup: API = {}, Indexer = {}, Indexer URL = {}".format(blockstack_api_opts['enabled'], blockstack_opts['enabled'], blockstack_api_opts['indexer_url']))

    ret = {
        'working_dir': working_dir,
        'atlas': atlas_state,
        'subdomains': subdomain_state,
        'subdomains_initialized': False,
        'rpc': rpc_srv,
        'api': api_srv,
        'pid_file': pid_file,
        'port': port,
        'api_port': api_port
    }

    return ret