2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# Migrating from Greenlock v2 to v3
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								**Greenlock Express** uses Greenlock directly, the same as before.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								All options described for `Greenlock.create({...})`  also apply to the Greenlock Express `init()`  callback.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Overview of Major Differences
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-    Reduced API 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    No code in the config 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    (config is completely serializable)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    Manager callbacks replace `approveDomains`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    Greenlock Express does more, with less config 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    cluster is supported out-of-the-box
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    high-performance
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    scalable
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    ACME challenges are simplified 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    init
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    zones (dns-01)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    set
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    get
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    remove
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    Store callbacks are simplified 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    accounts
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        -    checkKeypairs
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    certificates
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        -    checkKeypairs
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        -    check
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        -    set
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Greenlock JavaScript API greatly reduced
  
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Whereas before there were many different methods with nuance differences,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								now there's just `create` , `get` , `renew` , and sometimes `add`  ().
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-    Greenlock.create({ maintainerEmail, packageAgent, notify }) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    Greenlock.get({ servername, wildname, duplicate, force }) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    (just a convenience wrapper around renew)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    Greenlock.renew({ subject, altnames, issuedBefore, expiresAfter }) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    (retrieves, issues, renews, all-in-one)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    _optional_  Greenlock.add({ subject, altnames, subscriberEmail }) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    (partially replaces `approveDomains` )
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Also, some disambiguation on terms:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `domains`  was often ambiguous and confusing, it has been replaced by: 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    `subject`  refers to the subject of a certificate - the primary domain
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    `altnames`  refers to the domains in the SAN (Subject Alternative Names) section of the certificate
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    `servername`  refers to the TLS (SSL) SNI (Server Name Indication) request for a cetificate
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    -    `wildname`  refers to the wildcard version of the servername (ex: `www.example.com => *.example.com` )
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								When you create an instance of Greenlock, you only supply package and maintainer info.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								All other configuration is A) optional and B) handled by the _Manager_ .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								'use strict';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var pkg = require('./package.json');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var Greenlock = require('greenlock');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var greenlock = Greenlock.create({
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // used for the ACME client User-Agent string as per RFC 8555 and RFC 7231
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    packageAgent: pkg.name + '/' + pkg.version,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // used as the contact for critical bug and security notices
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // should be the same as pkg.author.email
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    maintainerEmail: 'jon@example .com',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // used for logging background events and errors
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    notify: function(ev, args) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if ('error' === ev || 'warning' === ev) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            console.error(ev, args);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        console.info(ev, args);
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								});
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								By default **no certificates will be issued** . See the _manager_  section.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								When you want to get a single certificate, you use `get` , which will:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    will return null if neither the `servername`  or its `wildname`  (wildcard) variant can be found 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    retrieve a non-expired certificate, if possible 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    will renew the certificate in the background, if stale 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    will wait for the certificate to be issued if new 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								greenlock
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    .get({ servername: 'www.example.com' })
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    .then(function(result) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!result) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // certificate is not on the approved list
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var fullchain = result.pems.cert + '\n' + result.pems.chain + '\n';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var privkey = result.pems.privkey;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            fullchain: fullchain,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            privkey: privkey
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    })
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    .catch(function(e) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // something went wrong in the renew process
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        console.error(e);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    });
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								By default **no certificates will be issued** . See the _manager_  section.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								When you want to renew certificates, _en masse_ , you use `renew` , which will:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    check all certificates matching the given criteria 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    only renew stale certificates by default 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    return error objects (will NOT throw exception for failed renewals) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								greenlock
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    .renew({})
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    .then(function(results) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!result.length) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // no certificates found
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return null;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // [{ site, error }]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return results;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    })
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    .catch(function(e) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // an unexpected error, not related to renewal
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        console.error(e);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    });
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Options:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| Option        | Description                                                                |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| ------------- | -------------------------------------------------------------------------- |
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:40:59 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								| `altnames`     | only check and renew certs matching these altnames (including wildcards)   |
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								| `renewBefore`  | only check and renew certs marked for renewal before the given date, in ms |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `duplicate`    | renew certificates regardless of timing                                    |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								| `force`        | allow silly things, like tiny `renewOffset` s                               |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								By default **no certificates will be issued** . See the _manager_  section.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Greenlock Express Example
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The options that must be returned from `init()`  are the same that are used in `Greenlock.create()` ,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								with a few extra that are specific to Greenlock Express:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								require('@root/greenlock -express')
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    .init(function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // This object will be passed to Greenlock.create()
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var options = {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // some options, like cluster, are special to Greenlock Express
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            cluster: false,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // The rest are the same as for Greenlock
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            packageAgent: pkg.name + '/' + pkg.version,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            maintainerEmail: 'jon@example .com',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            notify: function(ev, args) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                console.info(ev, args);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return options;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    })
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    .serve(function(glx) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // will start servers on port 80 and 443
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        glx.serveApp(function(req, res) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            res.end('Hello, Encrypted World!');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        });
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // you can get access to the raw server (i.e. for websockets)
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        glx.httpsServer(); // returns raw server object
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    });
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# _Manager_ replaces `approveDomains`
  
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`approveDomains`  was always a little confusing. Most people didn't need it. 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Instead, now there is a simple config file that will work for most people,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								as well as a set of callbacks for easy configurability.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								### Default Manager
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The default manager is `greenlock-manager-fs`  and the default `configFile`  is `~/.config/greenlock/manager.json` .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The config file should look something like this:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`~/.config/greenlock/manager.json` : 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```json
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    "subscriberEmail": "jon@example .com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "agreeToTerms": true,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "sites": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "example.com": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "subject": "example.com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "altnames": ["example.com", "www.example.com"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								You can specify a `acme-dns-01-*`  or `acme-http-01-*`  challenge plugin globally, or per-site.
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```json
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    "subscriberEmail": "jon@example .com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "agreeToTerms": true,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "sites": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "example.com": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "subject": "example.com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "altnames": ["example.com", "www.example.com"],
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "challenges": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                "dns-01": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "module": "acme-dns-01-digitalocean",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "token": "apikey-xxxxx"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								The same is true with `greenlock-store-*`  plugins:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								```json
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    "subscriberEmail": "jon@example .com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "agreeToTerms": true,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "sites": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "example.com": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "subject": "example.com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "altnames": ["example.com", "www.example.com"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    },
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "store": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "module": "greenlock-store-fs",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "basePath": "~/.config/greenlock"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								### Customer Manager, the lazy way
  
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								At the very least you have to implement `find({ servername })` .
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Since this is a very common use case, it's supported out of the box as part of the default manager plugin:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var greenlock = Greenlock.create({
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    packageAgent: pkg.name + '/' + pkg.version,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    maintainerEmail: 'jon@example .com',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    notify: notify,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find: find
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								});
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// In the simplest case you can ignore all incoming options
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// and return a single site config in the same format as the config file
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function find(options) {
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    var servername = options.servername; // www.example.com
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var wildname = options.wildname; // *.example.com
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return Promise.resolve([
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        { subject: 'example.com', altnames: ['example.com', 'www.example.com'] }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ]);
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function notify(ev, args) {
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if ('error' === ev || 'warning' === ev) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        console.error(ev, args);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    console.info(ev, args);
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								If you want to use wildcards or local domains, you must specify the `dns-01`  challenge plugin to use:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								function find(options) {
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    var subject = options.subject;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // may include wildcard
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var altnames = options.altnames;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var wildname = options.wildname; // *.example.com
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return Promise.resolve([
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            subject: 'example.com',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            altnames: ['example.com', 'www.example.com'],
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            challenges: {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                'dns-01': { module: 'acme-dns-01-namedotcom', apikey: 'xxxx' }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ]);
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								### Customer Manager, complete
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								To use a fully custom manager, you give the npm package name, or absolute path to the file to load
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Greenlock.create({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Greenlock Options
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    maintainerEmail: 'jon@example .com',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    packageAgent: 'my-package/v2.1.1',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    notify: notify,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // file path or npm package name
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    manager: '/path/to/manager.js',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // options that get passed to the manager
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    myFooOption: 'whatever'
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								});
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The manager itself is, again relatively simple:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    find(options) 
						 
					
						
							
								
									
										
										
										
											2019-10-31 16:25:43 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-    set(siteConfig) 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								-    remove(options) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    defaults(globalOptions) (as setter) 
						 
					
						
							
								
									
										
										
										
											2019-10-31 16:25:43 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    -    defaults() => globalOptions (as getter)
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`/path/to/manager.js` : 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								'use strict';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								module.exports.create = function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var manager = {};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    manager.find = async function({ subject, altnames, renewBefore }) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (subject) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return getSiteConfigBySubject(subject);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (altnames) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            // may include wildcards
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return getSiteConfigByAnyAltname(altnames);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (renewBefore) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return getSiteConfigsWhereRenewAtIsLessThan(renewBefore);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return [];
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-31 16:25:43 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    manage.set = function(opts) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // this is called by greenlock.add({ subject, altnames })
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // it's also called by greenlock._update({ subject, renewAt })
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-31 16:25:43 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return mergSiteConfig(subject, opts);
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    manage.remove = function({ subject, altname }) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (subject) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return removeSiteConfig(subject);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return removeFromSiteConfigAndResetRenewAtToZero(altname);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // set the global config
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    manage.defaults = function(options) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if (!options) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return getGlobalConfig();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return mergeGlobalConfig(options);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ACME Challenge Plugins
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The ACME challenge plugins are just a few simple callbacks:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `init`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `zones`  (dns-01 only) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `set`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `get`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `remove`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								They are described here:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    [dns-01 documentation ](https://git.rootprojects.org/root/acme-dns-01-test.js ) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    [http-01 documentation ](https://git.rootprojects.org/root/acme-http-01-test.js ) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# Key and Cert Store Plugins
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Again, these are just a few simple callbacks:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `certificates.checkKeypair`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `certificates.check`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `certificates.setKeypair`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `certificates.set`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `accounts.checkKeypair`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `accounts.check`  (optional) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `accounts.setKeypair`  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    `accounts.set`  (optional) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								The name `check`  is used instead of `get`  because they only need to return something if it exists. They do not need to fail, nor do they need to generate anything.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								They are described here:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								-    [greenlock store documentation ](https://git.rootprojects.org/root/greenlock-store-test.js ) 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								If you are just implenting in-house and are not going to publish a module, you can also do some hack things like this:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								### Custome Store, The hacky / lazy way
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								`/path/to/project/my-hacky-store.js` : 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```js
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								'use strict';
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								module.exports.create = function(options) {
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // ex: /path/to/account.ecdsa.jwk.json
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var accountJwk = require(options.accountJwkPath);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ex: /path/to/privkey.rsa.pem
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var serverPem = fs.readFileSync(options.serverPemPath, 'ascii');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var accounts = {};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var certificates = {};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    var store = { accounts, certificates };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // bare essential account callbacks
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    accounts.checkKeypair = function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ignore all options and just return a single, global keypair
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return Promise.resolve({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            privateKeyJwk: accountJwk
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        });
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    accounts.setKeypair = function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // this will never get called if checkKeypair always returns
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return Promise.resolve({});
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // bare essential cert and key callbacks
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    certificates.checkKeypair = function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // ignore all options and just return a global server keypair
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            privateKeyPem: serverPem
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    certificates.setKeypair = function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // never gets called if checkKeypair always returns an existing key
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return Promise.resolve(null);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    certificates.check = function(args) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var subject = args.subject;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // make a database call or whatever to get a certificate
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return goGetCertBySubject(subject).then(function() {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pems: {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    chain: '< PEM > ',
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    cert: '< PEM > '
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        });
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    certificates.set = function(args) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var subject = args.subject;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var cert = args.pems.cert;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        var chain = args.pems.chain;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // make a database call or whatever to get a certificate
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return goSaveCert({
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            subject,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            cert,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            chain
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        });
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    };
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								### Using the hacky / lazy store plugin
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								That sort of implementation won't pass the test suite, but it'll work just fine a use case where you only have one subscriber email (most of the time),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								you only have one server key (not recommended, but works), and you only really want to worry about storing cetificates.
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								Then you could assign it as the default for all of your sites:
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```json
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 04:05:54 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    "subscriberEmail": "jon@example .com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "agreeToTerms": true,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "sites": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "example.com": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "subject": "example.com",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            "altnames": ["example.com", "www.example.com"]
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    },
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    "store": {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "module": "/path/to/project/my-hacky-store.js",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "accountJwkPath": "/path/to/account.ecdsa.jwk.json",
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        "serverPemPath": "/path/to/privkey.rsa.pem"
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }
							 
						 
					
						
							
								
									
										
										
										
											2019-10-29 03:20:10 -06:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								```