Replaced: Use Greenlock Express v3
See https://git.rootprojects.org/root/greenlock-express.js
"use strict";
var pkg = require("./package.json");
require("greenlock-express")
.init(function getConfig() {
return {
package: { name: pkg.name, version: pkg.version },
maintainerEmail: pkg.author,
cloudnative: true
webscale: true
cluster: true
};
})
.serve(httpsWorker);
function httpsWorker(glx) {
glx.serveApp(function(req, res) {
res.end("Hello, Encrypted World!");
});
}
OLD STUFF BELOW
(Preserved for historical reference)
| A Root Project
| greenlock (lib)
| greenlock-cli
| greenlock-express
| greenlock-cluster
| greenlock-koa
| greenlock-hapi
|
greenlock-cluster
(previously letsencrypt-cluster)
Use automatic letsencrypt with node on multiple cores or even multiple machines.
- Take advantage of multi-core computing
- Process certificates in master
- Serve https from multiple workers
- Can work with any clustering strategy #1
Install
npm install --save greenlock-cluster@2.x
Usage
In a cluster environment you have some main file that boots your app
and then conditionally loads certain code based on whether that fork
is the master or just a worker.
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:
boot.js
:
"use strict";
var cluster = require("cluster");
var path = require("path");
var os = require("os");
var main;
var sharedOptions = {
webrootPath: path.join(os.tmpdir(), "acme-challenge"),
renewWithin: 14 * 24 * 60 * 60 * 1000,
debug: true
};
if (cluster.isMaster) {
main = require("./master");
} else {
main = require("./worker");
}
main.init(sharedOptions);
Master
We think it makes the most sense to load greenlock in master.
This can prevent race conditions (see node-letsencrypt#45)
as only one process is writing the to file system or database at a time.
The main implementation detail here is approveDomains(options, certs, cb)
for new domain certificates
and potentially agreeToTerms(opts, cb)
for new accounts.
The master takes the same arguments as node-greenlock
(challenge
, store
, etc),
plus a few extra (approveDomains
... okay, just one extra):
master.js
:
'use strict';
var cluster = require('cluster');
module.exports.init = function (sharedOpts) {
var cores = require('os').cpus();
var leMaster = require('greenlock-cluster/master').create({
debug: sharedOpts.debug
server: 'https://acme-staging-v02.api.letsencrypt.org/directory'
, version: 'draft-11'
, renewWithin: sharedOpts.renewWithin
, webrootPath: sharedOpts.webrootPath
, approveDomains: function (masterOptions, certs, cb) {
var results = { domain: masterOptions.domain
, options: masterOptions
, certs: certs };
cb(null, results);
}
});
cores.forEach(function () {
var worker = cluster.fork();
leMaster.addWorker(worker);
});
};
API
All options are passed directly to node-greenlock
(in other works, leMaster
is a greenlock
instance),
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).
-
leMaster.addWorker(worker)
is added by greenlock-cluster
and must be called for each new worker.
Worker
The worker takes similar arguments to node-greenlock
,
but only ones that are useful for determining certificate
renewal and for le.challenge.get
.
If you want to a non-default le.challenge
worker.js
:
"use strict";
module.exports.init = function(sharedOpts) {
var leWorker = require("greenlock-cluster/worker").create({
debug: sharedOpts.debug,
renewWithin: sharedOpts.renewWithin,
webrootPath: sharedOpts.webrootPath,
approveDomains: function(workerOptions, certs, cb) {
var results = {
domain: workerOptions.domains[0],
options: {
domains: workerOptions.domains
},
certs: certs
};
if (certs) {
results.options.domains = certs.altnames;
cb(null, results);
return;
}
results.options.email = "john.doe@example.com";
results.options.agreeTos = true;
cb(null, results);
}
});
function app(req, res) {
res.end("Hello, World!");
}
var redirectHttps = require("redirect-https")();
var plainServer = require("http").createServer(leWorker.middleware(redirectHttps));
plainServer.listen(80);
var server = require("https").createServer(leWorker.httpsOptions, leWorker.middleware(app));
server.listen(443);
};
API
node-greenlock
is not used directly by the worker,
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 certleOptions.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.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
that isn't shown here, look at the code (it's not that much) or open an issue.
Message Passing
The master and workers will communicate through process.on('message', fn)
, process.send({})
,
worker.on('message', fn)
and worker.send({})
.
All messages have a type
property which is a string and begins with LE_
.
All other messages are ignored.