Compare commits
	
		
			No commits in common. "master" and "greenlock" have entirely different histories.
		
	
	
		
	
		
@ -1,7 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "bracketSpacing": true,
 | 
					 | 
				
			||||||
  "printWidth": 120,
 | 
					 | 
				
			||||||
  "tabWidth": 4,
 | 
					 | 
				
			||||||
  "trailingComma": "none",
 | 
					 | 
				
			||||||
  "useTabs": false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										210
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								README.md
									
									
									
									
									
								
							@ -1,68 +1,47 @@
 | 
				
			|||||||
# Replaced: Use Greenlock Express v3
 | 
					<!-- BANNER_TPL_BEGIN -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
See https://git.rootprojects.org/root/greenlock-express.js
 | 
					About Daplie: We're taking back the Internet!
 | 
				
			||||||
 | 
					--------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					Down with Google, Apple, and Facebook!
 | 
				
			||||||
"use strict";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
var pkg = require("./package.json");
 | 
					We're re-decentralizing the web and making it read-write again - one home cloud system at a time.
 | 
				
			||||||
require("greenlock-express")
 | 
					 | 
				
			||||||
    .init(function getConfig() {
 | 
					 | 
				
			||||||
        // Greenlock Config
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {
 | 
					Tired of serving the Empire? Come join the Rebel Alliance:
 | 
				
			||||||
            package: { name: pkg.name, version: pkg.version },
 | 
					 | 
				
			||||||
            maintainerEmail: pkg.author,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // put cluster on full throttle!
 | 
					<a href="mailto:jobs@daplie.com">jobs@daplie.com</a> | [Invest in Daplie on Wefunder](https://daplie.com/invest/) | [Pre-order Cloud](https://daplie.com/preorder/), The World's First Home Server for Everyone
 | 
				
			||||||
            cloudnative: true
 | 
					 | 
				
			||||||
            webscale: true
 | 
					 | 
				
			||||||
            cluster: true
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
    .serve(httpsWorker);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function httpsWorker(glx) {
 | 
					<!-- BANNER_TPL_END -->
 | 
				
			||||||
    // Serves on 80 and 443
 | 
					 | 
				
			||||||
    // Get's SSL certificates magically!
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glx.serveApp(function(req, res) {
 | 
					[](https://gitter.im/Daplie/letsencrypt-express?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 | 
				
			||||||
        res.end("Hello, Encrypted World!");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# OLD STUFF BELOW
 | 
					| [greenlock (lib)](https://git.daplie.com/Daplie/node-greenlock)
 | 
				
			||||||
 | 
					| [greenlock-cli](https://git.daplie.com/Daplie/greenlock-cli)
 | 
				
			||||||
# (Preserved for historical reference)
 | 
					| [greenlock-express](https://git.daplie.com/Daplie/greenlock-express)
 | 
				
			||||||
 | 
					 | 
				
			||||||
| A [Root](https://therootcompany.com) Project
 | 
					 | 
				
			||||||
| [greenlock (lib)](https://git.coolaj86.com/coolaj86/greenlock.js)
 | 
					 | 
				
			||||||
| [greenlock-cli](https://git.coolaj86.com/coolaj86/greenlock-cli.js)
 | 
					 | 
				
			||||||
| [greenlock-express](https://git.coolaj86.com/coolaj86/greenlock-express.js)
 | 
					 | 
				
			||||||
| **greenlock-cluster**
 | 
					| **greenlock-cluster**
 | 
				
			||||||
| [greenlock-koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js)
 | 
					| [greenlock-koa](https://git.daplie.com/Daplie/greenlock-koa)
 | 
				
			||||||
| [greenlock-hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js)
 | 
					| [greenlock-hapi](https://git.daplie.com/Daplie/greenlock-hapi)
 | 
				
			||||||
|
 | 
					|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# greenlock-cluster
 | 
					greenlock-cluster (letsencrypt-cluster)
 | 
				
			||||||
 | 
					===================
 | 
				
			||||||
(previously letsencrypt-cluster)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Use automatic letsencrypt with node on multiple cores or even multiple machines.
 | 
					Use automatic letsencrypt with node on multiple cores or even multiple machines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-   Take advantage of multi-core computing
 | 
					* Take advantage of multi-core computing
 | 
				
			||||||
-   Process certificates in master
 | 
					* Process certificates in master
 | 
				
			||||||
-   Serve https from multiple workers
 | 
					* Serve https from multiple workers
 | 
				
			||||||
-   Can work with any clustering strategy [#1](https://github.com/Daplie/letsencrypt-cluster/issues/1)
 | 
					* Can work with any clustering strategy [#1](https://github.com/Daplie/letsencrypt-cluster/issues/1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Install
 | 
					Install
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
npm install --save greenlock-cluster@2.x
 | 
					npm install --save greenlock-cluster@2.x
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Usage
 | 
					Usage
 | 
				
			||||||
 | 
					=====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In a cluster environment you have some main file that boots your app
 | 
					In a cluster environment you have some main file that boots your app
 | 
				
			||||||
and then conditionally loads certain code based on whether that fork
 | 
					and then conditionally loads certain code based on whether that fork
 | 
				
			||||||
@ -72,34 +51,35 @@ In such a file you might want to define some of the options that need
 | 
				
			|||||||
to be shared between both the master and the worker, like this:
 | 
					to be shared between both the master and the worker, like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`boot.js`:
 | 
					`boot.js`:
 | 
				
			||||||
 | 
					 | 
				
			||||||
```javascript
 | 
					```javascript
 | 
				
			||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var cluster = require("cluster");
 | 
					var cluster = require('cluster');
 | 
				
			||||||
var path = require("path");
 | 
					var path = require('path');
 | 
				
			||||||
var os = require("os");
 | 
					var os = require('os');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var main;
 | 
					var main;
 | 
				
			||||||
var sharedOptions = {
 | 
					var sharedOptions = {
 | 
				
			||||||
    webrootPath: path.join(os.tmpdir(), "acme-challenge"), // /tmp/acme-challenge
 | 
					  webrootPath: path.join(os.tmpdir(), 'acme-challenge')			// /tmp/acme-challenge
 | 
				
			||||||
    // used by le-challenge-fs, the default plugin
 | 
					                                                            // used by le-challenge-fs, the default plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    renewWithin: 14 * 24 * 60 * 60 * 1000, // 10 days before expiration
 | 
					, renewWithin: 10 * 24 * 60 * 60 * 1000 										// 10 days before expiration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    debug: true
 | 
					, debug: true
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (cluster.isMaster) {
 | 
					if (cluster.isMaster) {
 | 
				
			||||||
    main = require("./master");
 | 
					  main = require('./master');
 | 
				
			||||||
} else {
 | 
					}
 | 
				
			||||||
    main = require("./worker");
 | 
					else {
 | 
				
			||||||
 | 
					  main = require('./worker');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
main.init(sharedOptions);
 | 
					main.init(sharedOptions);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Master
 | 
					Master
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We think it makes the most sense to load greenlock in master.
 | 
					We think it makes the most sense to load greenlock in master.
 | 
				
			||||||
This can prevent race conditions (see [node-letsencrypt#45](https://github.com/Daplie/node-letsencrypt/issues/45))
 | 
					This can prevent race conditions (see [node-letsencrypt#45](https://github.com/Daplie/node-letsencrypt/issues/45))
 | 
				
			||||||
@ -112,7 +92,6 @@ The master takes **the same arguments** as `node-greenlock` (`challenge`, `store
 | 
				
			|||||||
plus a few extra (`approveDomains`... okay, just one extra):
 | 
					plus a few extra (`approveDomains`... okay, just one extra):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`master.js`:
 | 
					`master.js`:
 | 
				
			||||||
 | 
					 | 
				
			||||||
```javascript
 | 
					```javascript
 | 
				
			||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -123,9 +102,7 @@ module.exports.init = function (sharedOpts) {
 | 
				
			|||||||
  var leMaster = require('greenlock-cluster/master').create({
 | 
					  var leMaster = require('greenlock-cluster/master').create({
 | 
				
			||||||
    debug: sharedOpts.debug
 | 
					    debug: sharedOpts.debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // You MUST change this to 'https://acme-v02.api.letsencrypt.org/directory' in production
 | 
					  , server: 'staging'                                                       // CHANGE TO PRODUCTION
 | 
				
			||||||
    server: 'https://acme-staging-v02.api.letsencrypt.org/directory'
 | 
					 | 
				
			||||||
  , version: 'draft-11' // Let's Encrypt v2
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  , renewWithin: sharedOpts.renewWithin
 | 
					  , renewWithin: sharedOpts.renewWithin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -155,75 +132,75 @@ All options are passed directly to `node-greenlock`
 | 
				
			|||||||
(in other works, `leMaster` is a `greenlock` instance),
 | 
					(in other works, `leMaster` is a `greenlock` instance),
 | 
				
			||||||
but a few are only actually used by `greenlock-cluster`.
 | 
					but a few are only actually used by `greenlock-cluster`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-   `leOptions.approveDomains(options, certs, cb)` is special for `greenlock-cluster`, but will probably be included in `node-greenlock` in the future (no API change).
 | 
					* `leOptions.approveDomains(options, certs, cb)` is special for `greenlock-cluster`, but will probably be included in `node-greenlock` in the future (no API change).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-   `leMaster.addWorker(worker)` is added by `greenlock-cluster` and **must be called** for each new worker.
 | 
					* `leMaster.addWorker(worker)` is added by `greenlock-cluster` and **must be called** for each new worker.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Worker
 | 
					Worker
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The worker takes _similar_ arguments to `node-greenlock`,
 | 
					The worker takes *similar* arguments to `node-greenlock`,
 | 
				
			||||||
but only ones that are useful for determining certificate
 | 
					but only ones that are useful for determining certificate
 | 
				
			||||||
renewal and for `le.challenge.get`.
 | 
					renewal and for `le.challenge.get`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want to a non-default `le.challenge`
 | 
					If you want to  a non-default `le.challenge`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`worker.js`:
 | 
					`worker.js`:
 | 
				
			||||||
 | 
					 | 
				
			||||||
```javascript
 | 
					```javascript
 | 
				
			||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.init = function(sharedOpts) {
 | 
					module.exports.init = function (sharedOpts) {
 | 
				
			||||||
    var leWorker = require("greenlock-cluster/worker").create({
 | 
					  var leWorker = require('greenlock-cluster/worker').create({
 | 
				
			||||||
        debug: sharedOpts.debug,
 | 
					    debug: sharedOpts.debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        renewWithin: sharedOpts.renewWithin,
 | 
					  , renewWithin: sharedOpts.renewWithin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        webrootPath: sharedOpts.webrootPath,
 | 
					  , webrootPath: sharedOpts.webrootPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // , challenge: require('le-challenge-fs').create({ webrootPath: '...', ... })
 | 
					  // , challenge: require('le-challenge-fs').create({ webrootPath: '...', ... })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        approveDomains: function(workerOptions, certs, cb) {
 | 
					  , approveDomains: function (workerOptions, certs, cb) {
 | 
				
			||||||
            // opts = { domains, email, agreeTos, tosUrl }
 | 
					      // opts = { domains, email, agreeTos, tosUrl }
 | 
				
			||||||
            // certs = { subject, altnames, expiresAt, issuedAt }
 | 
					      // certs = { subject, altnames, expiresAt, issuedAt }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var results = {
 | 
					      var results = {
 | 
				
			||||||
                domain: workerOptions.domains[0],
 | 
					        domain: workerOptions.domains[0]
 | 
				
			||||||
                options: {
 | 
					      , options: {
 | 
				
			||||||
                    domains: workerOptions.domains
 | 
					          domains: workerOptions.domains
 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                certs: certs
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (certs) {
 | 
					 | 
				
			||||||
                // modify opts.domains to match the original request
 | 
					 | 
				
			||||||
                // email is not necessary, because the account already exists
 | 
					 | 
				
			||||||
                // this will only fail if the account has become corrupt
 | 
					 | 
				
			||||||
                results.options.domains = certs.altnames;
 | 
					 | 
				
			||||||
                cb(null, results);
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // This is where one would check one's application-specific database:
 | 
					 | 
				
			||||||
            //   1. Lookup the domain to see which email it belongs to
 | 
					 | 
				
			||||||
            //   2. Assign a default email if it isn't in the system
 | 
					 | 
				
			||||||
            //   3. If the email has no le account, `agreeToTerms` will fire unless `agreeTos` is preset
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            results.options.email = "john.doe@example.com";
 | 
					 | 
				
			||||||
            results.options.agreeTos = true; // causes agreeToTerms to be skipped
 | 
					 | 
				
			||||||
            cb(null, results);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					      , certs: certs
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function app(req, res) {
 | 
					      if (certs) {
 | 
				
			||||||
        res.end("Hello, World!");
 | 
					        // modify opts.domains to match the original request
 | 
				
			||||||
 | 
					        // email is not necessary, because the account already exists
 | 
				
			||||||
 | 
					        // this will only fail if the account has become corrupt
 | 
				
			||||||
 | 
					        results.options.domains = certs.altnames;
 | 
				
			||||||
 | 
					        cb(null, results);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // This is where one would check one's application-specific database:
 | 
				
			||||||
 | 
					      //   1. Lookup the domain to see which email it belongs to
 | 
				
			||||||
 | 
					      //   2. Assign a default email if it isn't in the system
 | 
				
			||||||
 | 
					      //   3. If the email has no le account, `agreeToTerms` will fire unless `agreeTos` is preset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      results.options.email = 'john.doe@example.com'
 | 
				
			||||||
 | 
					      results.options.agreeTos = true                                 // causes agreeToTerms to be skipped
 | 
				
			||||||
 | 
					      cb(null, results);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var redirectHttps = require("redirect-https")();
 | 
					  function app(req, res) {
 | 
				
			||||||
    var plainServer = require("http").createServer(leWorker.middleware(redirectHttps));
 | 
					    res.end("Hello, World!");
 | 
				
			||||||
    plainServer.listen(80);
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var server = require("https").createServer(leWorker.httpsOptions, leWorker.middleware(app));
 | 
					  var redirectHttps = require('redirect-https')();
 | 
				
			||||||
    server.listen(443);
 | 
					  var plainServer = require('http').createServer(leWorker.middleware(redirectHttps));
 | 
				
			||||||
 | 
					  plainServer.listen(80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var server = require('https').createServer(leWorker.httpsOptions, leWorker.middleware(app));
 | 
				
			||||||
 | 
					  server.listen(443);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -232,15 +209,16 @@ module.exports.init = function(sharedOpts) {
 | 
				
			|||||||
`node-greenlock` is **not used** directly by the worker,
 | 
					`node-greenlock` is **not used** directly by the worker,
 | 
				
			||||||
but certain options are shared because certain logic is duplicated.
 | 
					but certain options are shared because certain logic is duplicated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-   `leOptions.renewWithin` is shared so that the worker knows how earlier to request a new cert
 | 
					* `leOptions.renewWithin` is shared so that the worker knows how earlier to request a new cert
 | 
				
			||||||
-   `leOptions.renewBy` is passed to `le-sni-auto` so that it staggers renewals between `renewWithin` (latest) and `renewBy` (earlier)
 | 
					* `leOptions.renewBy` is passed to `le-sni-auto` so that it staggers renewals between `renewWithin` (latest) and `renewBy` (earlier)
 | 
				
			||||||
-   `leWorker.middleware(nextApp)` uses `greenlock/middleware` for GET-ing `http-01`, hence `sharedOptions.webrootPath`
 | 
					* `leWorker.middleware(nextApp)` uses `greenlock/middleware` for GET-ing `http-01`, hence `sharedOptions.webrootPath`
 | 
				
			||||||
-   `leWorker.httpsOptions` has a default localhost certificate and the `SNICallback`.
 | 
					* `leWorker.httpsOptions` has a default localhost certificate and the `SNICallback`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
There are a few options that aren't shown in these examples, so if you need to change something
 | 
					There are a few options that aren't shown in these examples, so if you need to change something
 | 
				
			||||||
that isn't shown here, look at the code (it's not that much) or open an issue.
 | 
					that isn't shown here, look at the code (it's not that much) or open an issue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Message Passing
 | 
					Message Passing
 | 
				
			||||||
 | 
					---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The master and workers will communicate through `process.on('message', fn)`, `process.send({})`,
 | 
					The master and workers will communicate through `process.on('message', fn)`, `process.send({})`,
 | 
				
			||||||
`worker.on('message', fn)`and `worker.send({})`.
 | 
					`worker.on('message', fn)`and `worker.send({})`.
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
## greenlock cluster examples
 | 
					greenlock cluster examples
 | 
				
			||||||
 | 
					-------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
First you need to change the email address in `examples/worker.js`.
 | 
					First you need to change the email address in `examples/worker.js`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,29 +1,35 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var cluster = require("cluster");
 | 
					var cluster = require('cluster');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.init = function(sharedOpts) {
 | 
					module.exports.init = function (sharedOpts) {
 | 
				
			||||||
    var numCores = 2; // // Math.max(2, require('os').cpus().length)
 | 
					  var numCores = 2; // // Math.max(2, require('os').cpus().length)
 | 
				
			||||||
    var i;
 | 
					  var i;
 | 
				
			||||||
    var master = require("../master").create({
 | 
					  var master = require('../master').create({
 | 
				
			||||||
        debug: true,
 | 
					    debug: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        server: "staging",
 | 
					 | 
				
			||||||
        webrootPath: sharedOpts.webrootPath,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        approveDomains: function(masterOptions, certs, cb) {
 | 
					 | 
				
			||||||
            // Depending on your setup it may be more efficient
 | 
					 | 
				
			||||||
            // for you to implement the approveDomains function
 | 
					 | 
				
			||||||
            // in your master or in your workers.
 | 
					 | 
				
			||||||
            //
 | 
					 | 
				
			||||||
            // Since we implement it in the worker (below) in this example
 | 
					 | 
				
			||||||
            // we'll give it an immediate approval here in the master
 | 
					 | 
				
			||||||
            var results = { domain: masterOptions.domain, options: masterOptions, certs: certs };
 | 
					 | 
				
			||||||
            cb(null, results);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < numCores; i += 1) {
 | 
					  , server: 'staging'
 | 
				
			||||||
        master.addWorker(cluster.fork());
 | 
					  , webrootPath: sharedOpts.webrootPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  , approveDomains: function (masterOptions, certs, cb) {
 | 
				
			||||||
 | 
					      // Depending on your setup it may be more efficient
 | 
				
			||||||
 | 
					      // for you to implement the approveDomains function
 | 
				
			||||||
 | 
					      // in your master or in your workers.
 | 
				
			||||||
 | 
					      //
 | 
				
			||||||
 | 
					      // Since we implement it in the worker (below) in this example
 | 
				
			||||||
 | 
					      // we'll give it an immediate approval here in the master
 | 
				
			||||||
 | 
					      var results = { domain: masterOptions.domain, options: masterOptions, certs: certs };
 | 
				
			||||||
 | 
					      cb(null, results);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (i = 0; i < numCores; i += 1) {
 | 
				
			||||||
 | 
					    master.addWorker(cluster.fork());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,27 +1,33 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var cluster = require("cluster");
 | 
					var cluster = require('cluster');
 | 
				
			||||||
var main;
 | 
					var main;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// You'll often see examples where people use cluster
 | 
					// You'll often see examples where people use cluster
 | 
				
			||||||
// master and worker all in the same file, which is fine,
 | 
					// master and worker all in the same file, which is fine,
 | 
				
			||||||
// but in order to conserve memory and especially to be
 | 
					// but in order to conserve memory and especially to be
 | 
				
			||||||
// less confusing, I'm splitting the code into two files
 | 
					// less confusing, I'm splitting the code into two files
 | 
				
			||||||
if (cluster.isMaster) {
 | 
					if (cluster.isMaster) {
 | 
				
			||||||
    main = require("./master");
 | 
					  main = require('./master');
 | 
				
			||||||
} else {
 | 
					 | 
				
			||||||
    main = require("./worker");
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
					  main = require('./worker');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// this is nothing greenlock-cluster specific
 | 
					// this is nothing greenlock-cluster specific
 | 
				
			||||||
// I'm just arbitrarily choosing to share some configuration
 | 
					// I'm just arbitrarily choosing to share some configuration
 | 
				
			||||||
// that I know I'm going to use in both places
 | 
					// that I know I'm going to use in both places
 | 
				
			||||||
main.init({
 | 
					main.init({
 | 
				
			||||||
    // Depending on the strategy, the whole le-challenge-<<strategy>>
 | 
					 | 
				
			||||||
    // could be shared between worker and server, but since I'm just
 | 
					 | 
				
			||||||
    // using using le-challenge-fs (as you'll see), I'm only sharing the webrootPath
 | 
					 | 
				
			||||||
    webrootPath: require("os").tmpdir() + require("path").sep + "acme-challenge",
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // this is used both by node-greenlock (master) and le-sni-auto (worker)
 | 
					  // Depending on the strategy, the whole le-challenge-<<strategy>>
 | 
				
			||||||
    renewWithin: 15 * 24 * 60 * 60 * 1000
 | 
					  // could be shared between worker and server, but since I'm just
 | 
				
			||||||
 | 
					  // using using le-challenge-fs (as you'll see), I'm only sharing the webrootPath
 | 
				
			||||||
 | 
					  webrootPath: require('os').tmpdir() + require('path').sep + 'acme-challenge'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // this is used both by node-greenlock (master) and le-sni-auto (worker)
 | 
				
			||||||
 | 
					, renewWithin: 15 * 24 * 60 * 60 * 1000
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -1,18 +1,24 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.init = function(sharedOpts) {
 | 
					module.exports.init = function (sharedOpts) {
 | 
				
			||||||
    var worker = require("../worker").create({
 | 
					  var worker = require('../worker').create({
 | 
				
			||||||
        debug: true,
 | 
					    debug: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We want both to renew well before the expiration date
 | 
					 | 
				
			||||||
        // and also to stagger the renewals, just a touch
 | 
					 | 
				
			||||||
        // here we specify to renew between 10 and 15 days
 | 
					 | 
				
			||||||
        renewWithin: sharedOpts.renewWithin,
 | 
					 | 
				
			||||||
        renewBy: 10 * 24 * 60 * 60 * 1000, // optional
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        webrootPath: sharedOpts.webrootPath,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*
 | 
					    // We want both to renew well before the expiration date
 | 
				
			||||||
 | 
					    // and also to stagger the renewals, just a touch
 | 
				
			||||||
 | 
					    // here we specify to renew between 10 and 15 days
 | 
				
			||||||
 | 
					  , renewWithin: sharedOpts.renewWithin
 | 
				
			||||||
 | 
					  , renewBy: 10 * 24 * 60 * 60 * 1000 // optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  , webrootPath: sharedOpts.webrootPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
    challenge: {
 | 
					    challenge: {
 | 
				
			||||||
      get: function (ignored, domain, token, cb) {
 | 
					      get: function (ignored, domain, token, cb) {
 | 
				
			||||||
        cb(null, keyAuthorization);
 | 
					        cb(null, keyAuthorization);
 | 
				
			||||||
@ -27,48 +33,55 @@ module.exports.init = function(sharedOpts) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // There are two approval processes:
 | 
					 | 
				
			||||||
        // 1. emails are tied to private keys (accounts) which must agree to the tos url
 | 
					 | 
				
			||||||
        // 2. domains are tied to accounts (and should be verifiable via loopback)
 | 
					 | 
				
			||||||
        approveDomains: function(workerOptions, certs, cb) {
 | 
					 | 
				
			||||||
            // opts = { domains, email, agreeTos, tosUrl }
 | 
					 | 
				
			||||||
            // certs = { subject, altnames, expiresAt, issuedAt }
 | 
					 | 
				
			||||||
            var results = {
 | 
					 | 
				
			||||||
                domain: workerOptions.domains[0],
 | 
					 | 
				
			||||||
                options: {
 | 
					 | 
				
			||||||
                    domains: (certs && certs.altnames) || workerOptions.domains,
 | 
					 | 
				
			||||||
                    email: "john.doe@example.com",
 | 
					 | 
				
			||||||
                    agreeTos: true
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                certs: certs
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We might want to do a check to make sure that all of the domains
 | 
					    // There are two approval processes:
 | 
				
			||||||
            // specified in altnames are still approved to be renewed and have
 | 
					    // 1. emails are tied to private keys (accounts) which must agree to the tos url
 | 
				
			||||||
            // the correct dns entries, but generally speaking it's probably okay
 | 
					    // 2. domains are tied to accounts (and should be verifiable via loopback)
 | 
				
			||||||
            // for renewals to be automatic
 | 
					  , approveDomains: function (workerOptions, certs, cb) {
 | 
				
			||||||
            if (certs) {
 | 
					      // opts = { domains, email, agreeTos, tosUrl }
 | 
				
			||||||
                // modify opts.domains to overwrite certs.altnames in renewal
 | 
					      // certs = { subject, altnames, expiresAt, issuedAt }
 | 
				
			||||||
                cb(null, results);
 | 
					      var results = {
 | 
				
			||||||
                return;
 | 
					        domain: workerOptions.domains[0]
 | 
				
			||||||
            }
 | 
					      , options: {
 | 
				
			||||||
 | 
					          domains: certs && certs.altnames || workerOptions.domains
 | 
				
			||||||
            // This is where we would check our database to make sure that
 | 
					        , email: 'john.doe@example.com'
 | 
				
			||||||
            // this user (specified by email address) has agreed to the terms
 | 
					        , agreeTos: true
 | 
				
			||||||
            // and do some check that they have access to this domain
 | 
					 | 
				
			||||||
            cb(null, results);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					      , certs: certs
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function app(req, res) {
 | 
					
 | 
				
			||||||
        res.end("Hello, World!");
 | 
					
 | 
				
			||||||
 | 
					      // We might want to do a check to make sure that all of the domains
 | 
				
			||||||
 | 
					      // specified in altnames are still approved to be renewed and have
 | 
				
			||||||
 | 
					      // the correct dns entries, but generally speaking it's probably okay
 | 
				
			||||||
 | 
					      // for renewals to be automatic
 | 
				
			||||||
 | 
					      if (certs) {
 | 
				
			||||||
 | 
					        // modify opts.domains to overwrite certs.altnames in renewal
 | 
				
			||||||
 | 
					        cb(null, results);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // This is where we would check our database to make sure that
 | 
				
			||||||
 | 
					      // this user (specified by email address) has agreed to the terms
 | 
				
			||||||
 | 
					      // and do some check that they have access to this domain
 | 
				
			||||||
 | 
					      cb(null, results);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // worker.handleAcmeOrRedirectToHttps()
 | 
					  function app(req, res) {
 | 
				
			||||||
    // worker.handleAcmeOrUse(app)
 | 
					    res.end("Hello, World!");
 | 
				
			||||||
    var redirectHttps = require("redirect-https")();
 | 
					  }
 | 
				
			||||||
    var plainServer = require("http").createServer(worker.middleware(redirectHttps));
 | 
					
 | 
				
			||||||
    var server = require("https").createServer(worker.httpsOptions, worker.middleware(app));
 | 
					
 | 
				
			||||||
    plainServer.listen(80);
 | 
					  // worker.handleAcmeOrRedirectToHttps()
 | 
				
			||||||
    server.listen(443);
 | 
					  // worker.handleAcmeOrUse(app)
 | 
				
			||||||
 | 
					  var redirectHttps = require('redirect-https')();
 | 
				
			||||||
 | 
					  var plainServer = require('http').createServer(worker.middleware(redirectHttps));
 | 
				
			||||||
 | 
					  var server = require('https').createServer(worker.httpsOptions, worker.middleware(app));
 | 
				
			||||||
 | 
					  plainServer.listen(80);
 | 
				
			||||||
 | 
					  server.listen(443);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										13
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								index.js
									
									
									
									
									
								
							@ -1,3 +1,12 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = require("@root/greenlock-express");
 | 
					console.error("");
 | 
				
			||||||
 | 
					console.error("One does not simply require('greenlock-cluster');");
 | 
				
			||||||
 | 
					console.error("");
 | 
				
			||||||
 | 
					console.error("Usage:");
 | 
				
			||||||
 | 
					console.error("\trequire('greenlock-cluster/master').create({ ... });");
 | 
				
			||||||
 | 
					console.error("\trequire('greenlock-cluster/worker').create({ ... });");
 | 
				
			||||||
 | 
					console.error("");
 | 
				
			||||||
 | 
					console.error("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					process.exit(1);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										138
									
								
								master.js
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								master.js
									
									
									
									
									
								
							@ -1,61 +1,59 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// opts.addWorker(worker)
 | 
					// opts.addWorker(worker)
 | 
				
			||||||
// opts.approveDomains(options, certs, cb)
 | 
					// opts.approveDomains(options, certs, cb)
 | 
				
			||||||
module.exports.create = function(opts) {
 | 
					module.exports.create = function (opts) {
 | 
				
			||||||
    opts = opts || {};
 | 
					  opts = opts || { };
 | 
				
			||||||
    opts._workers = [];
 | 
					  opts._workers = [];
 | 
				
			||||||
    opts.webrootPath = opts.webrootPath || require("os").tmpdir() + require("path").sep + "acme-challenge";
 | 
					  opts.webrootPath = opts.webrootPath || require('os').tmpdir() + require('path').sep + 'acme-challenge';
 | 
				
			||||||
    if (!opts.greenlock) {
 | 
					  if (!opts.greenlock) { opts.greenlock = require('greenlock').create(opts); }
 | 
				
			||||||
        opts.greenlock = require("greenlock").create(opts);
 | 
					  if ('function' !== typeof opts.approveDomains) {
 | 
				
			||||||
    }
 | 
					    throw new Error("You must provide opts.approveDomains(domain, certs, callback) to approve certificates");
 | 
				
			||||||
    if ("function" !== typeof opts.approveDomains) {
 | 
					  }
 | 
				
			||||||
        throw new Error("You must provide opts.approveDomains(domain, certs, callback) to approve certificates");
 | 
					
 | 
				
			||||||
 | 
					  function log(debug) {
 | 
				
			||||||
 | 
					    if (!debug) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function log(debug) {
 | 
					    var args = Array.prototype.slice.call(arguments);
 | 
				
			||||||
        if (!debug) {
 | 
					    args.shift();
 | 
				
			||||||
            return;
 | 
					    args.unshift("[le/lib/core.js]");
 | 
				
			||||||
 | 
					    console.log.apply(console, args);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  opts.addWorker = function (worker) {
 | 
				
			||||||
 | 
					    opts._workers.push(worker);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    worker.on('online', function () {
 | 
				
			||||||
 | 
					      log(opts.debug, 'worker is up');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    worker.on('message', function (msg) {
 | 
				
			||||||
 | 
					      log(opts.debug, 'Message from worker ' + worker.id);
 | 
				
			||||||
 | 
					      if ('LE_REQUEST' !== (msg && msg.type)) {
 | 
				
			||||||
 | 
					        log(opts.debug, 'Ignoring irrelevant message');
 | 
				
			||||||
 | 
					        log(opts.debug, msg);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      log(opts.debug, 'about to approveDomains');
 | 
				
			||||||
 | 
					      opts.approveDomains(msg.options, msg.certs, function (err, results) {
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					          log(opts.debug, 'Approval got ERROR', err.stack || err);
 | 
				
			||||||
 | 
					          worker.send({
 | 
				
			||||||
 | 
					            type: 'LE_RESPONSE'
 | 
				
			||||||
 | 
					          , domain: msg.domain
 | 
				
			||||||
 | 
					          , error: { message: err.message, code: err.code, stack: err.stack }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var args = Array.prototype.slice.call(arguments);
 | 
					        var promise;
 | 
				
			||||||
        args.shift();
 | 
					 | 
				
			||||||
        args.unshift("[le/lib/core.js]");
 | 
					 | 
				
			||||||
        console.log.apply(console, args);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    opts.addWorker = function(worker) {
 | 
					        //
 | 
				
			||||||
        opts._workers.push(worker);
 | 
					        /*
 | 
				
			||||||
 | 
					        var certs = require('localhost.daplie.com-certificates').merge({
 | 
				
			||||||
        worker.on("online", function() {
 | 
					 | 
				
			||||||
            log(opts.debug, "worker is up");
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        worker.on("message", function(msg) {
 | 
					 | 
				
			||||||
            log(opts.debug, "Message from worker " + worker.id);
 | 
					 | 
				
			||||||
            if ("LE_REQUEST" !== (msg && msg.type)) {
 | 
					 | 
				
			||||||
                log(opts.debug, "Ignoring irrelevant message");
 | 
					 | 
				
			||||||
                log(opts.debug, msg);
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            log(opts.debug, "about to approveDomains");
 | 
					 | 
				
			||||||
            opts.approveDomains(msg.options, msg.certs, function(err, results) {
 | 
					 | 
				
			||||||
                if (err) {
 | 
					 | 
				
			||||||
                    log(opts.debug, "Approval got ERROR", err.stack || err);
 | 
					 | 
				
			||||||
                    worker.send({
 | 
					 | 
				
			||||||
                        type: "LE_RESPONSE",
 | 
					 | 
				
			||||||
                        domain: msg.domain,
 | 
					 | 
				
			||||||
                        error: { message: err.message, code: err.code, stack: err.stack }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var promise;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                //
 | 
					 | 
				
			||||||
                /*
 | 
					 | 
				
			||||||
        var certs = require('localhost.example.com-certificates').merge({
 | 
					 | 
				
			||||||
          subject: msg.domain
 | 
					          subject: msg.domain
 | 
				
			||||||
        , altnames: [ msg.domain ]
 | 
					        , altnames: [ msg.domain ]
 | 
				
			||||||
        , issuedAt: Date.now()
 | 
					        , issuedAt: Date.now()
 | 
				
			||||||
@ -68,28 +66,26 @@ module.exports.create = function(opts) {
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
        // */
 | 
					        // */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (results.certs) {
 | 
					        if (results.certs) {
 | 
				
			||||||
                    promise = opts.greenlock.renew(results.options, results.certs);
 | 
					          promise = opts.greenlock.renew(results.options, results.certs);
 | 
				
			||||||
                } else {
 | 
					        }
 | 
				
			||||||
                    promise = opts.greenlock.register(results.options);
 | 
					        else {
 | 
				
			||||||
                }
 | 
					          promise = opts.greenlock.register(results.options);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                promise.then(
 | 
					        promise.then(function (certs) {
 | 
				
			||||||
                    function(certs) {
 | 
					          log(opts.debug, 'Approval got certs', certs);
 | 
				
			||||||
                        log(opts.debug, "Approval got certs", certs);
 | 
					          // certs = { subject, domains, issuedAt, expiresAt, privkey, cert, chain };
 | 
				
			||||||
                        // certs = { subject, domains, issuedAt, expiresAt, privkey, cert, chain };
 | 
					          opts._workers.forEach(function (w) {
 | 
				
			||||||
                        opts._workers.forEach(function(w) {
 | 
					            w.send({ type: 'LE_RESPONSE', domain: msg.domain, certs: certs });
 | 
				
			||||||
                            w.send({ type: "LE_RESPONSE", domain: msg.domain, certs: certs });
 | 
					          });
 | 
				
			||||||
                        });
 | 
					        }, function (err) {
 | 
				
			||||||
                    },
 | 
					          log(opts.debug, 'Approval got ERROR', err.stack || err);
 | 
				
			||||||
                    function(err) {
 | 
					          worker.send({ type: 'LE_RESPONSE', domain: msg.domain, error: err });
 | 
				
			||||||
                        log(opts.debug, "Approval got ERROR", err.stack || err);
 | 
					 | 
				
			||||||
                        worker.send({ type: "LE_RESPONSE", domain: msg.domain, error: err });
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return opts;
 | 
					  return opts;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										149
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										149
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -1,149 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
    "name": "greenlock-cluster",
 | 
					 | 
				
			||||||
    "version": "3.0.0",
 | 
					 | 
				
			||||||
    "lockfileVersion": 1,
 | 
					 | 
				
			||||||
    "requires": true,
 | 
					 | 
				
			||||||
    "dependencies": {
 | 
					 | 
				
			||||||
        "@root/acme": {
 | 
					 | 
				
			||||||
            "version": "3.0.8",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/acme/-/acme-3.0.8.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-VmBvLvWdCDkolkanI9Dzm1ouSWPaAa2eCCwcDZcVQbWoNiUIOqbbd57fcMA/gZxLyuJPStD2WXFuEuSMPDxcww==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/encoding": "^1.0.1",
 | 
					 | 
				
			||||||
                "@root/keypairs": "^0.9.0",
 | 
					 | 
				
			||||||
                "@root/pem": "^1.0.4",
 | 
					 | 
				
			||||||
                "@root/request": "^1.3.11",
 | 
					 | 
				
			||||||
                "@root/x509": "^0.7.2"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/asn1": {
 | 
					 | 
				
			||||||
            "version": "1.0.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/asn1/-/asn1-1.0.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-0lfZNuOULKJDJmdIkP8V9RnbV3XaK6PAHD3swnFy4tZwtlMDzLKoM/dfNad7ut8Hu3r91wy9uK0WA/9zym5mig==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/encoding": "^1.0.1"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/csr": {
 | 
					 | 
				
			||||||
            "version": "0.8.1",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/csr/-/csr-0.8.1.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-hKl0VuE549TK6SnS2Yn9nRvKbFZXn/oAg+dZJU/tlKl/f/0yRXeuUzf8akg3JjtJq+9E592zDqeXZ7yyrg8fSQ==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/asn1": "^1.0.0",
 | 
					 | 
				
			||||||
                "@root/pem": "^1.0.4",
 | 
					 | 
				
			||||||
                "@root/x509": "^0.7.2"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/encoding": {
 | 
					 | 
				
			||||||
            "version": "1.0.1",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/encoding/-/encoding-1.0.1.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-OaEub02ufoU038gy6bsNHQOjIn8nUjGiLcaRmJ40IUykneJkIW5fxDqKxQx48cszuNflYldsJLPPXCrGfHs8yQ=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/greenlock": {
 | 
					 | 
				
			||||||
            "version": "3.0.25",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/greenlock/-/greenlock-3.0.25.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-VC8H9MTkbqxlB2LGntmcq5cstkE0TdZLvxm25SO5i7c6abJBVMQafhTD415OXwoGimnmWTn6SZ93Fj73d9QX/w==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/acme": "^3.0.8",
 | 
					 | 
				
			||||||
                "@root/csr": "^0.8.1",
 | 
					 | 
				
			||||||
                "@root/keypairs": "^0.9.0",
 | 
					 | 
				
			||||||
                "@root/mkdirp": "^1.0.0",
 | 
					 | 
				
			||||||
                "@root/request": "^1.3.10",
 | 
					 | 
				
			||||||
                "acme-http-01-standalone": "^3.0.5",
 | 
					 | 
				
			||||||
                "cert-info": "^1.5.1",
 | 
					 | 
				
			||||||
                "greenlock-manager-fs": "^3.0.1",
 | 
					 | 
				
			||||||
                "greenlock-store-fs": "^3.2.0",
 | 
					 | 
				
			||||||
                "safe-replace": "^1.1.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/greenlock-express": {
 | 
					 | 
				
			||||||
            "version": "3.0.13",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/greenlock-express/-/greenlock-express-3.0.13.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-SgFsP4rBDPRBp52yqb8kONw7ZCkgyYrBFJLg4xhfIMbsMct4dfqB+N5eJbeF/exJh4+BHM7tppvf31Xuz6EO2Q==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/greenlock": "^3.0.25",
 | 
					 | 
				
			||||||
                "redirect-https": "^1.1.5"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/keypairs": {
 | 
					 | 
				
			||||||
            "version": "0.9.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/keypairs/-/keypairs-0.9.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-NXE2L9Gv7r3iC4kB/gTPZE1vO9Ox/p14zDzAJ5cGpTpytbWOlWF7QoHSJbtVX4H7mRG/Hp7HR3jWdWdb2xaaXg==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/encoding": "^1.0.1",
 | 
					 | 
				
			||||||
                "@root/pem": "^1.0.4",
 | 
					 | 
				
			||||||
                "@root/x509": "^0.7.2"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/mkdirp": {
 | 
					 | 
				
			||||||
            "version": "1.0.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/mkdirp/-/mkdirp-1.0.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-hxGAYUx5029VggfG+U9naAhQkoMSXtOeXtbql97m3Hi6/sQSRL/4khKZPyOF6w11glyCOU38WCNLu9nUcSjOfA=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/pem": {
 | 
					 | 
				
			||||||
            "version": "1.0.4",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/pem/-/pem-1.0.4.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-rEUDiUsHtild8GfIjFE9wXtcVxeS+ehCJQBwbQQ3IVfORKHK93CFnRtkr69R75lZFjcmKYVc+AXDB+AeRFOULA=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/request": {
 | 
					 | 
				
			||||||
            "version": "1.4.2",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/request/-/request-1.4.2.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-J8FM4+SJuc7WRC+Jz17m+VT2lgI7HtatHhxN1F2ck5aIKUAxJEaR4u/gLBsgT60mVHevKCjKN0O8115UtJjwLw=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "@root/x509": {
 | 
					 | 
				
			||||||
            "version": "0.7.2",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/@root/x509/-/x509-0.7.2.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-ENq3LGYORK5NiMFHEVeNMt+fTXaC7DTS6sQXoqV+dFdfT0vmiL5cDLjaXQhaklJQq0NiwicZegzJRl1ZOTp3WQ==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/asn1": "^1.0.0",
 | 
					 | 
				
			||||||
                "@root/encoding": "^1.0.1"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "acme-http-01-standalone": {
 | 
					 | 
				
			||||||
            "version": "3.0.5",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/acme-http-01-standalone/-/acme-http-01-standalone-3.0.5.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-W4GfK+39GZ+u0mvxRVUcVFCG6gposfzEnSBF20T/NUwWAKG59wQT1dUbS1NixRIAsRuhpGc4Jx659cErFQH0Pg=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "cert-info": {
 | 
					 | 
				
			||||||
            "version": "1.5.1",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/cert-info/-/cert-info-1.5.1.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-eoQC/yAgW3gKTKxjzyClvi+UzuY97YCjcl+lSqbsGIy7HeGaWxCPOQFivhUYm27hgsBMhsJJFya3kGvK6PMIcQ=="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "escape-html": {
 | 
					 | 
				
			||||||
            "version": "1.0.3",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "greenlock-manager-fs": {
 | 
					 | 
				
			||||||
            "version": "3.0.1",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/greenlock-manager-fs/-/greenlock-manager-fs-3.0.1.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-vZfGFq1TTKxaAqdGDUwNservrNzXx0xCwT/ovG/N378GrhS+U5S8B8LUlNtQU7Fdw6RToMiBcm22OOxSrvZ2zw==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/mkdirp": "^1.0.0",
 | 
					 | 
				
			||||||
                "safe-replace": "^1.1.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "greenlock-store-fs": {
 | 
					 | 
				
			||||||
            "version": "3.2.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/greenlock-store-fs/-/greenlock-store-fs-3.2.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-zqcPnF+173oYq5qU7FoGtuqeG8dmmvAiSnz98kEHAHyvgRF9pE1T0MM0AuqDdj45I3kXlCj2gZBwutnRi37J3g==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "@root/mkdirp": "^1.0.0",
 | 
					 | 
				
			||||||
                "safe-replace": "^1.1.0"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "redirect-https": {
 | 
					 | 
				
			||||||
            "version": "1.3.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/redirect-https/-/redirect-https-1.3.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-9GzwI/+Cqw3jlSg0CW6TgBQbhiVhkHSDvW8wjgRQ9IK34wtxS71YJiQeazSCSEqbvowHCJuQZgmQFl1xUHKEgg==",
 | 
					 | 
				
			||||||
            "requires": {
 | 
					 | 
				
			||||||
                "escape-html": "^1.0.3"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "safe-replace": {
 | 
					 | 
				
			||||||
            "version": "1.1.0",
 | 
					 | 
				
			||||||
            "resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz",
 | 
					 | 
				
			||||||
            "integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw=="
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										81
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								package.json
									
									
									
									
									
								
							@ -1,40 +1,45 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "name": "greenlock-cluster",
 | 
					  "name": "greenlock-cluster",
 | 
				
			||||||
    "version": "3.0.0",
 | 
					  "version": "2.0.1",
 | 
				
			||||||
    "description": "Use automatic letsencrypt (free ssl certs) on multiple cores or even multiple machines",
 | 
					  "description": "Use automatic letsencrypt (free ssl certs) on multiple cores or even multiple machines",
 | 
				
			||||||
    "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
    "directories": {
 | 
					  "directories": {
 | 
				
			||||||
        "example": "examples"
 | 
					    "example": "examples"
 | 
				
			||||||
    },
 | 
					  },
 | 
				
			||||||
    "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
        "@root/greenlock-express": "^3.0.13"
 | 
					    "le-sni-auto": "^2.0.1",
 | 
				
			||||||
    },
 | 
					    "greenlock": "^2.0.4",
 | 
				
			||||||
    "devDependencies": {},
 | 
					    "localhost.daplie.com-certificates": "^1.2.3",
 | 
				
			||||||
    "scripts": {},
 | 
					    "redirect-https": "^1.1.0"
 | 
				
			||||||
    "repository": {
 | 
					  },
 | 
				
			||||||
        "type": "git",
 | 
					  "devDependencies": {},
 | 
				
			||||||
        "url": "https://git.coolaj86.com/coolaj86/greenlock-cluster.js.git"
 | 
					  "scripts": {
 | 
				
			||||||
    },
 | 
					    "test": "node examples/serve.js"
 | 
				
			||||||
    "keywords": [
 | 
					  },
 | 
				
			||||||
        "cluster",
 | 
					  "repository": {
 | 
				
			||||||
        "acme",
 | 
					    "type": "git",
 | 
				
			||||||
        "le",
 | 
					    "url": "git+https://git.daplie.com/Daplie/greenlock-cluster.git"
 | 
				
			||||||
        "multi-core",
 | 
					  },
 | 
				
			||||||
        "cloud",
 | 
					  "keywords": [
 | 
				
			||||||
        "scale",
 | 
					    "cluster",
 | 
				
			||||||
        "free",
 | 
					    "acme",
 | 
				
			||||||
        "ssl",
 | 
					    "le",
 | 
				
			||||||
        "https",
 | 
					    "multi-core",
 | 
				
			||||||
        "tls",
 | 
					    "cloud",
 | 
				
			||||||
        "letsencrypt",
 | 
					    "scale",
 | 
				
			||||||
        "node",
 | 
					    "free",
 | 
				
			||||||
        "greenlock",
 | 
					    "ssl",
 | 
				
			||||||
        "node.js"
 | 
					    "https",
 | 
				
			||||||
    ],
 | 
					    "tls",
 | 
				
			||||||
    "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
 | 
					    "letsencrypt",
 | 
				
			||||||
    "license": "MPL-2.0",
 | 
					    "node",
 | 
				
			||||||
    "bugs": {
 | 
					    "greenlock",
 | 
				
			||||||
        "url": "https://git.coolaj86.com/coolaj86/greenlock-cluster.js/issues"
 | 
					    "node.js"
 | 
				
			||||||
    },
 | 
					  ],
 | 
				
			||||||
    "homepage": "https://git.coolaj86.com/coolaj86/greenlock-cluster.js"
 | 
					  "author": "AJ ONeal <coolaj86@gmail.com> (https://coolaj86.com/)",
 | 
				
			||||||
 | 
					  "license": "(MIT OR Apache-2.0)",
 | 
				
			||||||
 | 
					  "bugs": {
 | 
				
			||||||
 | 
					    "url": "https://git.daplie.com/Daplie/greenlock-cluster/issues"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "homepage": "https://git.daplie.com/Daplie/greenlock-cluster#readme"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										129
									
								
								worker.js
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								worker.js
									
									
									
									
									
								
							@ -1,78 +1,87 @@
 | 
				
			|||||||
"use strict";
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function log(debug) {
 | 
					function log(debug) {
 | 
				
			||||||
    if (!debug) {
 | 
						if (!debug) {
 | 
				
			||||||
        return;
 | 
							return;
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var args = Array.prototype.slice.call(arguments);
 | 
						var args = Array.prototype.slice.call(arguments);
 | 
				
			||||||
    args.shift();
 | 
						args.shift();
 | 
				
			||||||
    args.unshift("[le/lib/core.js]");
 | 
						args.unshift("[le/lib/core.js]");
 | 
				
			||||||
    console.log.apply(console, args);
 | 
						console.log.apply(console, args);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports.create = function(opts) {
 | 
					
 | 
				
			||||||
    // if another worker updates the certs,
 | 
					
 | 
				
			||||||
    // receive a copy from master here as well
 | 
					module.exports.create = function (opts) {
 | 
				
			||||||
    // and update the sni cache manually
 | 
					
 | 
				
			||||||
    process.on("message", function(msg) {
 | 
					  // if another worker updates the certs,
 | 
				
			||||||
        if ("LE_RESPONSE" === msg.type && msg.certs) {
 | 
					  // receive a copy from master here as well
 | 
				
			||||||
            opts.sni.cacheCerts(msg.certs);
 | 
					  // and update the sni cache manually
 | 
				
			||||||
 | 
					  process.on('message', function (msg) {
 | 
				
			||||||
 | 
					    if ('LE_RESPONSE' === msg.type && msg.certs) {
 | 
				
			||||||
 | 
					      opts.sni.cacheCerts(msg.certs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  opts.sni = require('le-sni-auto').create({
 | 
				
			||||||
 | 
					    renewWithin: opts.renewWithin || (10 * 24 * 60 * 60 * 1000)
 | 
				
			||||||
 | 
					  , renewBy: opts.renewBy || (5 * 24 * 60 * 60 * 1000)
 | 
				
			||||||
 | 
					  , getCertificates: function (domain, certs, cb) {
 | 
				
			||||||
 | 
					      var workerOptions = { domains: [ domain ] };
 | 
				
			||||||
 | 
					      opts.approveDomains(workerOptions, certs, function (_err, results) {
 | 
				
			||||||
 | 
					        if (_err) {
 | 
				
			||||||
 | 
					          cb(_err);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    opts.sni = require("le-sni-auto").create({
 | 
					        var err = new Error("___MESSAGE___");
 | 
				
			||||||
        renewWithin: opts.renewWithin || 10 * 24 * 60 * 60 * 1000,
 | 
					        process.send({ type: 'LE_REQUEST', domain: domain, options: results.options, certs: results.certs });
 | 
				
			||||||
        renewBy: opts.renewBy || 5 * 24 * 60 * 60 * 1000,
 | 
					 | 
				
			||||||
        getCertificates: function(domain, certs, cb) {
 | 
					 | 
				
			||||||
            var workerOptions = { domains: [domain] };
 | 
					 | 
				
			||||||
            opts.approveDomains(workerOptions, certs, function(_err, results) {
 | 
					 | 
				
			||||||
                if (_err) {
 | 
					 | 
				
			||||||
                    cb(_err);
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                process.send({ type: "LE_REQUEST", domain: domain, options: results.options, certs: results.certs });
 | 
					        process.on('message', function (msg) {
 | 
				
			||||||
 | 
					          log(opts.debug, 'Message from master');
 | 
				
			||||||
 | 
					          log(opts.debug, msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                process.on("message", function(msg) {
 | 
					          if (msg.domain !== domain) {
 | 
				
			||||||
                    var err = new Error("___MESSAGE___");
 | 
					            return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    log(opts.debug, "Message from master");
 | 
					          if (msg.error) {
 | 
				
			||||||
                    log(opts.debug, msg);
 | 
					            err.message = msg.error.message || "unknown error sent from cluster master to worker";
 | 
				
			||||||
 | 
					            err.stack.replace("___MESSAGE___", err.message);
 | 
				
			||||||
 | 
					            err = {
 | 
				
			||||||
 | 
					              message: err.message
 | 
				
			||||||
 | 
					            , stack: err.stack
 | 
				
			||||||
 | 
					            , data: { options: workerOptions, certs: certs }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            err = null;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (msg.domain !== domain) {
 | 
					          cb(err, msg.certs);
 | 
				
			||||||
                        return;
 | 
					        });
 | 
				
			||||||
                    }
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (msg.error) {
 | 
					 | 
				
			||||||
                        err.message = msg.error.message || "unknown error sent from cluster master to worker";
 | 
					 | 
				
			||||||
                        err.stack.replace("___MESSAGE___", err.message);
 | 
					 | 
				
			||||||
                        err = {
 | 
					 | 
				
			||||||
                            message: err.message,
 | 
					 | 
				
			||||||
                            stack: err.stack,
 | 
					 | 
				
			||||||
                            data: { options: workerOptions, certs: certs }
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        err = null;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    cb(err, msg.certs);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    opts.httpsOptions = { SNICallback: opts.sni.sniCallback };
 | 
					  opts.httpsOptions = require('localhost.daplie.com-certificates').merge({ SNICallback: opts.sni.sniCallback });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    opts.challenge = {
 | 
					 | 
				
			||||||
        get:
 | 
					 | 
				
			||||||
            opts.getChallenge ||
 | 
					 | 
				
			||||||
            (opts.challenge && opts.challenge.get) ||
 | 
					 | 
				
			||||||
            require("le-challenge-fs").create({ webrootPath: opts.webrootPath }).get
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // opts.challenge.get, opts.acmeChallengePrefix
 | 
					 | 
				
			||||||
    opts.middleware = require("greenlock/lib/middleware").create(opts);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return opts;
 | 
					  opts.challenge = {
 | 
				
			||||||
 | 
					    get: opts.getChallenge
 | 
				
			||||||
 | 
					      || (opts.challenge && opts.challenge.get)
 | 
				
			||||||
 | 
					      || require('le-challenge-fs').create({ webrootPath: opts.webrootPath }).get
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // opts.challenge.get, opts.acmeChallengePrefix
 | 
				
			||||||
 | 
					  opts.middleware = require('greenlock/lib/middleware').create(opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return opts;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user