![require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages](https://cdn.sanity.io/images/cgdhsj6q/production/be8ab80c8efa5907bc341c6fefe9aa20d239d890-1600x1097.png?w=400&fit=max&auto=format)
Security News
require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
greenlock-cluster
Advanced tools
Use automatic letsencrypt (free ssl certs) on multiple cores or even multiple machines
See https://git.rootprojects.org/root/greenlock-express.js
"use strict";
var pkg = require("./package.json");
require("greenlock-express")
.init(function getConfig() {
// Greenlock Config
return {
package: { name: pkg.name, version: pkg.version },
maintainerEmail: pkg.author,
// put cluster on full throttle!
cloudnative: true
webscale: true
cluster: true
};
})
.serve(httpsWorker);
function httpsWorker(glx) {
// Serves on 80 and 443
// Get's SSL certificates magically!
glx.serveApp(function(req, res) {
res.end("Hello, Encrypted World!");
});
}
| A Root Project | greenlock (lib) | greenlock-cli | greenlock-express | greenlock-cluster | greenlock-koa | greenlock-hapi |
(previously letsencrypt-cluster)
Use automatic letsencrypt with node on multiple cores or even multiple machines.
npm install --save greenlock-cluster@2.x
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"), // /tmp/acme-challenge
// used by le-challenge-fs, the default plugin
renewWithin: 14 * 24 * 60 * 60 * 1000, // 10 days before expiration
debug: true
};
if (cluster.isMaster) {
main = require("./master");
} else {
main = require("./worker");
}
main.init(sharedOptions);
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
// You MUST change this to 'https://acme-v02.api.letsencrypt.org/directory' in production
server: 'https://acme-staging-v02.api.letsencrypt.org/directory'
, version: 'draft-11' // Let's Encrypt v2
, renewWithin: sharedOpts.renewWithin
, webrootPath: sharedOpts.webrootPath
, approveDomains: function (masterOptions, certs, cb) {
// Do any work that must be done by master to approve this domain
// (in this example, it's assumed to be done by the worker)
var results = { domain: masterOptions.domain // required
, options: masterOptions // domains, email, agreeTos
, certs: certs }; // altnames, privkey, cert
cb(null, results);
}
});
cores.forEach(function () {
var worker = cluster.fork();
leMaster.addWorker(worker);
});
};
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.
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,
// , challenge: require('le-challenge-fs').create({ webrootPath: '...', ... })
approveDomains: function(workerOptions, certs, cb) {
// opts = { domains, email, agreeTos, tosUrl }
// certs = { subject, altnames, expiresAt, issuedAt }
var results = {
domain: workerOptions.domains[0],
options: {
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);
}
});
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);
};
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.
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.
FAQs
Use automatic letsencrypt (free ssl certs) on multiple cores or even multiple machines
The npm package greenlock-cluster receives a total of 2 weekly downloads. As such, greenlock-cluster popularity was classified as not popular.
We found that greenlock-cluster demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.