static async initialize (options) {
    ArkimeConfig.#configFile ??= options.defaultConfigFile;

    if (ArkimeConfig.debug > 1) {
      console.log('ArkimeConfig.initialize', ArkimeConfig.#configFile, options);
    }

    if (options.defaultSections === undefined) {
      console.trace('defaultSections option must be set');
      process.exit();
    } else if (Array.isArray(options.defaultSections)) {
      ArkimeConfig.#defaultSections = options.defaultSections;
    } else {
      ArkimeConfig.#defaultSections = [options.defaultSections];
    }

    // The config is actually hidden
    if (ArkimeConfig.#configFile.endsWith('.hiddenconfig')) {
      ArkimeConfig.#configFile = fs.readFileSync(ArkimeConfig.#configFile).toString().split('\n')[0].trim();
    }
    if (ArkimeConfig.#configFile.startsWith('urlinfile://')) {
      ArkimeConfig.#configFile = fs.readFileSync(ArkimeConfig.#configFile.substring(12)).toString().split('\n')[0].trim();
    }

    ArkimeConfig.#uri = ArkimeConfig.#configFile;

    // If ARKIME__usersElasticsearch is set then create a temp config
    if (process.env.ARKIME__usersElasticsearch) {
      ArkimeConfig.#config = {
        [ArkimeConfig.#defaultSections[ArkimeConfig.#defaultSections.length - 1]]: {
          usersElasticsearch: process.env.ARKIME__usersElasticsearch,
          usersElasticsearchBasicAuth: process.env.ARKIME__usersElasticsearchBasicAuth,
          usersPrefix: process.env.ARKIME__usersPrefix
        }
      };
    }

    const parts = ArkimeConfig.#uri.split('://');

    if (parts.length === 1) {
      let missing = false;
      try { // check if the file exists
        fs.accessSync(ArkimeConfig.#uri, fs.constants.F_OK);
      } catch (err) { // if the file doesn't exist, create it
        console.log(`WARNING - ${ArkimeConfig.#uri} doesn't exist`);
        missing = true;
      }

      if (missing) {
        ArkimeConfig.#configImpl = ArkimeConfig.#schemes.missing;
      } else if (ArkimeConfig.#uri.endsWith('json')) {
        ArkimeConfig.#configImpl = ArkimeConfig.#schemes.json;
      } else if (ArkimeConfig.#uri.endsWith('yaml') || ArkimeConfig.#uri.endsWith('yml')) {
        ArkimeConfig.#configImpl = ArkimeConfig.#schemes.yaml;
      } else {
        ArkimeConfig.#configImpl = ArkimeConfig.#schemes.ini;
      }
    } else {
      ArkimeConfig.#configImpl = ArkimeConfig.#schemes[parts[0]];
    }

    await ArkimeConfig.reload();

    // Load includes, currently must be ini
    ArkimeConfig.#loadIncludes(ArkimeConfig.get('includes'));

    // Setup any defaults
    //
    if (ArkimeConfig.debug === 0) {
      ArkimeConfig.debug = parseInt(ArkimeConfig.get('debug', 0));
    }

    if (ArkimeConfig.debug) {
      console.log('Debug Level', ArkimeConfig.debug);
    }

    // Tell everything waiting on config we are done
    const loadedCbs = ArkimeConfig.#loadedCbs;
    ArkimeConfig.#loadedCbs = undefined; // Mark as loaded
    for (const cb of loadedCbs) {
      cb();
    }
  }
Initialize the ArkimeConfig subsystem
@param {string} options.defaultConfigFile what the default config file path is
@param {string} options.defaultSections what section to use when undefined