Greenlock v3 on its way (Nov 1st, 2019)
Greenlock v3 is in private beta (for backers) and will be available publicly by Nov 1st.
You can keep an eye for updates on the campaign page and,
if this has been a useful project that's saved you time, please contribute.


Greenlock provides Free SSL, Free Wildcard SSL, and Fully Automated HTTPS
certificates issued by Let's Encrypt v2 via ACME

Greenlock works
in the Commandline (cli),
as a Web Server,
in Web Browsers (WebCrypto),
and with node.js (npm).
Features
Greenlock.js for Middleware
Documentation for using Greenlock with
http/https,
Express.js,
hapi,
Koa,
rill.
Table of Contents
- Install
- QuickStart
- Simple Examples
- Example with ALL OPTIONS
- API
- Developer API
- Change History
- License
Install
npm install --save greenlock@2.x
Optional for more efficient RSA key generation you must use node v10.12+
(important for those on ARM devices like Raspberry Pi)
Production vs Staging
If at first you don't succeed, stop and switch to staging.
I've implemented a "dry run" loopback test with self diagnostics
so it's pretty safe to start off with the production URLs
and be far less likely to hit the bad request rate limits.
However, if your first attempt to get a certificate fails
I'd recommend switching to the staging acme server to debug -
unless you're very clear on what the failure was and how to fix it.
{ server: 'https://acme-staging-v02.api.letsencrypt.org/directory' }
QuickStart Screencast
Watch the QuickStart demonstration: https://youtu.be/e8vaR4CEZ5s

