Shares the same signature as express.js listen method, because it passes arguments to it
@param {Number} port
@param {String} [hostname]
@param {Function} [Callback]
@returns {{rpcNsp: (Emitter), io: {Object}, server: http.Server}}
function bootstrap () {
  var server = RPC.apply(null, arguments)
  var io = server.io

  var allQueries = []

  Object.keys(models).forEach(function (modelName) {
    var model = models[modelName]
    model._exposeCallback(server)
  })

  io.use(function (socket, next) {
    const registeredLQs = {}
    socket.moonridge = {
      registeredLQs: registeredLQs,
      user: {privilege_level: 0}
    } // default privilege level for any connected client

    socket.on('disconnect', function () {
      // clearing out liveQueries listeners
      debug(socket.id, ' socket disconnected, cleaning up LQ listeners')
      for (var LQId in registeredLQs) {
        var LQ = registeredLQs[LQId]
        LQ.removeListener(socket)
      }
    })

    next()
  })

  server.expose({
    MR: {
      getModels: function () {
        return Object.keys(models)
      },
      deAuthorize: function () {
        this.moonridge.user = {privilege_level: 0}	// for logging users out
      }
    }
  })

  if (process.env.MOONRIDGE_HEALTH === '1') {
    // this reveals any data that you use in queries to the public, so it should not be used in production when dealing with sensitive data

    server.expose({
      MR: {
        getHealth: function () {
          var allModels = {}
          var index = allQueries.length
          while (index--) {
            var modelQueriesForSerialization = {}
            var model = allQueries[index]
            for (var LQ in model.queries) {
              modelQueriesForSerialization[LQ] = Object.keys(model.queries[LQ].listeners).length
            }
            allModels[model.modelName] = modelQueriesForSerialization
          }
          return {
            pid: process.pid,
            memory: process.memoryUsage(),
            uptime: process.uptime(),   // in seconds
            liveQueries: allModels  // key is LQ.clientQuery and value is number of listening clients
          }
        }
      }
    })
  }

  return server
}