| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | // TODO if RAM is very low we should not fork at all,
 | 
					
						
							|  |  |  | // but use a different process altogether
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | console.info('pid:', process.pid); | 
					
						
							|  |  |  | console.info('title:', process.title); | 
					
						
							|  |  |  | console.info('arch:', process.arch); | 
					
						
							|  |  |  | console.info('platform:', process.platform); | 
					
						
							|  |  |  | console.info('\n\n\n[MASTER] Welcome to WALNUT!'); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:12:35 -04:00
										 |  |  | var path = require('path'); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | var cluster = require('cluster'); | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  | //var minWorkers = 2;
 | 
					
						
							| 
									
										
										
										
											2015-11-19 07:42:20 +00:00
										 |  |  | var numCores = 2; // Math.max(minWorkers, require('os').cpus().length);
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | var workers = []; | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  | var config = { | 
					
						
							|  |  |  |   externalPort: 443                                       // world accessible
 | 
					
						
							| 
									
										
										
										
											2015-11-23 08:45:20 +00:00
										 |  |  | , externalPortInsecure: 80                                // world accessible
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | // TODO externalInsecurePort?
 | 
					
						
							|  |  |  | , locked: false // TODO XXX
 | 
					
						
							|  |  |  | , ipcKey: null | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   // XXX
 | 
					
						
							| 
									
										
										
										
											2015-11-28 07:30:34 +00:00
										 |  |  |   // TODO needs mappings from db
 | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   // TODO autoconfig Caddy caddy
 | 
					
						
							|  |  |  |   // XXX
 | 
					
						
							|  |  |  | , caddy: { | 
					
						
							|  |  |  |     conf: __dirname + '/Caddyfile' | 
					
						
							|  |  |  |   , bin: '/usr/local/bin/caddy' | 
					
						
							|  |  |  |   , sitespath: path.join(__dirname, 'sites-enabled') | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | , redirects: [ | 
					
						
							|  |  |  |     { "ip": false, "id": "*", "value": false } // default no-www
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   , { "ip": false, "id": "daplie.domains", "value": null } | 
					
						
							|  |  |  |   , { "ip": false, "id": "*.daplie.domains", "value": false } | 
					
						
							|  |  |  |   , { "ip": false, "id": "no.daplie.domains", "value": false } | 
					
						
							|  |  |  |   , { "ip": false, "id": "*.no.daplie.domains", "value": false } | 
					
						
							|  |  |  |   , { "ip": false, "id": "ns2.daplie.domains", "value": false } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   , { "ip": true, "id": "maybe.daplie.domains", "value": null } | 
					
						
							|  |  |  |   , { "ip": true, "id": "*.maybe.daplie.domains", "value": null } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   , { "ip": true, "id": "www.daplie.domains", "value": null } | 
					
						
							|  |  |  |   , { "ip": true, "id": "yes.daplie.domains", "value": true } | 
					
						
							|  |  |  |   , { "ip": true, "id": "*.yes.daplie.domains", "value": true } | 
					
						
							|  |  |  |   , { "ip": true, "id": "ns1.daplie.domains", "value": false } | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  |   // TODO use sqlite3 or autogenerate ?
 | 
					
						
							|  |  |  | , 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') | 
					
						
							| 
									
										
										
										
											2016-03-29 16:00:19 -04:00
										 |  |  | // keys
 | 
					
						
							|  |  |  | // letsencrypt
 | 
					
						
							|  |  |  | // com.example.provider
 | 
					
						
							|  |  |  | // com.example.consumer
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  | var useCaddy = require('fs').existsSync(config.caddy.bin); | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | var state = {}; | 
					
						
							|  |  |  | var caddy; | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  | config.localPort = process.argv[2] || (useCaddy ? 4080 : 443);   // system / local network
 | 
					
						
							|  |  |  | config.insecurePort = process.argv[3] || (useCaddy ? 80 : 80);   // meh
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | function fork() { | 
					
						
							|  |  |  |   if (workers.length < numCores) { | 
					
						
							|  |  |  |     workers.push(cluster.fork()); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cluster.on('online', function (worker) { | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   console.info('[MASTER] Worker ' + worker.process.pid + ' is online'); | 
					
						
							|  |  |  |   fork(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   // TODO XXX Should these be configurable? If so, where?
 | 
					
						
							| 
									
										
										
										
											2016-03-28 21:12:35 -04:00
										 |  |  |   var certPaths = [ | 
					
						
							|  |  |  |     path.join(__dirname, 'certs', 'live') | 
					
						
							|  |  |  |   , path.join(__dirname, 'letsencrypt', 'live') | 
					
						
							|  |  |  |   ]; | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |   // TODO communicate config with environment vars?
 | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   var info = { | 
					
						
							| 
									
										
										
										
											2015-11-28 06:05:27 +00:00
										 |  |  |     type: 'walnut.init' | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   , conf: { | 
					
						
							|  |  |  |       protocol: useCaddy ? 'http' : 'https' | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |     , externalPort: config.externalPort | 
					
						
							|  |  |  |     , localPort: config.localPort | 
					
						
							|  |  |  |     , insecurePort: config.insecurePort | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |     , trustProxy: useCaddy ? true : false | 
					
						
							|  |  |  |     , certPaths: useCaddy ? null : certPaths | 
					
						
							|  |  |  |     , ipcKey: null | 
					
						
							| 
									
										
										
										
											2015-11-21 12:36:22 +00:00
										 |  |  |       // TODO let this load after server is listening
 | 
					
						
							| 
									
										
										
										
											2015-12-04 07:00:30 +00:00
										 |  |  |     , 'org.oauth3.consumer': config['org.oauth3.consumer'] | 
					
						
							|  |  |  |     , 'org.oauth3.provider': config['org.oauth3.provider'] | 
					
						
							|  |  |  |     , keys: config.keys | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   worker.send(info); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function touchMaster(msg) { | 
					
						
							| 
									
										
										
										
											2015-11-28 06:05:27 +00:00
										 |  |  |     if ('walnut.webserver.listening' !== msg.type) { | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |       console.warn('[MASTER] received unexpected message from worker'); | 
					
						
							|  |  |  |       console.warn(msg); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |     // calls init if init has not been called
 | 
					
						
							|  |  |  |     state.caddy = caddy; | 
					
						
							|  |  |  |     state.workers = workers; | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |     require('../lib/master').touch(config, state).then(function () { | 
					
						
							| 
									
										
										
										
											2015-11-28 06:05:27 +00:00
										 |  |  |       info.type = 'walnut.webserver.onrequest'; | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |       info.conf.ipcKey = config.ipcKey; | 
					
						
							|  |  |  |       info.conf.memstoreSock = config.memstoreSock; | 
					
						
							|  |  |  |       info.conf.sqlite3Sock = config.sqlite3Sock; | 
					
						
							| 
									
										
										
										
											2015-11-19 12:34:59 +00:00
										 |  |  |       // TODO get this from db config instead
 | 
					
						
							|  |  |  |       info.conf.privkey = config.privkey; | 
					
						
							|  |  |  |       info.conf.pubkey = config.pubkey; | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |       worker.send(info); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   worker.on('message', touchMaster); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cluster.on('exit', function (worker, code, signal) { | 
					
						
							| 
									
										
										
										
											2015-11-17 08:18:56 +00:00
										 |  |  |   console.info('[MASTER] Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   workers = workers.map(function (w) { | 
					
						
							|  |  |  |     if (worker !== w) { | 
					
						
							|  |  |  |       return w; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   }).filter(function (w) { | 
					
						
							|  |  |  |     return w; | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 07:42:20 +00:00
										 |  |  |   //console.log('WARNING: worker spawning turned off for debugging ');
 | 
					
						
							|  |  |  |   fork(); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | fork(); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  | if (useCaddy) { | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   caddy = require('../lib/spawn-caddy').create(config); | 
					
						
							| 
									
										
										
										
											2015-11-06 11:05:32 +00:00
										 |  |  |   // relies on { localPort, locked }
 | 
					
						
							| 
									
										
										
										
											2016-03-29 15:55:05 -04:00
										 |  |  |   caddy.spawn(config); | 
					
						
							| 
									
										
										
										
											2015-11-04 09:22:00 +00:00
										 |  |  | } |