minor refactor
This commit is contained in:
parent
c2fc1e76e1
commit
3a86624b8b
145
boot/master.js
145
boot/master.js
|
@ -14,12 +14,23 @@ var cluster = require('cluster');
|
||||||
//var minWorkers = 2;
|
//var minWorkers = 2;
|
||||||
var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
|
var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
|
||||||
var workers = [];
|
var workers = [];
|
||||||
|
var state = { firstRun: true };
|
||||||
|
|
||||||
|
function fork() {
|
||||||
|
if (workers.length < numCores) {
|
||||||
|
workers.push(cluster.fork());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster.on('online', function (worker) {
|
||||||
|
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
|
||||||
|
fork();
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
externalPort: 443 // world accessible
|
externalPort: 443 // world accessible
|
||||||
, externalPortInsecure: 80 // world accessible
|
, externalPortInsecure: 80 // world accessible
|
||||||
// TODO externalInsecurePort?
|
// TODO externalInsecurePort?
|
||||||
, locked: false // TODO XXX
|
, locked: false // TODO XXX
|
||||||
, ipcKey: null
|
|
||||||
// XXX
|
// XXX
|
||||||
// TODO needs mappings from db
|
// TODO needs mappings from db
|
||||||
// TODO autoconfig Caddy caddy
|
// TODO autoconfig Caddy caddy
|
||||||
|
@ -29,7 +40,63 @@ var config = {
|
||||||
, bin: '/usr/local/bin/caddy'
|
, bin: '/usr/local/bin/caddy'
|
||||||
, sitespath: path.join(__dirname, 'sites-enabled')
|
, sitespath: path.join(__dirname, 'sites-enabled')
|
||||||
}
|
}
|
||||||
, redirects: [
|
};
|
||||||
|
var useCaddy = require('fs').existsSync(config.caddy.bin);
|
||||||
|
var caddy;
|
||||||
|
|
||||||
|
config.localPort = process.argv[2] || (useCaddy ? 4080 : 443); // system / local network
|
||||||
|
config.insecurePort = process.argv[3] || (useCaddy ? 80 : 80); // meh
|
||||||
|
if (state.firstRun) {
|
||||||
|
state.firstRun = false;
|
||||||
|
if (useCaddy) {
|
||||||
|
caddy = require('../lib/spawn-caddy').create(config);
|
||||||
|
// relies on { localPort, locked }
|
||||||
|
caddy.spawn(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO XXX Should these be configurable? If so, where?
|
||||||
|
var certPaths = [
|
||||||
|
path.join(__dirname, '..', '..', 'certs', 'live')
|
||||||
|
, path.join(__dirname, '..', '..', 'letsencrypt', 'live')
|
||||||
|
];
|
||||||
|
// TODO communicate config with environment vars?
|
||||||
|
var info = {
|
||||||
|
type: 'walnut.init'
|
||||||
|
, conf: {
|
||||||
|
protocol: useCaddy ? 'http' : 'https'
|
||||||
|
, externalPort: config.externalPort
|
||||||
|
, localPort: config.localPort
|
||||||
|
, insecurePort: config.insecurePort
|
||||||
|
, certPaths: useCaddy ? null : certPaths
|
||||||
|
, trustProxy: useCaddy ? true : false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function touchMaster(msg) {
|
||||||
|
if ('walnut.webserver.listening' !== msg.type) {
|
||||||
|
console.warn('[MASTER] received unexpected message from worker');
|
||||||
|
console.warn(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calls init if init has not been called
|
||||||
|
state.caddy = caddy;
|
||||||
|
state.workers = workers;
|
||||||
|
require('../lib/master').touch(config, state).then(function (results) {
|
||||||
|
//var memstore = results.memstore;
|
||||||
|
var sqlstore = results.sqlstore;
|
||||||
|
info.type = 'walnut.webserver.onrequest';
|
||||||
|
// TODO let this load after server is listening
|
||||||
|
info.conf['org.oauth3.consumer'] = config['org.oauth3.consumer'];
|
||||||
|
info.conf['org.oauth3.provider'] = config['org.oauth3.provider'];
|
||||||
|
info.conf.keys = config.keys;
|
||||||
|
info.conf.memstoreSock = config.memstoreSock;
|
||||||
|
info.conf.sqlite3Sock = config.sqlite3Sock;
|
||||||
|
// TODO get this from db config instead
|
||||||
|
info.conf.privkey = config.privkey;
|
||||||
|
info.conf.pubkey = config.pubkey;
|
||||||
|
info.conf.redirects = [
|
||||||
{ "ip": false, "id": "*", "value": false } // default no-www
|
{ "ip": false, "id": "*", "value": false } // default no-www
|
||||||
|
|
||||||
, { "ip": false, "id": "daplie.domains", "value": null }
|
, { "ip": false, "id": "daplie.domains", "value": null }
|
||||||
|
@ -45,77 +112,19 @@ var config = {
|
||||||
, { "ip": true, "id": "yes.daplie.domains", "value": true }
|
, { "ip": true, "id": "yes.daplie.domains", "value": true }
|
||||||
, { "ip": true, "id": "*.yes.daplie.domains", "value": true }
|
, { "ip": true, "id": "*.yes.daplie.domains", "value": true }
|
||||||
, { "ip": true, "id": "ns1.daplie.domains", "value": false }
|
, { "ip": true, "id": "ns1.daplie.domains", "value": false }
|
||||||
]
|
];
|
||||||
// TODO use sqlite3 or autogenerate ?
|
// TODO use sqlite3 or autogenerate ?
|
||||||
, privkey: require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem', 'ascii')
|
info.conf.privkey = require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem', 'ascii');
|
||||||
, pubkey: require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem.pub', 'ascii')
|
info.conf.pubkey = require('fs').readFileSync(__dirname + '/../../' + '/nsx.redirect-www.org.key.pem.pub', 'ascii');
|
||||||
// keys
|
// keys
|
||||||
// letsencrypt
|
// letsencrypt
|
||||||
// com.example.provider
|
// com.example.provider
|
||||||
// com.example.consumer
|
// com.example.consumer
|
||||||
};
|
|
||||||
var useCaddy = require('fs').existsSync(config.caddy.bin);
|
|
||||||
var state = {};
|
|
||||||
var caddy;
|
|
||||||
|
|
||||||
config.localPort = process.argv[2] || (useCaddy ? 4080 : 443); // system / local network
|
|
||||||
config.insecurePort = process.argv[3] || (useCaddy ? 80 : 80); // meh
|
|
||||||
|
|
||||||
function fork() {
|
|
||||||
if (workers.length < numCores) {
|
|
||||||
workers.push(cluster.fork());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cluster.on('online', function (worker) {
|
|
||||||
console.info('[MASTER] Worker ' + worker.process.pid + ' is online');
|
|
||||||
fork();
|
|
||||||
|
|
||||||
// TODO XXX Should these be configurable? If so, where?
|
|
||||||
var certPaths = [
|
|
||||||
path.join(__dirname, 'certs', 'live')
|
|
||||||
, path.join(__dirname, 'letsencrypt', 'live')
|
|
||||||
];
|
|
||||||
// TODO communicate config with environment vars?
|
|
||||||
var info = {
|
|
||||||
type: 'walnut.init'
|
|
||||||
, conf: {
|
|
||||||
protocol: useCaddy ? 'http' : 'https'
|
|
||||||
, externalPort: config.externalPort
|
|
||||||
, localPort: config.localPort
|
|
||||||
, insecurePort: config.insecurePort
|
|
||||||
, trustProxy: useCaddy ? true : false
|
|
||||||
, certPaths: useCaddy ? null : certPaths
|
|
||||||
, ipcKey: null
|
|
||||||
// TODO let this load after server is listening
|
|
||||||
, 'org.oauth3.consumer': config['org.oauth3.consumer']
|
|
||||||
, 'org.oauth3.provider': config['org.oauth3.provider']
|
|
||||||
, keys: config.keys
|
|
||||||
}
|
|
||||||
};
|
|
||||||
worker.send(info);
|
|
||||||
|
|
||||||
function touchMaster(msg) {
|
|
||||||
if ('walnut.webserver.listening' !== msg.type) {
|
|
||||||
console.warn('[MASTER] received unexpected message from worker');
|
|
||||||
console.warn(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calls init if init has not been called
|
|
||||||
state.caddy = caddy;
|
|
||||||
state.workers = workers;
|
|
||||||
require('../lib/master').touch(config, state).then(function () {
|
|
||||||
info.type = 'walnut.webserver.onrequest';
|
|
||||||
info.conf.ipcKey = config.ipcKey;
|
|
||||||
info.conf.memstoreSock = config.memstoreSock;
|
|
||||||
info.conf.sqlite3Sock = config.sqlite3Sock;
|
|
||||||
// TODO get this from db config instead
|
|
||||||
info.conf.privkey = config.privkey;
|
|
||||||
info.conf.pubkey = config.pubkey;
|
|
||||||
worker.send(info);
|
worker.send(info);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
worker.send(info);
|
||||||
worker.on('message', touchMaster);
|
worker.on('message', touchMaster);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -136,9 +145,3 @@ cluster.on('exit', function (worker, code, signal) {
|
||||||
});
|
});
|
||||||
|
|
||||||
fork();
|
fork();
|
||||||
|
|
||||||
if (useCaddy) {
|
|
||||||
caddy = require('../lib/spawn-caddy').create(config);
|
|
||||||
// relies on { localPort, locked }
|
|
||||||
caddy.spawn(config);
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,36 +21,30 @@ module.exports.create = function (securePort, insecurePort, info, serverCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
function redirectHttps(req, res) {
|
function redirectHttps(req, res) {
|
||||||
|
if (req.headers.host && /^\/.well-known\/acme-challenge/.test(req.url) && useAppInsecurely(req, res)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO
|
||||||
|
// XXX NOTE: info.conf.redirects may or may not be loaded at first
|
||||||
|
// the object will be modified when the config is loaded
|
||||||
|
if (!redirectives && info.redirects || info.conf.redirects) {
|
||||||
|
redirectives = require('./hostname-redirects').compile(info.redirects || info.conf.redirects);
|
||||||
|
}
|
||||||
|
if (require('./no-www').scrubTheDub(req, res, redirectives)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Let it do this once they visit the https site
|
// Let it do this once they visit the https site
|
||||||
// res.setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains; preload');
|
// res.setHeader('Strict-Transport-Security', 'max-age=10886400; includeSubDomains; preload');
|
||||||
|
|
||||||
var host = req.headers.host || '';
|
var host = req.headers.host || '';
|
||||||
var url = req.url;
|
var url = req.url;
|
||||||
|
|
||||||
// TODO
|
|
||||||
// XXX NOTE: info.conf.redirects may or may not be loaded at first
|
|
||||||
// the object will be modified when the config is loaded
|
|
||||||
if (!redirectives && info.conf.redirects) {
|
|
||||||
redirectives = require('./hostname-redirects').compile(info.conf.redirects);
|
|
||||||
}
|
|
||||||
if (require('./no-www').scrubTheDub(req, res, redirectives)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// allow exceptions for the case of arduino and whatnot that cannot handle https?
|
// allow exceptions for the case of arduino and whatnot that cannot handle https?
|
||||||
// http://evothings.com/is-it-possible-to-secure-micro-controllers-used-within-iot/
|
// http://evothings.com/is-it-possible-to-secure-micro-controllers-used-within-iot/
|
||||||
// needs ECDSA?
|
// needs ECDSA?
|
||||||
|
|
||||||
console.warn('HARD-CODED HTTPS EXCEPTION in insecure-server.js');
|
|
||||||
if (/redirect-www.org$/.test(host) && useAppInsecurely(req, res)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (/^\/.well-known\/acme-challenge/.test(req.url) && useAppInsecurely(req, res)) {
|
|
||||||
console.log('exception for acme-challenge');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var escapeHtml = require('escape-html');
|
var escapeHtml = require('escape-html');
|
||||||
var newLocation = 'https://'
|
var newLocation = 'https://'
|
||||||
+ host.replace(/:\d+/, ':' + securePort) + url
|
+ host.replace(/:\d+/, ':' + securePort) + url
|
||||||
|
|
|
@ -2,12 +2,10 @@
|
||||||
|
|
||||||
var cluster = require('cluster');
|
var cluster = require('cluster');
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var memstore;
|
|
||||||
var sqlstore;
|
|
||||||
// TODO
|
// TODO
|
||||||
// var rootMasterKey;
|
// var rootMasterKey;
|
||||||
|
|
||||||
function init(conf/*, state*/) {
|
function init(conf, state) {
|
||||||
if (!conf.ipcKey) {
|
if (!conf.ipcKey) {
|
||||||
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
conf.ipcKey = require('crypto').randomBytes(16).toString('base64');
|
||||||
}
|
}
|
||||||
|
@ -46,27 +44,20 @@ function init(conf/*, state*/) {
|
||||||
, store: cluster.isMaster && null //new require('express-session/session/memory')()
|
, store: cluster.isMaster && null //new require('express-session/session/memory')()
|
||||||
// TODO implement
|
// TODO implement
|
||||||
, key: conf.ipcKey
|
, key: conf.ipcKey
|
||||||
}).then(function (_memstore) {
|
|
||||||
memstore = _memstore;
|
|
||||||
return memstore;
|
|
||||||
})
|
})
|
||||||
, sqlite3.createServer({
|
, sqlite3.createServer({
|
||||||
verbose: null
|
verbose: null
|
||||||
, sock: conf.sqlite3Sock
|
, sock: conf.sqlite3Sock
|
||||||
, ipcKey: conf.ipcKey
|
, ipcKey: conf.ipcKey
|
||||||
}).then(function (_sqlstore) {
|
|
||||||
sqlstore = _sqlstore;
|
|
||||||
return sqlstore;
|
|
||||||
})
|
})
|
||||||
]).then(function (/*args*/) {
|
]).then(function (args) {
|
||||||
return conf;
|
state.memstore = args[0];
|
||||||
/*
|
state.sqlstore = args[1];
|
||||||
{
|
return {
|
||||||
conf: conf
|
conf: conf
|
||||||
, memstore: memstore // args[0]
|
, memstore: args[0]
|
||||||
, sqlstore: sqlstore // args[1]
|
, sqlstore: args[1]
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return promise;
|
return promise;
|
||||||
|
@ -83,13 +74,6 @@ function touch(conf, state) {
|
||||||
conf.initialized = true;
|
conf.initialized = true;
|
||||||
return conf;
|
return conf;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
setInterval(function () {
|
|
||||||
console.log('SIGUSR1 to caddy');
|
|
||||||
return caddy.update(caddyConf);
|
|
||||||
}, 10 * 60 * 1000);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.init = init;
|
module.exports.init = init;
|
||||||
|
|
Loading…
Reference in New Issue