| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | le-sni-auto | 
					
						
							|  |  |  | =========== | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | | Sponsored by [ppl](https://ppl.family) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | An auto-sni strategy for registering and renewing letsencrypt certificates using SNICallback. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This does a couple of rather simple things: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * caches certificates in memory | 
					
						
							|  |  |  |   * calls `getCertificatesAsync(domain, null)` when a certificate is not in memory | 
					
						
							|  |  |  |   * calls `getCertificatesASync(domain, certs)` when a certificate is up for renewal or expired | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Install | 
					
						
							|  |  |  | ======= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```bash | 
					
						
							|  |  |  | npm install --save le-sni-auto@2.x | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Usage | 
					
						
							|  |  |  | ===== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | With node-letsencrypt | 
					
						
							|  |  |  | --------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var leSni = require('le-sni-auto').create({ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:36:34 -06:00
										 |  |  |   renewWithin: 14 * 24 * 60 * 60 1000     // do not renew more than 14 days before expiration | 
					
						
							|  |  |  | , renewBy: 10 * 24 * 60 * 60 1000         // do not wait more than 10 days before expiration | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | , tlsOptions: { | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  |     rejectUnauthorized: true              // These options will be used with tls.createSecureContext() | 
					
						
							|  |  |  |   , requestCert: false                    // in addition to key (privkey.pem) and cert (cert.pem + chain.pem), | 
					
						
							|  |  |  |   , ca: null                              // which are provided by letsencrypt | 
					
						
							|  |  |  |   , crl: null | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var le = require('letsencrypt').create({ | 
					
						
							|  |  |  |   server: 'staging' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | , sni: leSni | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | , approveDomains: function (domain, cb) { | 
					
						
							|  |  |  |     // here you would lookup details such as email address in your db | 
					
						
							|  |  |  |     cb(null, { email: 'john.doe@gmail.com.', domains: [domain, 'www.' + domain], agreeTos: true }} | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | var redirectHttps = require('redirect-https').create(); | 
					
						
							|  |  |  | http.createServer(le.middleware(redirectHttps)); | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | var app = require('express')(); | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | https.createServer(le.tlsOptions, le.middleware(app)).listen(443); | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You can also provide a thunk-style `getCertificates(domain, certs, cb)`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Standalone | 
					
						
							|  |  |  | ---------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | var leSni = require('le-sni-auto').create({ | 
					
						
							| 
									
										
										
										
											2018-04-19 15:02:28 -06:00
										 |  |  |   renewWithin: 14 * 24 * 60 * 60 1000       // do not renew prior to 10 days before expiration | 
					
						
							|  |  |  | , renewBy: 10 * 24 * 60 * 60 1000         // do not wait more than 5 days before expiration | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // key (privkey.pem) and cert (cert.pem + chain.pem) will be provided by letsencrypt | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | , tlsOptions: { rejectUnauthorized: true, requestCert: false, ca: null, crl: null } | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | , getCertificatesAsync: function (domain, certs) { | 
					
						
							|  |  |  |     // return a promise with an object with the following keys: | 
					
						
							|  |  |  |     // { privkey, cert, chain, expiresAt, issuedAt, subject, altnames } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | // some default certificates that work with localhost | 
					
						
							|  |  |  | // (because default certificates are required as a fallback) | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | var tlsOptions = require('localhost.daplie.me-certificates').merge({ | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  |   SNICallback: leSni.sniCallback | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | https.createServer(tlsOptions, app); | 
					
						
							| 
									
										
										
										
											2016-08-10 20:37:03 -04:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You can also provide a thunk-style `getCertificates(domain, certs, cb)`. | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | API | 
					
						
							|  |  |  | === | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | * create(options) | 
					
						
							|  |  |  |   * `getCertificates(domain, certs, cb)` or `getCertificatesAsync(domain, certs)` | 
					
						
							|  |  |  |   * `renewWithin` (default 7 days, min 3 days) | 
					
						
							|  |  |  |   * `renewBy` (default 2 days, min 12 hours) | 
					
						
							|  |  |  | * `sniCallback(domain, cb)` | 
					
						
							|  |  |  | * `cacheCerts(certs)` | 
					
						
							| 
									
										
										
										
											2016-10-08 15:23:32 +11:00
										 |  |  | * `uncacheDomain(domain)` | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | .renewWithin | 
					
						
							|  |  |  | ----------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Specifies the maximum amount of time (in ms) before | 
					
						
							|  |  |  | the certificate expires to renew it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Say the cert expires in 90 days and you would like | 
					
						
							|  |  |  | to renew, **at earliest** 10 days before it expires. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You would set this to `10 * 24 * 60 * 60 * 1000`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .renewBy | 
					
						
							|  |  |  | -------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Specifies the maximum amount of time (in ms) before | 
					
						
							|  |  |  | the certificate expires to renew it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Say the cert expires in 90 days and you would like | 
					
						
							|  |  |  | to renew, **at latest** 10 days before it expires. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | You would set this to `10 * 24 * 60 * 60 * 1000`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | **MUST** be **less than** `renewWithin`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .sniCallback() | 
					
						
							|  |  |  | ----------- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | This gets passed to `https.createServer(tlsOptions, app)` as `tlsOptions.SNICallback`. | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ```javascript | 
					
						
							|  |  |  | var leSni = require('le-sni-auto').create({ | 
					
						
							| 
									
										
										
										
											2018-04-19 15:02:28 -06:00
										 |  |  |   renewWithin: 14 * 24 * 60 * 60 1000 | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | var tlsOptions = require('localhost.daplie.com-certificates').merge({ | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  |   SNICallback: leSni.sniCallback | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function app(req, res) { | 
					
						
							|  |  |  |   res.end("Hello, World!"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-19 13:18:40 -06:00
										 |  |  | https.createServer(tlsOptions, app); | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .cacheCerts() | 
					
						
							|  |  |  | ----------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Manually load a certificate into the cache. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is useful in a cluster environment where the master | 
					
						
							| 
									
										
										
										
											2016-10-08 15:23:32 +11:00
										 |  |  | may wish to inform multiple workers of a new or renewed certificate, | 
					
						
							|  |  |  | or to satisfy tls-sni-01 challenges. | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | leSni.cacheCerts({ | 
					
						
							|  |  |  | , privkey: '<<privkey.pem>>' | 
					
						
							|  |  |  | , cert: '<<cert.pem + chain.pem>>' | 
					
						
							|  |  |  | , subject: 'example.com' | 
					
						
							|  |  |  | , altnames: [ 'example.com', 'www.example.com' ] | 
					
						
							|  |  |  | , issuedAt: 1470975565000 | 
					
						
							|  |  |  | , expiresAt: 1478751565000 | 
					
						
							| 
									
										
										
										
											2016-10-08 15:23:32 +11:00
										 |  |  | , auto: true | 
					
						
							| 
									
										
										
										
											2016-08-12 01:59:19 -04:00
										 |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2016-10-08 15:23:32 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | .uncacheCerts() | 
					
						
							|  |  |  | ----------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Remove cached certificates from the cache. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is useful once a tls-sni-01 challenge has been satisfied. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | leSni.uncacheCerts({ | 
					
						
							|  |  |  | , subject: 'example.com' | 
					
						
							|  |  |  | , altnames: [ 'example.com', 'www.example.com' ] | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 |