- 0:00 - Intro
- 2:22 - Demonstrating QuickStart Example
- 6:37 - Troubleshooting / Gotchas
Production Configuration (Part 2)
- 1:00 - Bringing Greenlock into an Existing Express Project
- 2:26 - The
approveDomains
callback
Security Concerns (Part 3)
- 0:00 - Potential Attacks, and Mitigation
Easy as 1, 2, 3... 4
Greenlock is built to incredibly easy to use, without sacrificing customization or extensibility.
The following examples range from just a few lines of code for getting started,
to more robust examples that you might start with for an enterprise-grade use of the ACME api.
- Automatic HTTPS (for single sites)
- Fully Automatic HTTPS (for multi-domain vhosts)
- Manual HTTPS (for API integration)
Automatic HTTPS
Note: For (fully) automatic HTTPS you may prefer
the Express.js module
This works for most people, but it's not as fun as some of the other examples.
Great when
var greenlock = require('greenlock').create({
email: 'user@example.com',
agreeTos: true,
configDir: '~/.config/acme',
communityMember: true,
securityUpdates: true
});
var redir = require('redirect-https')();
require('http')
.createServer(greenlock.middleware(redir))
.listen(80);
require('spdy')
.createServer(greenlock.tlsOptions, function(req, res) {
res.end('Hello, Secure World!');
})
.listen(443);
Fully Automatic HTTPS
Note: For (fully) automatic HTTPS you may prefer
the Express.js module
Great when
var path = require('path');
var os = require('os');
var Greenlock = require('greenlock');
var greenlock = Greenlock.create({
version: 'draft-12',
server: 'https://acme-v02.api.letsencrypt.org/directory',
approveDomains: approveDomains,
servername: 'example.com',
store: require('le-store-fs').create({
configDir: path.join(os.homedir(), 'acme/etc'),
webrootPath: '/tmp/acme-challenges'
})
});
var http01 = require('le-challenge-fs').create({
webrootPath: '/tmp/acme-challenges'
});
function approveDomains(opts, certs, cb) {
opts.communityMember = true;
opts.challenges = { 'http-01': http01 };
opts.email = 'john.doe@example.com';
opts.agreeTos = true;
cb(null, { options: opts, certs: certs });
}
var redir = require('redirect-https')();
require('http')
.createServer(greenlock.middleware(redir))
.listen(80);
require('https')
.createServer(greenlock.tlsOptions, function(req, res) {
res.end('Hello, Secure World!');
})
.listen(443);
Manual HTTPS
Here's a taste of the API that you might use if building a commandline tool or API integration
that doesn't use node's SNICallback.
/////////////////////
// SET USER PARAMS //
/////////////////////
var opts = {
domains: [ 'example.com' // CHANGE EMAIL AND DOMAINS
, 'www.example.com' ]
, email: 'user@example.com'
, agreeTos: true // Accept Let's Encrypt v2 Agreement
, communityMember: true // Help make Greenlock better by submitting
// stats and getting updates
};
////////////////////
// INIT GREENLOCK //
////////////////////
var greenlock = require('greenlock').create({
version: 'draft-12'
, server: 'https://acme-v02.api.letsencrypt.org/directory'
, configDir: '/tmp/acme/etc'
});
///////////////////
// GET TLS CERTS //
///////////////////
greenlock.register(opts).then(function (certs) {
console.log(certs);
// privkey, cert, chain, expiresAt, issuedAt, subject, altnames
}, function (err) {
console.error(err);
});
The domain key and ssl certificates you get back can be used in a webserver like this:
var tlsOptions = {
key: certs.privkey,
cert: certs.cert + '\r\n' + certs.chain
};
require('https')
.createServer(tlsOptions, function(req, res) {
res.end('Hello, Secure World!');
})
.listen(443);
Example with ALL OPTIONS
The configuration consists of 3 components:
- Storage Backend (search npm for projects starting with 'le-store-')
- ACME Challenge Handlers (search npm for projects starting with 'le-challenge-')
- Letsencryt Config (this is all you)
'use strict';
var Greenlock = require('greenlock');
var greenlock;
var leStore = require('greenlock-store-fs').create({
configDir: '~/acme/etc'
, debug: false
});
var leHttpChallenge = require('le-challenge-fs').create({
webrootPath: '~/acme/var/'
, debug: false
});
function leAgree(opts, agreeCb) {
agreeCb(null, opts.tosUrl);
}
greenlock = Greenlock.create({
version: 'draft-12'
server: 'https://acme-v02.api.letsencrypt.org/directory'
, store: leStore
, challenges: {
'http-01': leHttpChallenge
}
, challengeType: 'http-01'
, agreeToTerms: leAgree
, renewWithin: 14 * 24 * 60 * 60 * 1000
, renewBy: 10 * 24 * 60 * 60 * 1000
, debug: false
});
greenlock.check({ domains: [ 'example.com' ] }).then(function (results) {
if (results) {
return;
}
greenlock.register({
domains: ['example.com']
, email: 'user@email.com'
, agreeTos: ''
, rsaKeySize: 2048
, challengeType: 'http-01'
}).then(function (results) {
console.log('success');
}, function (err) {
console.error('[Error]: node-greenlock/examples/standalone');
console.error(err.stack);
});
});
Here's what results
looks like:
{ privkey: ''
, cert: ''
, chain: ''
, issuedAt: 0
, expiresAt: 0
, subject: ''
, altnames: []
}
API
The full end-user API is exposed in the example above and includes all relevant options.
greenlock.register(opts)
greenlock.check(opts)
Helper Functions
We do expose a few helper functions:
- Greenlock.validDomain(hostname) // returns '' or the hostname string if it's a valid ascii or punycode domain name
TODO fetch domain tld list
Template Strings
The following variables will be tempalted in any strings passed to the options object:
~/
replaced with os.homedir()
i.e. /Users/aj
:hostname
replaced with the first domain in the list i.e. example.com
Dangerous Options
By default SNI is made to lowercase and is automatically rejected if it contains invalid characters for a domain.
This behavior can be modified:
__dns_allow_dangerous_names
allow SNI names like "Robert'); DROP TABLE Students;"
__dns_preserve_case
passes SNI names such as "ExAMpLE.coM" without converting to lower case
Developer API
If you are developing an le-store-*
or le-challenge-*
plugin you need to be aware of
additional internal API expectations.
IMPORTANT:
Use v3.0.0
as your initial version - NOT v0.1.0 and NOT v1.0.0 and NOT v2.0.0.
This is to indicate that your module is compatible with v3 (v2.7+) of node-greenlock.
Since the public API for your module is defined by node-greenlock the major version
should be kept in sync.
store implementation
See greenlock-store-test
and greenlock-store-fs
- accounts.
- checkKeypair(opts)
- check(opts)
- setKeypair(opts)
- set(opts)
- certificates.
- checkKeypair(opts)
- check(opts)
- setKeypair(opts)
- set(opts)
challenge implementation
See greenlock-challenge-test,
acme-http-01-cli,
and acme-dns-01-cli
.set(opts);
.get(opts);
.remove(opts);
Change History
- v2.7
- API: transitional for v3 API (Promies, async/await)
- Security: Zero external dependencies
- Plugins:
greenlock-store-fs
replaces le-store-certbot
as the default storage plugin
- Features: Full wildcard support
- Licensing: Commercial licensing and support plans now available
- v2.6
- better defaults, fewer explicit options
- better pre-flight self-tests, explicit domains not required
- v2.5
- bugfix JWK (update rsa-compat)
- eliminate all external non-optional dependencies
- v2.4
- v2.4.3 - add security updates (default true) independent of community updates (default false)
- v2.2 - Let's Encrypt v2 Support
- v2.2.11 - documentation updates
- v2.2.10 - don't let SNICallback swallow approveDomains errors 6286883fc2a6ebfff711a540a2e4d92f3ac2907c
- v2.2.8 - communityMember option support
- v2.2.7 - bugfix for wildcard support
- v2.2.5 - node v6.x compat
- v2.2.4 - don't promisify all of
dns
- v2.2.3 -
renewWithin
default to 14 days
- v2.2.2 - replace git dependency with npm
- v2.2.1 - April 2018 Let's Encrypt v2 support
- v2.1.17 - Nov 5th 2017 migrate back to personal repo
- v2.1.9 - Jan 18th 2017 renamed to greenlock
- v2.0.2 - Aug 9th 2016 update readme
- v2.0.1 - Aug 9th 2016
- major refactor
- simplified API
- modular plugins
- knock out bugs
- v1.5.0 now using letiny-core v2.0.0 and rsa-compat
- v1.4.x I can't remember... but it's better!
- v1.1.0 Added letiny-core, removed node-letsencrypt-python
- v1.0.2 Works with node-letsencrypt-python
- v1.0.0 Thar be dragons
Commercial Licensing
As the number of businesses using Greenlock commercially has increased, we've become more aware of the need for quick-turnaround support and licenses that allow for local private modifications. Currently we offer LTS support and commercial licensing models for IoT, On-Prem, and Web Hosting. Please contact us to learn more.
Our trademark policy is pretty much "attribute, but don't confuse". Your users should understand that your product uses Greenlock and not be confused to think that it is Greenlock.
Legal & Rules of the Road
Greenlock™ is a trademark of AJ ONeal
The rule of thumb is "attribute, but don't confuse". For example:
Built with Greenlock.js (a Root project).
Please contact us if you have any questions in regards to our trademark,
attribution, and/or visible source policies. We want to build great software and a great community.
Greenlock™ |
MPL-2.0 |
Terms of Use |
Privacy Policy