rethinkdb / horizon-docs

Other
24 stars 36 forks source link

Describe how to run Horizon server without the `hz` CLI #77

Closed danielmewes closed 8 years ago

danielmewes commented 8 years ago

We have examples for running a Horizon server by instantiating the Server class in node.js (without using the hz serve CLI), but we don't have any formal documentation of this.

http://horizon.io/docs/server/ only covers how to use the CLI to start the server.

Some of the server options are also slightly different from the CLI options (e.g. hostname and port are separate options): https://github.com/rethinkdb/horizon/blob/061f784fa6f8cd6b30ffcaf6b88e823e0e386b3f/server/src/schema/server_options.js#L5 .

danielmewes commented 8 years ago

It also looks like this technique always requires setting up your own HTTP server first. I'm not sure what the requirements on the http_servers argument actually are.

@Tryneus Could you add some details about this please?

danielmewes commented 8 years ago

A related question came up on the horizon issue tracker about how to run the Horizon server within Express: https://github.com/rethinkdb/horizon/issues/425#issuecomment-222888180

danielmewes commented 8 years ago

One non-obvious aspect of this is configuring OAuth providers. You can't pass the provider options directly into the Server constructor, but need to call a separate add_auth_endpoint method on the server.

Here's some example code:

var horizon_server = require('@horizon/server');

var horizon_options = {
    auth: {
        token_secret: 'xxxx',
        allow_anonymous: true,
        allow_unauthenticated: true
    }
};

// ...
// Code to construct the http_server, e.g. with Express
// ...

var horizon_instance = horizon_server(http_server, horizon_options);

// Add an OAuth endpoint for GitHub
horizon_instance.add_auth_provider(
    horizon_server.auth["github"],
    {id: "xxxx", secret: "xxxx", path: "github"});
Tryneus commented 8 years ago

Here's a complete example script showing how to attach a Horizon server to multiple HTTP servers and add an auth endpoint (twitch) at the end. This assumes that a RethinkDB instance is running on localhost:28015, and that it has been initialized with hz set-schema.

'use strict';
const horizon = require('@horizon/server');

const fs = require('fs');
const http = require('http');
const https = require('https');

// Attach the horizon server to two http servers
// one on [::]:8181 over HTTPS and one on 127.0.0.1:8282 over HTTP
const on_http_request = (req, res) => {
  res.writeHead(404);
  res.end('File not found.');
};

const public_server = https.createServer({
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
}, on_http_request);

const loopback_server = http.createServer(on_http_request);

public_server.listen(8181);
loopback_server.listen(8282, '127.0.0.1');

const horizon_server =
  horizon([ public_server, loopback_server ], 
          {             
            project_name: 'foo',
            auth: {       
              token_secret: 'bar',
              allow_anonymous: true,
              allow_unauthenticated: true,
            },            
          });           

// Add twitch authentication
horizon_server.add_auth_provider(horizon.auth.twitch,
                                 {
                                   path: 'twitch',
                                   id: '0000000000000000000000000000000',
                                   secret: '0000000000000000000000000000000',
                                 });

// Shut down the server after 60 seconds
setTimeout(() => {
  horizon_server.close();
  public_server.close();
  loopback_server.close();
}, 60000);
danielmewes commented 8 years ago

We should also list the other supported options that can be passed into the server constructor. The full list is represented here: https://github.com/rethinkdb/horizon/blob/next/server/src/schema/server_options.js

danielmewes commented 8 years ago

@Tryneus What is the meaning of these three options in the auth field?

duration: Joi.alternatives(Joi.string(), Joi.number().positive()).default('1d'),
create_new_users: Joi.boolean().default(true),
new_user_group: Joi.string().default('authenticated'),